You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2017/07/03 11:57:41 UTC

[01/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Repository: lucene-solr
Updated Branches:
  refs/heads/jira/solr-10879 c488daf7d -> 97ebecedb


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetExtrasCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetExtrasCloudTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetExtrasCloudTest.java
new file mode 100644
index 0000000..427b50d
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetExtrasCloudTest.java
@@ -0,0 +1,253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.common.util.NamedList;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class FieldFacetExtrasCloudTest extends AbstractAnalyticsFacetCloudTest {
+  public static final int INT = 21;
+  public static final int LONG = 22;
+  public static final int FLOAT = 23;
+  public static final int DOUBLE = 24;
+  public static final int DATE = 25;
+  public static final int STRING = 26;
+  public static final int NUM_LOOPS = 100;
+  
+  //INT
+  static ArrayList<ArrayList<Integer>> intLongTestStart; 
+  static ArrayList<ArrayList<Integer>> intFloatTestStart; 
+  static ArrayList<ArrayList<Integer>> intDoubleTestStart; 
+  static ArrayList<ArrayList<Integer>> intStringTestStart; 
+  
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    setupCluster();
+
+    //INT
+    intLongTestStart = new ArrayList<>();
+    intFloatTestStart = new ArrayList<>();
+    intDoubleTestStart = new ArrayList<>();
+    intStringTestStart = new ArrayList<>();
+
+    UpdateRequest req = new UpdateRequest();
+    
+    for (int j = 0; j < NUM_LOOPS; ++j) {
+      int i = j%INT;
+      long l = j%LONG;
+      float f = j%FLOAT;
+      double d = j%DOUBLE;
+      int dt = j%DATE;
+      int s = j%STRING;
+      
+      List<String> fields = new ArrayList<>();
+      fields.add("id"); fields.add("1000"+j);
+      fields.add("int_id"); fields.add("" + i);
+      fields.add("long_ld"); fields.add("" + l);
+      fields.add("float_fd"); fields.add("" + f);
+      fields.add("double_dd"); fields.add("" + d);
+      fields.add("date_dtd"); fields.add((1800+dt) + "-12-31T23:59:59.999Z");
+      fields.add("string_sd"); fields.add("abc" + s);
+      req.add(fields.toArray(new String[0]));
+      
+      //Long
+      if (j-LONG<0) {
+        ArrayList<Integer> list1 = new ArrayList<>();
+        list1.add(i);
+        intLongTestStart.add(list1);
+      } else {
+        intLongTestStart.get((int)l).add(i);
+      }
+      //String
+      if (j-FLOAT<0) {
+        ArrayList<Integer> list1 = new ArrayList<>();
+        list1.add(i);
+        intFloatTestStart.add(list1);
+      } else {
+        intFloatTestStart.get((int)f).add(i);
+      }
+      //String
+      if (j-DOUBLE<0) {
+        ArrayList<Integer> list1 = new ArrayList<>();
+        list1.add(i);
+        intDoubleTestStart.add(list1);
+      } else {
+        intDoubleTestStart.get((int)d).add(i);
+      }
+      //String
+      if (j-STRING<0) {
+        ArrayList<Integer> list1 = new ArrayList<>();
+        list1.add(i);
+        intStringTestStart.add(list1);
+      } else {
+        intStringTestStart.get(s).add(i);
+      }
+    }
+
+    req.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+  }
+  
+  @Test
+  public void limitTest() throws Exception { 
+    String[] params = new String[] {
+        "o.lr.s.mean", "mean(int_id)",
+        "o.lr.s.median", "median(int_id)",
+        "o.lr.s.count", "count(int_id)",
+        "o.lr.s.percentile_20", "percentile(20,int_id)",
+        "o.lr.ff.long_ld", "long_ld",
+        "o.lr.ff.long_ld.ss", "mean",
+        "o.lr.ff.long_ld.sd", "asc",
+        "o.lr.ff.long_ld.limit", "5",
+        "o.lr.ff.float_fd", "float_fd",
+        "o.lr.ff.float_fd.ss", "median",
+        "o.lr.ff.float_fd.sd", "desc",
+        "o.lr.ff.float_fd.limit", "3",
+        "o.lr.ff.double_dd", "double_dd",
+        "o.lr.ff.double_dd.ss", "count",
+        "o.lr.ff.double_dd.sd", "asc",
+        "o.lr.ff.double_dd.limit", "7",
+        "o.lr.ff.string_sd", "string_sd",
+        "o.lr.ff.string_sd.ss", "percentile_20",
+        "o.lr.ff.string_sd.sd", "desc",
+        "o.lr.ff.string_sd.limit", "1"
+    };
+    
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+
+    Collection<Double> lon = getValueList(response, "lr", "fieldFacets", "long_ld", "mean", false);
+    assertEquals(responseStr, lon.size(),5);
+    Collection<Double> flo = getValueList(response, "lr", "fieldFacets", "float_fd", "median", false);
+    assertEquals(responseStr, flo.size(),3);
+    Collection<Long> doub = getValueList(response, "lr", "fieldFacets", "double_dd", "count", false);
+    assertEquals(responseStr, doub.size(),7);
+    Collection<Integer> string = getValueList(response, "lr", "fieldFacets", "string_sd", "percentile_20", false);
+    assertEquals(responseStr, string.size(),1);
+  }
+  
+  @Test
+  public void offsetTest() throws Exception { 
+    String[] params = new String[] {
+        "o.offAll.s.mean", "mean(int_id)",
+        "o.offAll.ff", "long_ld",
+        "o.offAll.ff.long_ld.ss", "mean",
+        "o.offAll.ff.long_ld.sd", "asc",
+        "o.offAll.ff.long_ld.limit", "7",
+
+        "o.off0.s.mean", "mean(int_id)",
+        "o.off0.ff", "long_ld",
+        "o.off0.ff.long_ld.ss", "mean",
+        "o.off0.ff.long_ld.sd", "asc",
+        "o.off0.ff.long_ld.limit", "2",
+        "o.off0.ff.long_ld.offset", "0",
+
+        "o.off1.s.mean", "mean(int_id)",
+        "o.off1.ff", "long_ld",
+        "o.off1.ff.long_ld.ss", "mean",
+        "o.off1.ff.long_ld.sd", "asc",
+        "o.off1.ff.long_ld.limit", "2",
+        "o.off1.ff.long_ld.offset", "2",
+
+        "o.off2.s.mean", "mean(int_id)",
+        "o.off2.ff", "long_ld",
+        "o.off2.ff.long_ld.ss", "mean",
+        "o.off2.ff.long_ld.sd", "asc",
+        "o.off2.ff.long_ld.limit", "3",
+        "o.off2.ff.long_ld.offset", "4"
+    };
+    
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+
+    Collection<Double> lon;
+   
+    List<Double> all = new ArrayList<>();
+    lon = getValueList(response, "off0", "fieldFacets", "long_ld", "mean", false);
+    assertEquals(responseStr, lon.size(),2);
+    assertArrayEquals(new Double[]{ 1.5,  2.0 }, lon.toArray(new Double[0]));
+    all.addAll(lon);
+    
+    lon = getValueList(response, "off1", "fieldFacets", "long_ld", "mean", false);
+    assertEquals(responseStr, lon.size(),2);
+    assertArrayEquals(new Double[]{ 3.0,  4.0 }, lon.toArray(new Double[0]));
+    all.addAll(lon);
+    
+    lon = getValueList(response, "off2", "fieldFacets", "long_ld", "mean", false);
+    assertEquals(responseStr, lon.size(),3);
+    assertArrayEquals(new Double[]{ 5.0,  5.75, 6.0 }, lon.toArray(new Double[0]));
+    all.addAll(lon);
+    
+    lon = getValueList(response, "offAll", "fieldFacets", "long_ld", "mean", false);
+    assertEquals(responseStr, lon.size(),7);
+    assertArrayEquals(all.toArray(new Double[0]), lon.toArray(new Double[0]));
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void sortTest() throws Exception { 
+    String[] params = new String[] {
+        "o.sr.s.mean", "mean(int_id)",
+        "o.sr.s.median", "median(int_id)",
+        "o.sr.s.count", "count(int_id)",
+        "o.sr.s.percentile_20", "percentile(20,int_id)",
+        "o.sr.ff", "long_ld",
+        "o.sr.ff.long_ld.ss", "mean",
+        "o.sr.ff.long_ld.sd", "asc",
+        "o.sr.ff", "float_fd",
+        "o.sr.ff.float_fd.ss", "median",
+        "o.sr.ff.float_fd.sd", "desc",
+        "o.sr.ff", "double_dd",
+        "o.sr.ff.double_dd.ss", "count",
+        "o.sr.ff.double_dd.sd", "asc",
+        "o.sr.ff", "string_sd",
+        "o.sr.ff.string_sd.ss", "percentile_20",
+        "o.sr.ff.string_sd.sd", "desc"
+    };
+    
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    Collection<Double> lon = getValueList(response, "sr", "fieldFacets", "long_ld", "mean", false);
+    ArrayList<Double> longTest = calculateNumberStat(intLongTestStart, "mean");
+    Collections.sort(longTest);
+    assertEquals(responseStr, longTest,lon);
+    
+    Collection<Double> flo = getValueList(response, "sr", "fieldFacets", "float_fd", "median", false);
+    ArrayList<Double> floatTest = calculateNumberStat(intFloatTestStart, "median");
+    Collections.sort(floatTest,Collections.reverseOrder());
+    assertEquals(responseStr, floatTest,flo);
+    
+    Collection<Long> doub = getValueList(response, "sr", "fieldFacets", "double_dd", "count", false);
+    ArrayList<Long> doubleTest = (ArrayList<Long>)calculateStat(intDoubleTestStart, "count");
+    Collections.sort(doubleTest);
+    assertEquals(responseStr, doubleTest,doub);
+    
+    Collection<Integer> string = getValueList(response, "sr", "fieldFacets", "string_sd", "percentile_20", false);
+    ArrayList<Integer> stringTest = (ArrayList<Integer>)calculateStat(intStringTestStart, "perc_20");
+    Collections.sort(stringTest,Collections.reverseOrder());
+    assertEquals(responseStr, stringTest,string);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetExtrasTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetExtrasTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetExtrasTest.java
index fc7df4b..a7e0012 100644
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetExtrasTest.java
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetExtrasTest.java
@@ -26,7 +26,7 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class FieldFacetExtrasTest extends AbstractAnalyticsFacetTest {
-  static String fileName = "/analytics/requestFiles/fieldFacetExtras.txt";
+  static String fileName = "fieldFacetExtras.txt";
 
   public static final int INT = 21;
   public static final int LONG = 22;
@@ -44,7 +44,7 @@ public class FieldFacetExtrasTest extends AbstractAnalyticsFacetTest {
   
   @BeforeClass
   public static void beforeClass() throws Exception {
-    initCore("solrconfig-basic.xml","schema-analytics.xml");
+    initCore("solrconfig-analytics.xml","schema-analytics.xml");
     h.update("<delete><query>*:*</query></delete>");
 
     //INT
@@ -104,7 +104,6 @@ public class FieldFacetExtrasTest extends AbstractAnalyticsFacetTest {
     setResponse(h.query(request(fileToStringArr(FieldFacetExtrasTest.class, fileName))));
   }
   
-  @SuppressWarnings("unchecked")
   @Test
   public void limitTest() throws Exception { 
 
@@ -118,7 +117,6 @@ public class FieldFacetExtrasTest extends AbstractAnalyticsFacetTest {
     assertEquals(getRawResponse(), string.size(),1);
   }
   
-  @SuppressWarnings("unchecked")
   @Test
   public void offsetTest() throws Exception { 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetTest.java
index bf67213..59f4d88 100644
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetTest.java
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetTest.java
@@ -24,10 +24,11 @@ import java.util.List;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.w3c.dom.Node;
 
 
 public class FieldFacetTest extends AbstractAnalyticsFacetTest{
-  static String fileName = "/analytics/requestFiles/fieldFacets.txt";
+  static String fileName = "fieldFacets.txt";
 
   public static final int INT = 71;
   public static final int LONG = 36;
@@ -87,7 +88,7 @@ public class FieldFacetTest extends AbstractAnalyticsFacetTest{
   
   @BeforeClass
   public static void beforeClass() throws Exception {
-    initCore("solrconfig-basic.xml","schema-analytics.xml");
+    initCore("solrconfig-analytics.xml","schema-analytics.xml");
     h.update("<delete><query>*:*</query></delete>");
     
     defaults.put("int", new Integer(0));
@@ -478,46 +479,6 @@ public class FieldFacetTest extends AbstractAnalyticsFacetTest{
   
   @SuppressWarnings("unchecked")
   @Test
-  public void sumOfSquaresFacetAscTest() throws Exception {
-    //Int Date
-    Collection<Double> intDate = getDoubleList("sumOfSquares","fieldFacets", "date_dtd", "double", "int");
-    ArrayList<Double> intDateTest = calculateNumberStat(intDateTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(),intDate,intDateTest);
-    //Int String
-    Collection<Double> intString = getDoubleList("sumOfSquares","fieldFacets", "string_sd", "double", "int");
-    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(),intString,intStringTest);
-
-    //Long Date
-    Collection<Double> longDate = getDoubleList("sumOfSquares","fieldFacets", "date_dtd", "double", "long");
-    ArrayList<Double> longDateTest = calculateNumberStat(longDateTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(),longDate,longDateTest);
-    //Long String
-    Collection<Double> longString = getDoubleList("sumOfSquares","fieldFacets", "string_sd", "double", "long");
-    ArrayList<Double> longStringTest = calculateNumberStat(longStringTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(),longString,longStringTest);
-
-    //Float Date
-    Collection<Double> floatDate = getDoubleList("sumOfSquares","fieldFacets", "date_dtd", "double", "float");
-    ArrayList<Double> floatDateTest = calculateNumberStat(floatDateTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(),floatDate,floatDateTest);
-    //Float String
-    Collection<Double> floatString = getDoubleList("sumOfSquares","fieldFacets", "string_sd", "double", "float");
-    ArrayList<Double> floatStringTest = calculateNumberStat(floatStringTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(),floatString,floatStringTest);
-
-    //Double Date
-    Collection<Double> doubleDate = getDoubleList("sumOfSquares","fieldFacets", "date_dtd", "double", "double");
-    ArrayList<Double> doubleDateTest = calculateNumberStat(doubleDateTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(),doubleDate,doubleDateTest);
-    //Double String
-    Collection<Double> doubleString = getDoubleList("sumOfSquares","fieldFacets", "string_sd", "double", "double");
-    ArrayList<Double> doubleStringTest = calculateNumberStat(doubleStringTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(),doubleString,doubleStringTest);
-  }
-  
-  @SuppressWarnings("unchecked")
-  @Test
   public void stddevFacetAscTest() throws Exception { 
     //Int Date
     ArrayList<Double> intDate = getDoubleList("stddev","fieldFacets", "date_dtd", "double", "int");
@@ -1037,31 +998,33 @@ public class FieldFacetTest extends AbstractAnalyticsFacetTest{
   public void missingFacetTest() throws Exception { 
     //int MultiDate
     String xPath = "/response/lst[@name='stats']/lst[@name='missingf']/lst[@name='fieldFacets']/lst[@name='date_dtdm']/lst[@name='(MISSING)']";
-    assertNotNull(getRawResponse(), getNode(xPath));
+    Node missingNodeXPath = getNode(xPath);
+    assertNotNull(getRawResponse(), missingNodeXPath);
 
     ArrayList<Double> string = getDoubleList("missingf", "fieldFacets", "date_dtdm", "double", "mean");
-    string.remove(0);
+    //super.removeNodes(xPath, string);
     ArrayList<Double> stringTest = calculateNumberStat(multiDateTestStart, "mean");
     assertEquals(getRawResponse(), string,stringTest);
-    
+
     //Int String
     xPath = "/response/lst[@name='stats']/lst[@name='missingf']/lst[@name='fieldFacets']/lst[@name='string_sd']/lst[@name='(MISSING)']";
-    assertNotNull(getRawResponse(), getNode(xPath));
+    missingNodeXPath = getNode(xPath);
+    String missingNodeXPathStr = xPath;
+    assertNotNull(getRawResponse(), missingNodeXPath);
 
     xPath = "/response/lst[@name='stats']/lst[@name='missingf']/lst[@name='fieldFacets']/lst[@name='string_sd']/lst[@name='str0']";
     assertNull(getRawResponse(), getNode(xPath));
+
     List<Double> intString = getDoubleList("missingf", "fieldFacets", "string_sd", "double", "mean");
-    intString.remove(0);
+    //removeNodes(missingNodeXPathStr, intString);
     ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "mean");
     assertEquals(getRawResponse(), intString,intStringTest);
-    
+
     //Int Date
     Collection<Double> intDate = getDoubleList("missingf", "fieldFacets", "date_dtd", "double", "mean");
     ArrayList<ArrayList<Double>> intDateMissingTestStart = (ArrayList<ArrayList<Double>>) intDateTestStart.clone();
     ArrayList<Double> intDateTest = calculateNumberStat(intDateMissingTestStart, "mean");
     assertEquals(getRawResponse(),intDate,intDateTest);
-    
-    
   }
 
   private void checkStddevs(ArrayList<Double> list1, ArrayList<Double> list2) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/QueryFacetCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/QueryFacetCloudTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/QueryFacetCloudTest.java
new file mode 100644
index 0000000..42b5abe
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/QueryFacetCloudTest.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.common.util.NamedList;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class QueryFacetCloudTest extends AbstractAnalyticsFacetCloudTest {
+  private static final int INT = 71;
+  private static final int LONG = 36;
+  private static final int FLOAT = 93;
+  private static final int DOUBLE = 49;
+  private static final int DATE = 12;
+  private static final int STRING = 7;
+  private static final int NUM_LOOPS = 100;
+  
+  private static ArrayList<ArrayList<Integer>> int1TestStart = new ArrayList<>();
+  private static ArrayList<ArrayList<Integer>> int2TestStart = new ArrayList<>();
+  private static ArrayList<ArrayList<Long>> longTestStart = new ArrayList<>();
+  private static ArrayList<ArrayList<Float>> floatTestStart = new ArrayList<>();
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    setupCluster();
+    
+    //INT
+    int1TestStart.add(new ArrayList<Integer>());
+    int2TestStart.add(new ArrayList<Integer>());
+    
+    //LONG
+    longTestStart.add(new ArrayList<Long>());
+    longTestStart.add(new ArrayList<Long>());
+    
+    //FLOAT
+    floatTestStart.add(new ArrayList<Float>());
+    floatTestStart.add(new ArrayList<Float>());
+    floatTestStart.add(new ArrayList<Float>());
+
+    UpdateRequest req = new UpdateRequest();
+    
+    for (int j = 0; j < NUM_LOOPS; ++j) {
+      int i = j%INT;
+      long l = j%LONG;
+      float f = j%FLOAT;
+      double d = j%DOUBLE;
+      int dt = j%DATE;
+      int s = j%STRING;
+      
+      List<String> fields = new ArrayList<>();
+      fields.add("id"); fields.add("1000"+j);
+      fields.add("int_id"); fields.add("" + i);
+      fields.add("long_ld"); fields.add("" + l);
+      fields.add("float_fd"); fields.add("" + f);
+      fields.add("double_dd"); fields.add("" + d);
+      fields.add("date_dtd"); fields.add((1000+dt) + "-01-01T23:59:59Z");
+      fields.add("string_sd"); fields.add("abc" + s);
+      req.add(fields.toArray(new String[0]));
+      
+      if (f<=50) {
+        int1TestStart.get(0).add(i);
+      }
+      if (f<=30) {
+        int2TestStart.get(0).add(i);
+      }
+      if (s == 1) {
+        longTestStart.get(0).add(l);
+      }
+      if (s == 2) {
+        longTestStart.get(1).add(l);
+      }
+      if (l>=30) {
+        floatTestStart.get(0).add(f);
+      }
+      if (d<=50) {
+        floatTestStart.get(1).add(f);
+      }
+      if (l>=20) {
+        floatTestStart.get(2).add(f);
+      }
+    }
+
+    req.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void queryTest() throws Exception { 
+    String[] params = new String[] {
+        "o.ir.s.sum", "sum(int_id)",
+        "o.ir.s.mean", "mean(int_id)",
+        "o.ir.s.median", "median(int_id)",
+        "o.ir.s.percentile_8", "percentile(8,int_id)",
+        "o.ir.qf", "float1",
+        "o.ir.qf.float1.q", "float_fd:[* TO 50]",
+        "o.ir.qf", "float2",
+        "o.ir.qf.float2.q", "float_fd:[* TO 30]",
+
+        "o.lr.s.sum", "sum(long_ld)",
+        "o.lr.s.mean", "mean(long_ld)",
+        "o.lr.s.median", "median(long_ld)",
+        "o.lr.s.percentile_8", "percentile(8,long_ld)",
+        "o.lr.qf", "string",
+        "o.lr.qf.string.q", "string_sd:abc1",
+        "o.lr.qf.string.q", "string_sd:abc2",
+        
+        "o.fr.s.sum", "sum(float_fd)",
+        "o.fr.s.mean", "mean(float_fd)",
+        "o.fr.s.median", "median(float_fd)",
+        "o.fr.s.percentile_8", "percentile(8,float_fd)",
+        "o.fr.qf", "lad",
+        "o.fr.qf.lad.q", "long_ld:[20 TO *]",
+        "o.fr.qf.lad.q", "long_ld:[30 TO *]",
+        "o.fr.qf.lad.q", "double_dd:[* TO 50]"
+    };
+    
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int One
+    ArrayList<Double> int1 = getValueList(response, "ir", "queryFacets", "float1", "sum", false);
+    ArrayList<Double> int1Test = calculateNumberStat(int1TestStart, "sum");
+    assertEquals(responseStr, int1, int1Test);
+    //Int Two
+    ArrayList<Integer> int2 = getValueList(response, "ir", "queryFacets", "float2", "percentile_8", false);
+    ArrayList<Integer> int2Test = (ArrayList<Integer>)calculateStat(int2TestStart, "perc_8");
+    assertEquals(responseStr, int2, int2Test);
+
+    //Long
+    ArrayList<Double> long1 = getValueList(response, "lr", "queryFacets", "string", "median", false);
+    ArrayList<Double> long1Test = calculateNumberStat(longTestStart, "median");
+    assertEquals(responseStr,long1,long1Test);
+
+    //Float
+    ArrayList<Double> float1 = getValueList(response, "fr", "queryFacets", "lad", "mean", false);
+    ArrayList<Double> float1Test = calculateNumberStat(floatTestStart, "mean");
+    assertEquals(responseStr, float1, float1Test);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/QueryFacetTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/QueryFacetTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/QueryFacetTest.java
index f62a82b..e892dc9 100644
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/QueryFacetTest.java
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/QueryFacetTest.java
@@ -23,7 +23,7 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class QueryFacetTest extends AbstractAnalyticsFacetTest {
-  static String fileName = "/analytics/requestFiles/queryFacets.txt";
+  static String fileName = "queryFacets.txt";
 
   public final int INT = 71;
   public final int LONG = 36;
@@ -35,7 +35,7 @@ public class QueryFacetTest extends AbstractAnalyticsFacetTest {
 
   @BeforeClass
   public static void beforeClass() throws Exception {
-    initCore("solrconfig-basic.xml","schema-analytics.xml");
+    initCore("solrconfig-analytics.xml","schema-analytics.xml");
   }
 
   @SuppressWarnings("unchecked")
@@ -81,13 +81,13 @@ public class QueryFacetTest extends AbstractAnalyticsFacetTest {
       if (new Integer(s).toString().charAt(0)=='2') {
         longTestStart.get(1).add(l);
       }
-      if (l>=20) {
+      if (l>=30) {
         floatTestStart.get(0).add(f);
       }
-      if (l>=30) {
+      if (d<=50) {
         floatTestStart.get(1).add(f);
       }
-      if (d<=50) {
+      if (l>=20) {
         floatTestStart.get(2).add(f);
       }
       

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/RangeFacetCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/RangeFacetCloudTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/RangeFacetCloudTest.java
new file mode 100644
index 0000000..880324d
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/RangeFacetCloudTest.java
@@ -0,0 +1,588 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.common.util.NamedList;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+public class RangeFacetCloudTest extends AbstractAnalyticsFacetCloudTest{
+  public static final int INT = 71;
+  public static final int LONG = 36;
+  public static final int FLOAT = 93;
+  public static final int DOUBLE = 48;
+  public static final int DATE = 52;
+  public static final int STRING = 28;
+  public static final int NUM_LOOPS = 100;
+  
+  //INT
+  static ArrayList<ArrayList<Integer>> intLongTestStart; 
+  static ArrayList<ArrayList<Integer>> intDoubleTestStart; 
+  static ArrayList<ArrayList<Integer>> intDateTestStart; 
+  
+  //FLOAT
+  static ArrayList<ArrayList<Float>> floatLongTestStart; 
+  static ArrayList<ArrayList<Float>> floatDoubleTestStart; 
+  static ArrayList<ArrayList<Float>> floatDateTestStart; 
+  
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    setupCluster();
+    
+    //INT
+    intLongTestStart = new ArrayList<>();
+    intDoubleTestStart = new ArrayList<>();
+    intDateTestStart = new ArrayList<>();
+    
+    //FLOAT
+    floatLongTestStart = new ArrayList<>();
+    floatDoubleTestStart = new ArrayList<>();
+    floatDateTestStart = new ArrayList<>();
+
+    UpdateRequest req = new UpdateRequest();
+    
+    for (int j = 0; j < NUM_LOOPS; ++j) {
+      int i = j%INT;
+      long l = j%LONG;
+      float f = j%FLOAT;
+      double d = j%DOUBLE;
+      int dt = j%DATE;
+      int s = j%STRING;
+      
+      List<String> fields = new ArrayList<>();
+      fields.add("id"); fields.add("1000"+j);
+      fields.add("int_id"); fields.add("" + i);
+      fields.add("long_ld"); fields.add("" + l);
+      fields.add("float_fd"); fields.add("" + f);
+      fields.add("double_dd"); fields.add("" + d);
+      fields.add("date_dtd"); fields.add((1000+dt) + "-01-01T23:59:59Z");
+      fields.add("string_sd"); fields.add("abc" + s);
+      req.add(fields.toArray(new String[0]));
+      
+      //Longs
+      if (j-LONG<0) {
+        ArrayList<Integer> list1 = new ArrayList<>();
+        list1.add(i);
+        intLongTestStart.add(list1);
+        ArrayList<Float> list2 = new ArrayList<>();
+        list2.add(f);
+        floatLongTestStart.add(list2);
+      } else {
+        intLongTestStart.get((int)l).add(i);
+        floatLongTestStart.get((int)l).add(f);
+      }
+      //Doubles
+      if (j-DOUBLE<0) {
+        ArrayList<Integer> list1 = new ArrayList<>();
+        list1.add(i);
+        intDoubleTestStart.add(list1);
+        ArrayList<Float> list2 = new ArrayList<>();
+        list2.add(f);
+        floatDoubleTestStart.add(list2);
+      } else {
+        intDoubleTestStart.get((int)d).add(i);
+        floatDoubleTestStart.get((int)d).add(f);
+      }
+      //Dates
+      if (j-DATE<0) {
+        ArrayList<Integer> list1 = new ArrayList<>();
+        list1.add(i);
+        intDateTestStart.add(list1);
+        ArrayList<Float> list2 = new ArrayList<>();
+        list2.add(f);
+        floatDateTestStart.add(list2);
+      } else {
+        intDateTestStart.get(dt).add(i);
+        floatDateTestStart.get(dt).add(f);
+      }
+    }
+
+    req.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void rangeTest() throws Exception {
+    String[] params = new String[] {
+        "o.ri.s.sum", "sum(int_id)",
+        "o.ri.s.mean", "mean(int_id)",
+        "o.ri.s.median", "median(int_id)",
+        "o.ri.s.count", "count(int_id)",
+        "o.ri.rf", "long_ld",
+        "o.ri.rf.long_ld.st", "5",
+        "o.ri.rf.long_ld.e", "30",
+        "o.ri.rf.long_ld.g", "5",
+        "o.ri.rf.long_ld.ib", "lower",
+        "o.ri.rf.long_ld.or", "all",
+        "o.ri.rf", "double_dd",
+        "o.ri.rf.double_dd.st", "3",
+        "o.ri.rf.double_dd.e", "39",
+        "o.ri.rf.double_dd.g", "7",
+        "o.ri.rf.double_dd.ib", "upper",
+        "o.ri.rf.double_dd.ib", "outer",
+        "o.ri.rf.double_dd.or", "all",
+        "o.ri.rf", "date_dtd",
+        "o.ri.rf.date_dtd.st", "1007-01-01T23:59:59Z",
+        "o.ri.rf.date_dtd.e", "1044-01-01T23:59:59Z",
+        "o.ri.rf.date_dtd.g", "+7YEARS",
+        "o.ri.rf.date_dtd.ib", "lower",
+        "o.ri.rf.date_dtd.ib", "edge",
+        "o.ri.rf.date_dtd.ib", "outer",
+        "o.ri.rf.date_dtd.or", "all",
+
+        "o.rf.s.sum", "sum(float_fd)",
+        "o.rf.s.mean", "mean(float_fd)",
+        "o.rf.s.median", "median(float_fd)",
+        "o.rf.s.count", "count(float_fd)",
+        "o.rf.rf", "long_ld",
+        "o.rf.rf.long_ld.st", "0",
+        "o.rf.rf.long_ld.e", "29",
+        "o.rf.rf.long_ld.g", "4",
+        "o.rf.rf.long_ld.ib", "all",
+        "o.rf.rf.long_ld.or", "all",
+        "o.rf.rf", "double_dd",
+        "o.rf.rf.double_dd.st", "4",
+        "o.rf.rf.double_dd.e", "47",
+        "o.rf.rf.double_dd.g", "11",
+        "o.rf.rf.double_dd.ib", "edge",
+        "o.rf.rf.double_dd.or", "all",
+        "o.rf.rf", "date_dtd",
+        "o.rf.rf.date_dtd.st", "1004-01-01T23:59:59Z",
+        "o.rf.rf.date_dtd.e", "1046-01-01T23:59:59Z",
+        "o.rf.rf.date_dtd.g", "+5YEARS",
+        "o.rf.rf.date_dtd.ib", "upper",
+        "o.rf.rf.date_dtd.ib", "edge",
+        "o.rf.rf.date_dtd.or", "all"
+    };
+    
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Long
+    ArrayList<Long> intLong = getValueList(response, "ri", "rangeFacets", "long_ld", "count", false);
+    ArrayList<Long> intLongTest = calculateStat(transformLists(intLongTestStart, 5, 30, 5
+                                                        , false, true, false, false, false), "count");
+    assertEquals(responseStr, intLong,intLongTest);
+    //Int Double
+    ArrayList<Double> intDouble = getValueList(response, "ri", "rangeFacets", "double_dd", "mean", false);
+    ArrayList<Double> intDoubleTest = calculateNumberStat(transformLists(intDoubleTestStart, 3, 39, 7
+                                                          , false, false, true, false, true), "mean");
+    assertEquals(responseStr, intDouble,intDoubleTest);
+    //Int Date
+    ArrayList<Long> intDate = getValueList(response, "ri", "rangeFacets", "date_dtd", "count", false);
+    ArrayList<Long> intDateTest = (ArrayList<Long>)calculateStat(transformLists(intDateTestStart, 7, 44, 7
+                                                      , false, true, false, true, true), "count");
+    assertEquals(responseStr, intDate,intDateTest);
+    
+    //Float Long
+    ArrayList<Double> floatLong = getValueList(response, "rf", "rangeFacets", "long_ld", "median", false);
+    ArrayList<Double> floatLongTest = calculateNumberStat(transformLists(floatLongTestStart, 0, 29, 4
+                                                          , false, true, true, true, true), "median");
+    assertEquals(responseStr, floatLong,floatLongTest);
+    //Float Double
+    ArrayList<Long> floatDouble = getValueList(response, "rf", "rangeFacets", "double_dd", "count", false);
+    ArrayList<Long> floatDoubleTest = (ArrayList<Long>)calculateStat(transformLists(floatDoubleTestStart, 4, 47, 11
+                                                                     , false, false, false, true, false), "count");
+    assertEquals(responseStr, floatDouble,floatDoubleTest);
+  }
+  
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void hardendRangeTest() throws Exception {
+    String[] params = new String[] {
+        "o.hi.s.sum", "sum(int_id)",
+        "o.hi.s.mean", "mean(int_id)",
+        "o.hi.s.median", "median(int_id)",
+        "o.hi.s.count", "count(int_id)",
+        "o.hi.rf", "long_ld",
+        "o.hi.rf.long_ld.st", "5",
+        "o.hi.rf.long_ld.e", "30",
+        "o.hi.rf.long_ld.g", "5",
+        "o.hi.rf.long_ld.he", "true",
+        "o.hi.rf.long_ld.ib", "lower",
+        "o.hi.rf.long_ld.or", "all",
+        "o.hi.rf", "double_dd",
+        "o.hi.rf.double_dd.st", "3",
+        "o.hi.rf.double_dd.e", "39",
+        "o.hi.rf.double_dd.g", "7",
+        "o.hi.rf.double_dd.he", "true",
+        "o.hi.rf.double_dd.ib", "upper",
+        "o.hi.rf.double_dd.ib", "outer",
+        "o.hi.rf.double_dd.or", "all",
+        "o.hi.rf", "date_dtd",
+        "o.hi.rf.date_dtd.st", "1007-01-01T23:59:59Z",
+        "o.hi.rf.date_dtd.e", "1044-01-01T23:59:59Z",
+        "o.hi.rf.date_dtd.g", "+7YEARS",
+        "o.hi.rf.date_dtd.he", "true",
+        "o.hi.rf.date_dtd.ib", "lower",
+        "o.hi.rf.date_dtd.ib", "edge",
+        "o.hi.rf.date_dtd.ib", "outer",
+        "o.hi.rf.date_dtd.or", "all",
+
+        "o.hf.s.sum", "sum(float_fd)",
+        "o.hf.s.mean", "mean(float_fd)",
+        "o.hf.s.median", "median(float_fd)",
+        "o.hf.s.count", "count(float_fd)",
+        "o.hf.rf", "long_ld",
+        "o.hf.rf.long_ld.st", "0",
+        "o.hf.rf.long_ld.e", "29",
+        "o.hf.rf.long_ld.g", "4",
+        "o.hf.rf.long_ld.he", "true",
+        "o.hf.rf.long_ld.ib", "all",
+        "o.hf.rf.long_ld.or", "all",
+        "o.hf.rf", "double_dd",
+        "o.hf.rf.double_dd.st", "4",
+        "o.hf.rf.double_dd.e", "47",
+        "o.hf.rf.double_dd.g", "11",
+        "o.hf.rf.double_dd.he", "true",
+        "o.hf.rf.double_dd.ib", "edge",
+        "o.hf.rf.double_dd.or", "all",
+        "o.hf.rf", "date_dtd",
+        "o.hf.rf.date_dtd.st", "1004-01-01T23:59:59Z",
+        "o.hf.rf.date_dtd.e", "1046-01-01T23:59:59Z",
+        "o.hf.rf.date_dtd.g", "+5YEARS",
+        "o.hf.rf.date_dtd.he", "true",
+        "o.hf.rf.date_dtd.ib", "upper",
+        "o.hf.rf.date_dtd.ib", "edge",
+        "o.hf.rf.date_dtd.or", "all"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Long
+    ArrayList<Double> intLong = getValueList(response, "hi", "rangeFacets", "long_ld", "sum", false);
+    ArrayList<Double> intLongTest = calculateNumberStat(transformLists(intLongTestStart, 5, 30, 5
+                                                        , true, true, false, false, false), "sum");
+    assertEquals(responseStr, intLong,intLongTest);
+    //Int Double
+    ArrayList<Double> intDouble = getValueList(response, "hi", "rangeFacets", "double_dd", "mean", false);
+    ArrayList<Double> intDoubleTest = calculateNumberStat(transformLists(intDoubleTestStart, 3, 39, 7
+                                                          , true, false, true, false, true), "mean");
+    assertEquals(responseStr, intDouble,intDoubleTest);
+    //Int Date
+    ArrayList<Long> intDate = getValueList(response, "hi", "rangeFacets", "date_dtd", "count", false);
+    ArrayList<Long> intDateTest = (ArrayList<Long>)calculateStat(transformLists(intDateTestStart, 7, 44, 7
+                                                      , true, true, false, true, true), "count");
+    assertEquals(responseStr, intDate,intDateTest);
+    
+    //Float Long
+    ArrayList<Double> floatLong = getValueList(response, "hf", "rangeFacets", "long_ld", "median", false);
+    ArrayList<Double> floatLongTest = calculateNumberStat(transformLists(floatLongTestStart, 0, 29, 4
+                                                          , true, true, true, true, true), "median");
+    assertEquals(responseStr, floatLong,floatLongTest);
+    //Float Double
+    ArrayList<Long> floatDouble = getValueList(response, "hf", "rangeFacets", "double_dd", "count", false);
+    ArrayList<Long> floatDoubleTest = (ArrayList<Long>)calculateStat(transformLists(floatDoubleTestStart, 4, 47, 11
+                                                                     , true, false, false, true, false), "count");
+    assertEquals(responseStr, floatDouble,floatDoubleTest);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void multiGapTest() throws Exception {
+    String[] params = new String[] {
+        "o.mi.s.sum", "sum(int_id)",
+        "o.mi.s.mean", "mean(int_id)",
+        "o.mi.s.median", "median(int_id)",
+        "o.mi.s.count", "count(int_id)",
+        "o.mi.rf", "long_ld",
+        "o.mi.rf.long_ld.st", "5",
+        "o.mi.rf.long_ld.e", "30",
+        "o.mi.rf.long_ld.g", "4,2,6,3",
+        "o.mi.rf.long_ld.ib", "lower",
+        "o.mi.rf.long_ld.or", "all",
+        "o.mi.rf", "double_dd",
+        "o.mi.rf.double_dd.st", "3",
+        "o.mi.rf.double_dd.e", "39",
+        "o.mi.rf.double_dd.g", "3,1,7",
+        "o.mi.rf.double_dd.ib", "upper",
+        "o.mi.rf.double_dd.ib", "outer",
+        "o.mi.rf.double_dd.or", "all",
+        "o.mi.rf", "date_dtd",
+        "o.mi.rf.date_dtd.st", "1007-01-01T23:59:59Z",
+        "o.mi.rf.date_dtd.e", "1044-01-01T23:59:59Z",
+        "o.mi.rf.date_dtd.g", "+2YEARS,+7YEARS",
+        "o.mi.rf.date_dtd.ib", "lower",
+        "o.mi.rf.date_dtd.ib", "edge",
+        "o.mi.rf.date_dtd.ib", "outer",
+        "o.mi.rf.date_dtd.or", "all",
+
+        "o.mf.s.sum", "sum(float_fd)",
+        "o.mf.s.mean", "mean(float_fd)",
+        "o.mf.s.median", "median(float_fd)",
+        "o.mf.s.count", "count(float_fd)",
+        "o.mf.rf", "long_ld",
+        "o.mf.rf.long_ld.st", "0",
+        "o.mf.rf.long_ld.e", "29",
+        "o.mf.rf.long_ld.g", "1,4",
+        "o.mf.rf.long_ld.ib", "all",
+        "o.mf.rf.long_ld.or", "all",
+        "o.mf.rf", "double_dd",
+        "o.mf.rf.double_dd.st", "4",
+        "o.mf.rf.double_dd.e", "47",
+        "o.mf.rf.double_dd.g", "2,3,11",
+        "o.mf.rf.double_dd.ib", "edge",
+        "o.mf.rf.double_dd.or", "all",
+        "o.mf.rf", "date_dtd",
+        "o.mf.rf.date_dtd.st", "1004-01-01T23:59:59Z",
+        "o.mf.rf.date_dtd.e", "1046-01-01T23:59:59Z",
+        "o.mf.rf.date_dtd.g", "+4YEARS,+5YEARS",
+        "o.mf.rf.date_dtd.ib", "upper",
+        "o.mf.rf.date_dtd.ib", "edge",
+        "o.mf.rf.date_dtd.or", "all"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Long
+    ArrayList<Double> intLong = getValueList(response, "mi", "rangeFacets", "long_ld", "sum", false);
+    ArrayList<Double> intLongTest = calculateNumberStat(transformLists(intLongTestStart, 5, 30, "4,2,6,3"
+                                                        , false, true, false, false, false), "sum");
+    assertEquals(responseStr, intLong,intLongTest);
+    //Int Double
+    ArrayList<Double> intDouble = getValueList(response, "mi", "rangeFacets", "double_dd", "mean", false);
+    ArrayList<Double> intDoubleTest = calculateNumberStat(transformLists(intDoubleTestStart, 3, 39, "3,1,7"
+                                                          , false, false, true, false, true), "mean");
+    assertEquals(responseStr, intDouble,intDoubleTest);
+    //Int Date
+    ArrayList<Long> intDate = getValueList(response, "mi", "rangeFacets", "date_dtd", "count", false);
+    ArrayList<Long> intDateTest = (ArrayList<Long>)calculateStat(transformLists(intDateTestStart, 7, 44, "2,7"
+                                                      , false, true, false, true, true), "count");
+    assertEquals(responseStr, intDate,intDateTest);
+    
+    //Float Long
+    ArrayList<Double> floatLong = getValueList(response, "mf", "rangeFacets", "long_ld", "median", false);
+    ArrayList<Double> floatLongTest = calculateNumberStat(transformLists(floatLongTestStart, 0, 29, "1,4"
+                                                          , false, true, true, true, true), "median");;
+    assertEquals(responseStr, floatLong,floatLongTest);
+    //Float Double
+    ArrayList<Long> floatDouble = getValueList(response, "mf", "rangeFacets", "double_dd", "count", false);
+    ArrayList<Long> floatDoubleTest = (ArrayList<Long>)calculateStat(transformLists(floatDoubleTestStart, 4, 47, "2,3,11"
+                                                          , false, false, false, true, false), "count");
+    assertEquals(responseStr, floatDouble,floatDoubleTest);
+  }
+  
+  private <T> ArrayList<ArrayList<T>> transformLists(ArrayList<ArrayList<T>> listsStart, int start, int end, int gap
+      , boolean hardend, boolean incLow, boolean incUp, boolean incEdge, boolean incOut) {
+    int off = (end-start)%gap;
+    if (!hardend && off>0) {
+      end+=gap-off;
+    }
+
+    ArrayList<ArrayList<T>> lists = new ArrayList<>();
+    ArrayList<T> between = new ArrayList<>();
+    if (incLow && incUp) {
+      for (int i = start; i<end && i<listsStart.size(); i+=gap) {
+        ArrayList<T> list = new ArrayList<>();
+        for (int j = i; j<=i+gap && j<=end && j<listsStart.size(); j++) {
+          list.addAll(listsStart.get(j));
+        }
+        lists.add(list);
+      }
+      for (int i = start; i<listsStart.size() && i<=end; i++) {
+        between.addAll(listsStart.get(i));
+      }
+    } else if (incLow && !incUp) {
+      for (int i = start; i<end && i<listsStart.size(); i+=gap) {
+        ArrayList<T> list = new ArrayList<>();
+        for (int j = i; j<i+gap && j<end && j<listsStart.size(); j++) {
+          list.addAll(listsStart.get(j));
+        }
+        lists.add(list);
+      }
+      for (int i = start; i<listsStart.size() && i<end; i++) {
+        between.addAll(listsStart.get(i));
+      }
+    } else if (!incLow && incUp) {
+      for (int i = start; i<end && i<listsStart.size(); i+=gap) {
+        ArrayList<T> list = new ArrayList<>();
+        for (int j = i+1; j<=i+gap && j<=end && j<listsStart.size(); j++) {
+          list.addAll(listsStart.get(j));
+        }
+        lists.add(list);
+      }
+      for (int i = start+1; i<listsStart.size() && i<=end; i++) {
+        between.addAll(listsStart.get(i));
+      }
+    } else {
+      for (int i = start; i<end && i<listsStart.size(); i+=gap) {
+        ArrayList<T> list = new ArrayList<>();
+        for (int j = i+1; j<i+gap && j<end && j<listsStart.size(); j++) {
+          list.addAll(listsStart.get(j));
+        }
+        lists.add(list);
+      }
+      for (int i = start+1; i<listsStart.size() && i<end; i++) {
+        between.addAll(listsStart.get(i));
+      }
+    }
+    
+    if (incEdge && !incLow && start>=0) {
+      lists.get(0).addAll(listsStart.get(start));
+      between.addAll(listsStart.get(start));
+    }
+    if (incEdge && !incUp && end<listsStart.size()) {
+      lists.get(lists.size()-1).addAll(listsStart.get(end));
+      between.addAll(listsStart.get(end));
+    }
+    ArrayList<T> before = new ArrayList<>();
+    ArrayList<T> after = new ArrayList<>();
+    if (incOut || !(incLow||incEdge)) {
+      for (int i = 0; i<=start; i++) {
+        before.addAll(listsStart.get(i));
+      }
+    } else {
+      for (int i = 0; i<start; i++) {
+        before.addAll(listsStart.get(i));
+      }
+    }
+    if (incOut || !(incUp||incEdge)) {
+      for (int i = end; i<listsStart.size(); i++) {
+        after.addAll(listsStart.get(i));
+      }
+    } 
+    else {
+      for (int i = end+1; i<listsStart.size(); i++) {
+        after.addAll(listsStart.get(i));
+      }
+    }
+    lists.add(before);
+    lists.add(after);
+    lists.add(between);
+    return lists;
+  }
+  
+  private <T> ArrayList<ArrayList<T>> transformLists(ArrayList<ArrayList<T>> listsStart, int start, int end, String gapString
+      , boolean hardend, boolean incLow, boolean incUp, boolean incEdge, boolean incOut) {
+    String[] stringGaps = gapString.split(",");
+    int[] gaps = new int[stringGaps.length];
+    for (int i = 0; i<gaps.length; i++) {
+      gaps[i] = Integer.parseInt(stringGaps[i]);
+    }
+    int bigGap = 0;
+    int last = gaps[gaps.length-1];
+    for (int i = 0; i<gaps.length-1; i++) {
+      bigGap += gaps[i];
+    }
+    int off = (end-start-bigGap)%last;
+    if (!hardend && off>0) {
+      end+=last-off;
+    }
+    
+    ArrayList<ArrayList<T>> lists = new ArrayList<>();
+    ArrayList<T> between = new ArrayList<>();
+    int gap = 0;
+    int gapCounter = 0;
+    if (incLow && incUp) {
+      for (int i = start; i<end && i<listsStart.size(); i+=gap) {
+        if (gapCounter<gaps.length) {
+          gap = gaps[gapCounter++];
+        }
+        ArrayList<T> list = new ArrayList<>();
+        for (int j = i; j<=i+gap && j<=end && j<listsStart.size(); j++) {
+          list.addAll(listsStart.get(j));
+        }
+        lists.add(list);
+      }
+      for (int i = start; i<listsStart.size() && i<=end; i++) {
+        between.addAll(listsStart.get(i));
+      }
+    } else if (incLow && !incUp) {
+      for (int i = start; i<end && i<listsStart.size(); i+=gap) {
+        if (gapCounter<gaps.length) {
+          gap = gaps[gapCounter++];
+        }
+        ArrayList<T> list = new ArrayList<>();
+        for (int j = i; j<i+gap && j<end && j<listsStart.size(); j++) {
+          list.addAll(listsStart.get(j));
+        }
+        lists.add(list);
+      }
+      for (int i = start; i<listsStart.size() && i<end; i++) {
+        between.addAll(listsStart.get(i));
+      }
+    } else if (!incLow && incUp) {
+      for (int i = start; i<end && i<listsStart.size(); i+=gap) {
+        if (gapCounter<gaps.length) {
+          gap = gaps[gapCounter++];
+        }
+        ArrayList<T> list = new ArrayList<>();
+        for (int j = i+1; j<=i+gap && j<=end && j<listsStart.size(); j++) {
+          list.addAll(listsStart.get(j));
+        }
+        lists.add(list);
+      }
+      for (int i = start+1; i<listsStart.size() && i<=end; i++) {
+        between.addAll(listsStart.get(i));
+      }
+    } else {
+      for (int i = start; i<end && i<listsStart.size(); i+=gap) {
+        if (gapCounter<gaps.length) {
+          gap = gaps[gapCounter++];
+        }
+        ArrayList<T> list = new ArrayList<>();
+        for (int j = i+1; j<i+gap && j<end && j<listsStart.size(); j++) {
+          list.addAll(listsStart.get(j));
+        }
+        lists.add(list);
+      }
+      for (int i = start+1; i<listsStart.size() && i<end; i++) {
+        between.addAll(listsStart.get(i));
+      }
+    }
+    
+    if (incEdge && !incLow && start>=0) {
+      lists.get(0).addAll(listsStart.get(start));
+      between.addAll(listsStart.get(start));
+    }
+    if (incEdge && !incUp && end<listsStart.size()) {
+      lists.get(lists.size()-1).addAll(listsStart.get(end));
+      between.addAll(listsStart.get(end));
+    }
+    ArrayList<T> before = new ArrayList<>();
+    ArrayList<T> after = new ArrayList<>();
+    if (incOut || !(incLow||incEdge)) {
+      for (int i = 0; i<=start; i++) {
+        before.addAll(listsStart.get(i));
+      }
+    } else {
+      for (int i = 0; i<start; i++) {
+        before.addAll(listsStart.get(i));
+      }
+    }
+    if (incOut || !(incUp||incEdge)) {
+      for (int i = end; i<listsStart.size(); i++) {
+        after.addAll(listsStart.get(i));
+      }
+    } 
+    else {
+      for (int i = end+1; i<listsStart.size(); i++) {
+        after.addAll(listsStart.get(i));
+      }
+    }
+    lists.add(before);
+    lists.add(after);
+    lists.add(between);
+    return lists;
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/RangeFacetTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/RangeFacetTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/RangeFacetTest.java
index cda8202..24a7ea2 100644
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/RangeFacetTest.java
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/RangeFacetTest.java
@@ -24,7 +24,7 @@ import org.junit.Test;
 
 
 public class RangeFacetTest extends AbstractAnalyticsFacetTest {
-  static String fileName = "/analytics/requestFiles/rangeFacets.txt";
+  static String fileName = "rangeFacets.txt";
 
   public static final int INT = 71;
   public static final int LONG = 36;
@@ -46,7 +46,7 @@ public class RangeFacetTest extends AbstractAnalyticsFacetTest {
   
   @BeforeClass
   public static void beforeClass() throws Exception {
-    initCore("solrconfig-basic.xml","schema-analytics.xml");
+    initCore("solrconfig-analytics.xml","schema-analytics.xml");
     h.update("<delete><query>*:*</query></delete>");
     
     //INT
@@ -145,11 +145,6 @@ public class RangeFacetTest extends AbstractAnalyticsFacetTest {
     ArrayList<Long> floatDoubleTest = (ArrayList<Long>)calculateStat(transformLists(floatDoubleTestStart, 4, 47, 11
                                                                      , false, false, false, true, false), "count");
     assertEquals(getRawResponse(), floatDouble,floatDoubleTest);
-    //Float Date                      
-    ArrayList<Double> floatDate = getDoubleList("rf", "rangeFacets", "date_dtd", "double", "sumOfSquares");
-    ArrayList<Double> floatDateTest = calculateNumberStat(transformLists(floatDateTestStart, 4, 46, 5
-                                                          , false, false, true, true, false), "sumOfSquares");
-    assertEquals(getRawResponse(), floatDate,floatDateTest);
   }
   
 
@@ -182,11 +177,6 @@ public class RangeFacetTest extends AbstractAnalyticsFacetTest {
     ArrayList<Long> floatDoubleTest = (ArrayList<Long>)calculateStat(transformLists(floatDoubleTestStart, 4, 47, 11
                                                                      , true, false, false, true, false), "count");
     assertEquals(getRawResponse(), floatDouble,floatDoubleTest);
-    //Float Date                      
-    ArrayList<Double> floatDate = getDoubleList("hf", "rangeFacets", "date_dtd", "double", "sumOfSquares");
-    ArrayList<Double> floatDateTest = calculateNumberStat(transformLists(floatDateTestStart, 4, 46, 5
-                                                          , true, false, true, true, false), "sumOfSquares");
-    assertEquals(getRawResponse(), floatDate,floatDateTest);
   }
   
   @SuppressWarnings("unchecked")
@@ -218,11 +208,6 @@ public class RangeFacetTest extends AbstractAnalyticsFacetTest {
     ArrayList<Long> floatDoubleTest = (ArrayList<Long>)calculateStat(transformLists(floatDoubleTestStart, 4, 47, "2,3,11"
                                                           , false, false, false, true, false), "count");
     assertEquals(getRawResponse(), floatDouble,floatDoubleTest);
-    //Float Date                      
-    ArrayList<Double> floatDate = getDoubleList("mf", "rangeFacets", "date_dtd", "double", "sumOfSquares");
-    ArrayList<Double> floatDateTest = calculateNumberStat(transformLists(floatDateTestStart, 4, 46, "4,5"
-                                                          , false, false, true, true, false), "sumOfSquares");
-    assertEquals(getRawResponse(), floatDate,floatDateTest);
   }
   
   private <T> ArrayList<ArrayList<T>> transformLists(ArrayList<ArrayList<T>> listsStart, int start, int end, int gap
@@ -309,15 +294,9 @@ public class RangeFacetTest extends AbstractAnalyticsFacetTest {
         after.addAll(listsStart.get(i));
       }
     }
-    if (before.size()>0) {
-      lists.add(before);
-    }
-    if (after.size()>0) {
-      lists.add(after);
-    }
-    if (between.size()>0) {
-      lists.add(between);
-    }
+    lists.add(before);
+    lists.add(after);
+    lists.add(between);
     return lists;
   }
   
@@ -429,15 +408,9 @@ public class RangeFacetTest extends AbstractAnalyticsFacetTest {
         after.addAll(listsStart.get(i));
       }
     }
-    if (before.size()>0) {
-      lists.add(before);
-    }
-    if (after.size()>0) {
-      lists.add(after);
-    }
-    if (between.size()>0) {
-      lists.add(between);
-    }
+    lists.add(before);
+    lists.add(after);
+    lists.add(between);
     return lists;
   }
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/util/valuesource/FunctionTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/util/valuesource/FunctionTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/util/valuesource/FunctionTest.java
deleted file mode 100644
index 5981cc0..0000000
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/util/valuesource/FunctionTest.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-
-import org.apache.solr.analytics.AbstractAnalyticsStatsTest;
-import org.apache.solr.analytics.facet.AbstractAnalyticsFacetTest;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-public class FunctionTest extends AbstractAnalyticsStatsTest {
-  static String fileName = "/analytics/requestFiles/functions.txt";
-
-  static public final int INT = 71;
-  static public final int LONG = 36;
-  static public final int FLOAT = 93;
-  static public final int DOUBLE = 49;
-  static public final int DATE = 12;
-  static public final int STRING = 28;
-  static public final int NUM_LOOPS = 100;
-
-  @BeforeClass
-  public static void beforeClass() throws Exception {
-    initCore("solrconfig-basic.xml","schema-analytics.xml");
-    h.update("<delete><query>*:*</query></delete>");
-    
-    for (int j = 0; j < NUM_LOOPS; ++j) {
-      int i = j%INT+1;
-      long l = j%LONG+1;
-      float f = j%FLOAT+1;
-      double d = j%DOUBLE+1;
-      double d0 = j%DOUBLE;
-      String dt = (1800+j%DATE) + "-06-30T23:59:59Z";
-      String s = "str" + (j%STRING);
-
-      double add_if = (double)i+f;
-      double add_ldf = (double)l+d+f;
-      double mult_if = (double)i*f;
-      double mult_ldf = (double)l*d*f;
-      double div_if = (double)i/f;
-      double div_ld = (double)l/d;
-      double pow_if = Math.pow(i,f);
-      double pow_ld = Math.pow(l,d);
-      double neg_i = (double)i*-1;
-      double neg_l = (double)l*-1;
-      String dm_2y = (1802+j%DATE) + "-06-30T23:59:59Z";
-      String dm_2m = (1800+j%DATE) + "-08-30T23:59:59Z";
-      String concat_first = "this is the first"+s;
-      String concat_second = "this is the second"+s;
-      String rev = new StringBuilder(s).reverse().toString();
-      
-      assertU(adoc(AbstractAnalyticsFacetTest.filter("id", "1000" + j, "int_id", "" + i, "long_ld", "" + l, "float_fd", "" + f, 
-            "double_dd", "" + d,  "date_dtd", dt, "string_sd", s,
-            "add_if_dd", ""+add_if, "add_ldf_dd", ""+add_ldf, "mult_if_dd", ""+mult_if, "mult_ldf_dd", ""+mult_ldf,
-            "div_if_dd", ""+div_if, "div_ld_dd", ""+div_ld, "pow_if_dd", ""+pow_if, "pow_ld_dd", ""+pow_ld,
-            "neg_i_dd", ""+neg_i, "neg_l_dd", ""+neg_l, "const_8_dd", "8", "const_10_dd", "10", "dm_2y_dtd", dm_2y, "dm_2m_dtd", dm_2m,
-            "const_00_dtd", "1800-06-30T23:59:59Z", "const_04_dtd", "1804-06-30T23:59:59Z", "const_first_sd", "this is the first", "const_second_sd", "this is the second",
-            "concat_first_sd", concat_first, "concat_second_sd", concat_second, "rev_sd", rev, "miss_dd", ""+d0 )));
-      
-      
-      if (usually()) {
-        assertU(commit()); // to have several segments
-      }
-    }
-    
-    assertU(commit()); 
-    
-    setResponse(h.query(request(fileToStringArr(FunctionTest.class, fileName))));
-  }
-      
-  @Test
-  public void addTest() throws Exception { 
-    double result = (Double)getStatResult("ar", "sum", VAL_TYPE.DOUBLE);
-    double calculated = (Double)getStatResult("ar", "sumc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(), result, calculated, 0.0);
-    // TODO checfk why asserted 2times
-    assertEquals(getRawResponse(), result, calculated, 0.0);
-
-    result = (Double)getStatResult("ar", "mean", VAL_TYPE.DOUBLE);
-    calculated = (Double)getStatResult("ar", "meanc", VAL_TYPE.DOUBLE);
-    assertTrue(result==calculated);
-    assertEquals(getRawResponse(), result, calculated, 0.0);
-  }
-  
-  @Test
-  public void multiplyTest() throws Exception { 
-    double result = (Double)getStatResult("mr", "sum", VAL_TYPE.DOUBLE);
-    double calculated = (Double)getStatResult("mr", "sumc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(),  result, calculated, 0.0);
-    
-    result = (Double)getStatResult("mr", "mean", VAL_TYPE.DOUBLE);
-    calculated = (Double)getStatResult("mr", "meanc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(),  result, calculated, 0.0);
-  }
-  
-  @Test
-  public void divideTest() throws Exception { 
-    Double result = (Double)getStatResult("dr", "sum", VAL_TYPE.DOUBLE);
-    Double calculated = (Double)getStatResult("dr", "sumc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(),  result, calculated, 0.0);
-    
-    result = (Double)getStatResult("dr", "mean", VAL_TYPE.DOUBLE);
-    calculated = (Double)getStatResult("dr", "meanc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(),  result, calculated, 0.0);
-  }
-  
-  @Test
-  public void powerTest() throws Exception { 
-    double result = (Double)getStatResult("pr", "sum", VAL_TYPE.DOUBLE);
-    double calculated = (Double)getStatResult("pr", "sumc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(), result, calculated, 0.0);
-    assertEquals(getRawResponse(),  result, calculated, 0.0);
-    
-    result = (Double)getStatResult("pr", "mean", VAL_TYPE.DOUBLE);
-    calculated = (Double)getStatResult("pr", "meanc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(), result, calculated, 0.0);
-    assertEquals(getRawResponse(), result, calculated, 0.0);
-  }
-  
-  @Test
-  public void negateTest() throws Exception { 
-    double result = (Double)getStatResult("nr", "sum", VAL_TYPE.DOUBLE);
-    double calculated = (Double)getStatResult("nr", "sumc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(),  result, calculated, 0.0);
-    
-    result = (Double)getStatResult("nr", "mean", VAL_TYPE.DOUBLE);
-    calculated = (Double)getStatResult("nr", "meanc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(),  result, calculated, 0.0);
-  }
-
-  @Test 
-  public void absoluteValueTest() throws Exception {
-    double result = (Double)getStatResult("avr", "sum", VAL_TYPE.DOUBLE);
-    double calculated = (Double)getStatResult("avr", "sumc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(),  result, calculated, 0.0);
-    
-    result = (Double)getStatResult("avr", "mean", VAL_TYPE.DOUBLE);
-    calculated = (Double)getStatResult("avr", "meanc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(),  result, calculated, 0.0);
-  }
-  
-  @Test
-  public void constantNumberTest() throws Exception { 
-    double result = (Double)getStatResult("cnr", "sum", VAL_TYPE.DOUBLE);
-    double calculated = (Double)getStatResult("cnr", "sumc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(), result, calculated, 0.0);
-    assertEquals(getRawResponse(), result, calculated, 0.0);
-    
-    result = (Double)getStatResult("cnr", "mean", VAL_TYPE.DOUBLE);
-    calculated = (Double)getStatResult("cnr", "meanc", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(), result, calculated, 0.0);
-    assertEquals(getRawResponse(),  result, calculated, 0.0);
-  }
-  
-  @Test
-  public void dateMathTest() throws Exception {
-    String result = (String)getStatResult("dmr", "median", VAL_TYPE.DATE);
-    String calculated = (String)getStatResult("dmr", "medianc", VAL_TYPE.DATE);
-    assertEquals(getRawResponse(), result, calculated);
-    
-    result = (String)getStatResult("dmr", "max", VAL_TYPE.DATE);
-    calculated = (String)getStatResult("dmr", "maxc", VAL_TYPE.DATE);
-    assertEquals(getRawResponse(), result, calculated);
-  }
-  
-  @Test
-  public void constantDateTest() throws Exception { 
-    String result = (String)getStatResult("cdr", "median", VAL_TYPE.DATE);
-    String calculated = (String)getStatResult("cdr", "medianc", VAL_TYPE.DATE);
-    assertEquals(getRawResponse(), result, calculated);
-    assertEquals(getRawResponse(), result, calculated);
-    
-    result = (String)getStatResult("cdr", "max", VAL_TYPE.DATE);
-    calculated = (String)getStatResult("cdr", "maxc", VAL_TYPE.DATE);
-    assertEquals(getRawResponse(), result, calculated);
-  }
-  
-  @Test
-  public void constantStringTest() throws Exception { 
-    String result = (String)getStatResult("csr", "min", VAL_TYPE.STRING);
-    String calculated = (String)getStatResult("csr", "minc", VAL_TYPE.STRING);
-    assertEquals(getRawResponse(), result, calculated);
-    
-    result = (String)getStatResult("csr", "max", VAL_TYPE.STRING);
-    calculated = (String)getStatResult("csr", "maxc", VAL_TYPE.STRING);
-    assertEquals(getRawResponse(), result, calculated);
-  }
-  
-  @Test
-  public void concatenateTest() throws Exception { 
-    String result = (String)getStatResult("cr", "min", VAL_TYPE.STRING);
-    String calculated = (String)getStatResult("cr", "minc", VAL_TYPE.STRING);
-    assertEquals(getRawResponse(), result, calculated);
-    
-    result = (String)getStatResult("cr", "max", VAL_TYPE.STRING);
-    calculated = (String)getStatResult("cr", "maxc", VAL_TYPE.STRING);
-    assertEquals(getRawResponse(), result, calculated);
-  }
-  
-  @Test
-  public void reverseTest() throws Exception { 
-    String result = (String)getStatResult("rr", "min", VAL_TYPE.STRING);
-    String calculated = (String)getStatResult("rr", "minc", VAL_TYPE.STRING);
-    assertEquals(getRawResponse(), result, calculated);
-    
-    result = (String)getStatResult("rr", "max", VAL_TYPE.STRING);
-    calculated = (String)getStatResult("rr", "maxc", VAL_TYPE.STRING);
-    assertEquals(getRawResponse(), result, calculated);
-  }
-  
-  @Test
-  public void missingTest() throws Exception { 
-    double min = (Double)getStatResult("ms", "min", VAL_TYPE.DOUBLE);
-    double max = (Double)getStatResult("ms", "max", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(), 48.0d, max, 0.0);
-    assertEquals(getRawResponse(), 1.0d, min, 0.0);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java b/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
index e5eaff9..8e9477b 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
@@ -60,6 +60,7 @@ public class ResponseBuilder
   public boolean doExpand;
   public boolean doStats;
   public boolean doTerms;
+  public boolean doAnalytics;
   public MergeStrategy mergeFieldHandler;
 
   private boolean needDocList = false;
@@ -173,6 +174,8 @@ public class ResponseBuilder
   StatsInfo _statsInfo;
   TermsComponent.TermsHelper _termsHelper;
   SimpleOrderedMap<List<NamedList<Object>>> _pivots;
+  Object _analyticsRequestManager;
+  boolean _isOlapAnalytics;
 
   // Context fields for grouping
   public final Map<String, Collection<SearchGroup<BytesRef>>> mergedSearchGroups = new HashMap<>();


[45/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-1095: Refactor code to standardize replica assignment

Posted by ab...@apache.org.
SOLR-1095: Refactor code to standardize replica assignment


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/15118d40
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/15118d40
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/15118d40

Branch: refs/heads/jira/solr-10879
Commit: 15118d40c55774df8da6663b38dcc956651cfa04
Parents: 196d84b
Author: Noble Paul <no...@apache.org>
Authored: Fri Jun 30 15:50:23 2017 +0930
Committer: Noble Paul <no...@apache.org>
Committed: Fri Jun 30 15:50:23 2017 +0930

----------------------------------------------------------------------
 .../cloud/OverseerCollectionMessageHandler.java | 90 --------------------
 1 file changed, 90 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/15118d40/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java b/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
index c6051d7..600e6da 100644
--- a/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
+++ b/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
@@ -19,7 +19,6 @@ package org.apache.solr.cloud;
 import java.io.Closeable;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -37,16 +36,12 @@ import com.google.common.collect.ImmutableMap;
 import org.apache.commons.lang.StringUtils;
 import org.apache.solr.client.solrj.SolrResponse;
 import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.cloud.autoscaling.Policy;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.impl.HttpSolrClient.RemoteSolrException;
 import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.response.UpdateResponse;
 import org.apache.solr.cloud.overseer.OverseerAction;
-import org.apache.solr.cloud.rule.ReplicaAssigner;
-import org.apache.solr.cloud.rule.ReplicaAssigner.Position;
-import org.apache.solr.cloud.rule.Rule;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.cloud.ClusterState;
@@ -93,7 +88,6 @@ import static org.apache.solr.common.cloud.ZkStateReader.PROPERTY_VALUE_PROP;
 import static org.apache.solr.common.cloud.ZkStateReader.REJOIN_AT_HEAD_PROP;
 import static org.apache.solr.common.cloud.ZkStateReader.REPLICA_PROP;
 import static org.apache.solr.common.cloud.ZkStateReader.SHARD_ID_PROP;
-import static org.apache.solr.common.cloud.ZkStateReader.SOLR_AUTOSCALING_CONF_PATH;
 import static org.apache.solr.common.params.CollectionParams.CollectionAction.*;
 import static org.apache.solr.common.params.CommonAdminParams.ASYNC;
 import static org.apache.solr.common.params.CommonParams.NAME;
@@ -632,30 +626,6 @@ public class OverseerCollectionMessageHandler implements OverseerMessageHandler
     }
   }
 
-  static List<String> getLiveOrLiveAndCreateNodeSetList(final Set<String> liveNodes, final ZkNodeProps message, final Random random) {
-    // TODO: add smarter options that look at the current number of cores per
-    // node?
-    // for now we just go random (except when createNodeSet and createNodeSet.shuffle=false are passed in)
-
-    List<String> nodeList;
-
-    final String createNodeSetStr = message.getStr(CREATE_NODE_SET);
-    final List<String> createNodeList = (createNodeSetStr == null)?null:StrUtils.splitSmart((CREATE_NODE_SET_EMPTY.equals(createNodeSetStr)?"":createNodeSetStr), ",", true);
-
-    if (createNodeList != null) {
-      nodeList = new ArrayList<>(createNodeList);
-      nodeList.retainAll(liveNodes);
-      if (message.getBool(CREATE_NODE_SET_SHUFFLE, CREATE_NODE_SET_SHUFFLE_DEFAULT)) {
-        Collections.shuffle(nodeList, random);
-      }
-    } else {
-      nodeList = new ArrayList<>(liveNodes);
-      Collections.shuffle(nodeList, random);
-    }
-
-    return nodeList;
-  }
-
 
   private void modifyCollection(ClusterState clusterState, ZkNodeProps message, NamedList results)
       throws KeeperException, InterruptedException {
@@ -704,66 +674,6 @@ public class OverseerCollectionMessageHandler implements OverseerMessageHandler
     commandMap.get(DELETE).call(zkStateReader.getClusterState(), new ZkNodeProps(props), results);
   }
 
-  Map<Position, String> identifyNodes(ClusterState clusterState,
-                                      List<String> nodeList,
-                                      String collectionName,
-                                      ZkNodeProps message,
-                                      List<String> shardNames,
-                                      int numNrtReplicas, 
-                                      int numTlogReplicas,
-                                      int numPullReplicas) throws KeeperException, InterruptedException {
-    List<Map> rulesMap = (List) message.get("rule");
-    String policyName = message.getStr(POLICY);
-    Map autoScalingJson = Utils.getJson(zkStateReader.getZkClient(), SOLR_AUTOSCALING_CONF_PATH, true);
-
-    if (rulesMap == null && policyName == null) {
-      int i = 0;
-      Map<Position, String> result = new HashMap<>();
-      for (String aShard : shardNames) {
-        for (int j = 0; j < numNrtReplicas; j++){
-          result.put(new Position(aShard, j, Replica.Type.NRT), nodeList.get(i % nodeList.size()));
-          i++;
-        }
-        for (int j = 0; j < numTlogReplicas; j++){
-          result.put(new Position(aShard, j, Replica.Type.TLOG), nodeList.get(i % nodeList.size()));
-          i++;
-        }
-        for (int j = 0; j < numPullReplicas; j++){
-          result.put(new Position(aShard, j, Replica.Type.PULL), nodeList.get(i % nodeList.size()));
-          i++;
-        }
-      }
-      return result;
-    } else {
-      if (numTlogReplicas + numPullReplicas != 0) {
-        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
-            Replica.Type.TLOG + " or " + Replica.Type.PULL + " replica types not supported with placement rules or cluster policies");
-      }
-    }
-
-    if (policyName != null || autoScalingJson.get(Policy.CLUSTER_POLICY) != null) {
-      return Assign.getPositionsUsingPolicy(collectionName,
-          shardNames, numNrtReplicas, policyName, zkStateReader, nodeList);
-
-    } else {
-      List<Rule> rules = new ArrayList<>();
-      for (Object map : rulesMap) rules.add(new Rule((Map) map));
-
-      Map<String, Integer> sharVsReplicaCount = new HashMap<>();
-
-      for (String shard : shardNames) sharVsReplicaCount.put(shard, numNrtReplicas);
-      ReplicaAssigner replicaAssigner = new ReplicaAssigner(rules,
-          sharVsReplicaCount,
-          (List<Map>) message.get(SNITCH),
-          new HashMap<>(),//this is a new collection. So, there are no nodes in any shard
-          nodeList,
-          overseer.getZkController().getCoreContainer(),
-          clusterState);
-
-      return replicaAssigner.getNodeMappings();
-    }
-  }
-
   Map<String, Replica> waitToSeeReplicasInState(String collectionName, Collection<String> coreNames) throws InterruptedException {
     Map<String, Replica> result = new HashMap<>();
     TimeOut timeout = new TimeOut(30, TimeUnit.SECONDS);


[53/58] [abbrv] lucene-solr:jira/solr-10879: LUCENE-5822: Remove python binary temp artifact

Posted by ab...@apache.org.
LUCENE-5822: Remove python binary temp artifact


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/80ae5e29
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/80ae5e29
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/80ae5e29

Branch: refs/heads/jira/solr-10879
Commit: 80ae5e29d57ef8b9c3cf382cf2e1676126f5b13d
Parents: 7b322bd
Author: Uwe Schindler <us...@apache.org>
Authored: Sun Jul 2 12:32:09 2017 +0200
Committer: Uwe Schindler <us...@apache.org>
Committed: Sun Jul 2 12:32:09 2017 +0200

----------------------------------------------------------------------
 dev-tools/scripts/.smokeTestRelease.py.swp | Bin 16384 -> 0 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/80ae5e29/dev-tools/scripts/.smokeTestRelease.py.swp
----------------------------------------------------------------------
diff --git a/dev-tools/scripts/.smokeTestRelease.py.swp b/dev-tools/scripts/.smokeTestRelease.py.swp
deleted file mode 100644
index 3c5acb1..0000000
Binary files a/dev-tools/scripts/.smokeTestRelease.py.swp and /dev/null differ


[12/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/StringCastFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/StringCastFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/StringCastFunction.java
new file mode 100644
index 0000000..5960c0e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/StringCastFunction.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A mapping function that casts any input to a {@link StringValue} or {@link StringValueStream}.
+ */
+public class StringCastFunction {
+  public static final String name = "string";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+    }
+    AnalyticsValueStream param = params[0];
+    if (param instanceof StringValueStream) {
+      return LambdaFunction.createStringLambdaFunction(name, a -> a, (StringValueStream)param);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a string-castable parameter.");
+    }
+  });
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/SubtractFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/SubtractFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/SubtractFunction.java
new file mode 100644
index 0000000..3a4e456
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/SubtractFunction.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A subtraction mapping function.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If two numeric Values are passed in, a {@link DoubleValue} representing the first subtracted by the second is returned.
+ * <li>If a numeric ValueStream and a numeric Value are passed in, a {@link DoubleValueStream} representing the Value subtracted by
+ * each of the values of the ValueStream for a document is returned. 
+ * (Or the other way, since the Value and ValueStream can be used in either order)
+ * </ul>
+ */
+public class SubtractFunction {
+  public static final String name = "sub";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramaters, " + params.length + " found.");
+    }
+    AnalyticsValueStream param1 = params[0];
+    AnalyticsValueStream param2 = params[1];
+    if (param1 instanceof DoubleValueStream && param2 instanceof DoubleValueStream) {
+      return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a-b, (DoubleValueStream)param1, (DoubleValueStream)param2);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters.");
+    }
+  });
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/TopFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/TopFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/TopFunction.java
new file mode 100644
index 0000000..801d1ea
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/TopFunction.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A top mapping function, returning the highest value found.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If a single comparable ValueStream is passed in, a Value (of the same type) representing the maximum of the values for each document is returned.
+ * <li>If multiple comparable Values are passed in, a Value (of the same type) representing the maximum of all values is returned.
+ * </ul>
+ */
+public class TopFunction {
+  public static final String name = "top";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires paramaters.");
+    }
+    AnalyticsValueStream param = params[0];
+    if (param instanceof DateValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createDateLambdaFunction(name, (a,b) -> (a>b)? a:b, (DateValueStream)param);
+      }
+      DateValue[] castedParams = new DateValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof DateValue) {
+          castedParams[i] = (DateValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createDateLambdaFunction(name, (a,b) -> (a>b)? a:b, castedParams, false);
+      }
+    }
+    if (param instanceof IntValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createIntLambdaFunction(name, (a,b) -> (a>b)? a:b, (IntValueStream)param);
+      }
+      IntValue[] castedParams = new IntValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof IntValue) {
+          castedParams[i] = (IntValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createIntLambdaFunction(name, (a,b) -> (a>b)? a:b, castedParams, false);
+      }
+    }
+    if (param instanceof LongValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createLongLambdaFunction(name, (a,b) -> (a>b)? a:b, (LongValueStream)param);
+      }
+      LongValue[] castedParams = new LongValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof LongValue) {
+          castedParams[i] = (LongValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createLongLambdaFunction(name, (a,b) -> (a>b)? a:b, castedParams, false);
+      }
+    }
+    if (param instanceof FloatValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createFloatLambdaFunction(name, (a,b) -> (a>b)? a:b, (FloatValueStream)param);
+      }
+      FloatValue[] castedParams = new FloatValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof FloatValue) {
+          castedParams[i] = (FloatValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createFloatLambdaFunction(name, (a,b) -> (a>b)? a:b, castedParams, false);
+      }
+    }
+    if (param instanceof DoubleValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> (a>b)? a:b, (DoubleValueStream)param);
+      }
+      DoubleValue[] castedParams = new DoubleValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof DoubleValue) {
+          castedParams[i] = (DoubleValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> (a>b)? a:b, castedParams, false);
+      }
+    }
+    if (param instanceof StringValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createStringLambdaFunction(name, (a,b) -> (a.compareTo(b)>=0)? a:b, (StringValueStream)param);
+      }
+      StringValue[] castedParams = new StringValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof StringValue) {
+          castedParams[i] = (StringValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createStringLambdaFunction(name, (a,b) -> (a.compareTo(b)>=0)? a:b, castedParams, false);
+      }
+    }
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter. " + 
+          "Incorrect parameter: "+params[0].getExpressionStr());
+  });
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/package-info.java
new file mode 100644
index 0000000..3cf363b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Mapping functions to use for analytics expressions.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/package-info.java
new file mode 100644
index 0000000..e21dd9b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Functions to use for analytics expressions.
+ */
+package org.apache.solr.analytics.function;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/CountFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/CountFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/CountFunction.java
new file mode 100644
index 0000000..a77f997
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/CountFunction.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.CountCollector;
+import org.apache.solr.analytics.function.reduction.data.CountCollector.ExpressionCountCollector;
+import org.apache.solr.analytics.function.reduction.data.CountCollector.TotalCountCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which either counts the number of values that the parameter expression contains,
+ * or the number of documents returned if no parameter is given.
+ */
+public class CountFunction extends AbstractLongValue implements ReductionFunction {
+  private CountCollector collector;
+  public static final String name = "count";
+  private final String exprStr;
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length == 0) {
+      return new CountFunction();
+    }
+    if (params.length == 1) {
+      return new CountFunction(params[0]);
+    }
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function a max of 1 paramater, " + params.length + " given.");
+  });
+  
+  public CountFunction() {
+    this.collector = new TotalCountCollector();
+    this.exprStr = AnalyticsValueStream.createExpressionString(name);
+  }
+  
+  public CountFunction(AnalyticsValueStream param) {
+    this.collector = new ExpressionCountCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public long getLong() {
+    return collector.count();
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (CountCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/DocCountFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/DocCountFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/DocCountFunction.java
new file mode 100644
index 0000000..f009b59
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/DocCountFunction.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.CountCollector;
+import org.apache.solr.analytics.function.reduction.data.CountCollector.ExpressionCountCollector;
+import org.apache.solr.analytics.function.reduction.data.CountCollector.TotalCountCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which either counts the number of Solr Documents for which the parameter expression exists,
+ * or the number of documents returned if no parameter is given.
+ */
+public class DocCountFunction extends AbstractLongValue implements ReductionFunction {
+  private CountCollector collector;
+  public static final String name = "docCount";
+  private final String exprStr;
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length == 0) {
+      return new DocCountFunction();
+    }
+    if (params.length == 1) {
+      return new DocCountFunction(params[0]);
+    }
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function accepts at most 1 paramater, " + params.length + " given.");
+  });
+  
+  public DocCountFunction() {
+    this.collector = new TotalCountCollector();
+    this.exprStr = AnalyticsValueStream.createExpressionString(name);
+  }
+  
+  public DocCountFunction(AnalyticsValueStream param) {
+    this.collector = new ExpressionCountCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public long getLong() {
+    return collector.docCount();
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (CountCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MaxFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MaxFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MaxFunction.java
new file mode 100644
index 0000000..f5ea12d
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MaxFunction.java
@@ -0,0 +1,298 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.MaxCollector.DoubleMaxCollector;
+import org.apache.solr.analytics.function.reduction.data.MaxCollector.FloatMaxCollector;
+import org.apache.solr.analytics.function.reduction.data.MaxCollector.IntMaxCollector;
+import org.apache.solr.analytics.function.reduction.data.MaxCollector.LongMaxCollector;
+import org.apache.solr.analytics.function.reduction.data.MaxCollector.StringMaxCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the maximum value of the given expression.
+ */
+public class MaxFunction {
+  public static final String name = "max";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+    }
+    AnalyticsValueStream param = params[0];
+    if (param instanceof DateValueStream) {
+      return new DateMaxFunction((DateValueStream)param);
+    }
+    if (param instanceof IntValueStream) {
+      return new IntMaxFunction((IntValueStream)param);
+    }
+    if (param instanceof LongValueStream) {
+      return new LongMaxFunction((LongValueStream)param);
+    }
+    if (param instanceof FloatValueStream) {
+      return new FloatMaxFunction((FloatValueStream)param);
+    }
+    if (param instanceof DoubleValueStream) {
+      return new DoubleMaxFunction((DoubleValueStream)param);
+    }
+    if (param instanceof StringValueStream) {
+      return new StringMaxFunction((StringValueStream)param);
+    }
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter. " + 
+          "Incorrect parameter: "+params[0].getExpressionStr());
+  });
+}
+class IntMaxFunction extends AbstractIntValue implements ReductionFunction {
+  private IntMaxCollector collector;
+  public static final String name = MaxFunction.name;
+  private final String exprStr;
+  
+  public IntMaxFunction(IntValueStream param) {
+    this.collector = new IntMaxCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public int getInt() {
+    return collector.exists() ? collector.max() : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (IntMaxCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class LongMaxFunction extends AbstractLongValue implements ReductionFunction {
+  private LongMaxCollector collector;
+  public static final String name = MaxFunction.name;
+  private final String exprStr;
+  
+  public LongMaxFunction(LongValueStream param) {
+    this.collector = new LongMaxCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public long getLong() {
+    return collector.exists() ? collector.max() : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (LongMaxCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class FloatMaxFunction extends AbstractFloatValue implements ReductionFunction {
+  private FloatMaxCollector collector;
+  public static final String name = MaxFunction.name;
+  private final String exprStr;
+  
+  public FloatMaxFunction(FloatValueStream param) {
+    this.collector = new FloatMaxCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public float getFloat() {
+    return collector.exists() ? collector.max() : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (FloatMaxCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class DoubleMaxFunction extends AbstractDoubleValue implements ReductionFunction {
+  private DoubleMaxCollector collector;
+  public static final String name = MaxFunction.name;
+  private final String exprStr;
+  
+  public DoubleMaxFunction(DoubleValueStream param) {
+    this.collector = new DoubleMaxCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public double getDouble() {
+    return collector.exists() ? collector.max() : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (DoubleMaxCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class DateMaxFunction extends AbstractDateValue implements ReductionFunction {
+  private LongMaxCollector collector;
+  public static final String name = MaxFunction.name;
+  private final String exprStr;
+  
+  public DateMaxFunction(LongValueStream param) {
+    this.collector = new LongMaxCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public long getLong() {
+    return collector.exists() ? collector.max() : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (LongMaxCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class StringMaxFunction extends AbstractStringValue implements ReductionFunction {
+  private StringMaxCollector collector;
+  public static final String name = MaxFunction.name;
+  private final String exprStr;
+  
+  public StringMaxFunction(StringValueStream param) {
+    this.collector = new StringMaxCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public String getString() {
+    return collector.exists() ? collector.max() : null;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (StringMaxCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MedianFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MedianFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MedianFunction.java
new file mode 100644
index 0000000..9a6fe40
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MedianFunction.java
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedDoubleListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedFloatListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedIntListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedLongListCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the median value of the given expression.
+ */
+public class MedianFunction {
+  public static final String name = "median";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+    }
+    AnalyticsValueStream param = params[0];
+    if (param instanceof DateValueStream) {
+      return new DateMedianFunction((DateValueStream)param);
+    } else if (param instanceof IntValueStream) {
+      return new IntMedianFunction((IntValueStream)param);
+    } else if (param instanceof LongValueStream) {
+      return new LongMedianFunction((LongValueStream)param);
+    } else if (param instanceof FloatValueStream) {
+      return new FloatMedianFunction((FloatValueStream)param);
+    } else if (param instanceof DoubleValueStream) {
+      return new DoubleMedianFunction((DoubleValueStream)param);
+    }
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a date or numeric parameter.");
+  });
+}
+abstract class NumericMedianFunction<T extends Comparable<T>> extends AbstractDoubleValue implements ReductionFunction {
+  protected SortedListCollector<T> collector;
+  public static final String name = MedianFunction.name;
+  private final String exprStr;
+  
+  public NumericMedianFunction(DoubleValueStream param, SortedListCollector<T> collector) {
+    this.collector = collector;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  protected abstract double collectOrd(int ord);
+  
+  @Override
+  public double getDouble() {
+    int size = collector.size();
+    if (size == 0) {
+      return 0;
+    }
+    if (size % 2 == 0) {
+      return (collectOrd(size/2) + collectOrd(size/2 - 1))/2;
+    } else {
+      return collectOrd(size/2);
+    }
+  }
+  @Override
+  public boolean exists() {
+    return collector.size() > 0;
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedListCollector<T>)sync.apply(collector);
+    collector.calcMedian();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class IntMedianFunction extends NumericMedianFunction<Integer> {
+  public IntMedianFunction(IntValueStream param) {
+    super((DoubleValueStream) param, new SortedIntListCollector(param));
+  }
+
+  @Override
+  protected double collectOrd(int ord) {
+    return collector.get(ord);
+  }
+}
+class LongMedianFunction extends NumericMedianFunction<Long> {
+  public LongMedianFunction(LongValueStream param) {
+    super((DoubleValueStream) param, new SortedLongListCollector(param));
+  }
+
+  @Override
+  protected double collectOrd(int ord) {
+    return collector.get(ord);
+  }
+}
+class FloatMedianFunction extends NumericMedianFunction<Float> {
+  public FloatMedianFunction(FloatValueStream param) {
+    super((DoubleValueStream) param, new SortedFloatListCollector(param));
+  }
+
+  @Override
+  protected double collectOrd(int ord) {
+    return collector.get(ord);
+  }
+}
+class DoubleMedianFunction extends NumericMedianFunction<Double> {
+  public DoubleMedianFunction(DoubleValueStream param) {
+    super(param, new SortedDoubleListCollector(param));
+  }
+
+  @Override
+  protected double collectOrd(int ord) {
+    return collector.get(ord);
+  }
+}
+class DateMedianFunction extends AbstractDateValue implements ReductionFunction {
+  private SortedLongListCollector collector;
+  public static final String name = MedianFunction.name;
+  private final String exprStr;
+  
+  public DateMedianFunction(DateValueStream param) {
+    this.collector = new SortedLongListCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public long getLong() {
+    int size = collector.size();
+    if (size == 0) {
+      return 0;
+    }
+    if (size % 2 == 0) {
+      return (collector.get(size/2) + collector.get(size/2 - 1))/2;
+    } else {
+      return collector.get(size/2);
+    }
+  }
+  @Override
+  public boolean exists() {
+    return collector.size() > 0;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedLongListCollector)sync.apply(collector);
+    collector.calcMedian();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MinFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MinFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MinFunction.java
new file mode 100644
index 0000000..92539d7
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MinFunction.java
@@ -0,0 +1,298 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.MinCollector.DoubleMinCollector;
+import org.apache.solr.analytics.function.reduction.data.MinCollector.FloatMinCollector;
+import org.apache.solr.analytics.function.reduction.data.MinCollector.IntMinCollector;
+import org.apache.solr.analytics.function.reduction.data.MinCollector.LongMinCollector;
+import org.apache.solr.analytics.function.reduction.data.MinCollector.StringMinCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the minumum value of the given expression.
+ */
+public class MinFunction {
+  public static final String name = "min";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+    }
+    AnalyticsValueStream param = params[0];
+    if (param instanceof DateValueStream) {
+      return new DateMinFunction((DateValueStream)param);
+    }
+    if (param instanceof IntValueStream) {
+      return new IntMinFunction((IntValueStream)param);
+    }
+    if (param instanceof LongValueStream) {
+      return new LongMinFunction((LongValueStream)param);
+    }
+    if (param instanceof FloatValueStream) {
+      return new FloatMinFunction((FloatValueStream)param);
+    }
+    if (param instanceof DoubleValueStream) {
+      return new DoubleMinFunction((DoubleValueStream)param);
+    }
+    if (param instanceof StringValueStream) {
+      return new StringMinFunction((StringValueStream)param);
+    }
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter. " + 
+          "Incorrect parameter: "+params[0].getExpressionStr());
+  });
+}
+class IntMinFunction extends AbstractIntValue implements ReductionFunction {
+  private IntMinCollector collector;
+  public static final String name = MinFunction.name;
+  private final String exprStr;
+  
+  public IntMinFunction(IntValueStream param) {
+    this.collector = new IntMinCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public int getInt() {
+    return collector.exists() ? collector.min() : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (IntMinCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class LongMinFunction extends AbstractLongValue implements ReductionFunction {
+  private LongMinCollector collector;
+  public static final String name = MinFunction.name;
+  private final String exprStr;
+  
+  public LongMinFunction(LongValueStream param) {
+    this.collector = new LongMinCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public long getLong() {
+    return collector.exists() ? collector.min() : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (LongMinCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class FloatMinFunction extends AbstractFloatValue implements ReductionFunction {
+  private FloatMinCollector collector;
+  public static final String name = MinFunction.name;
+  private final String exprStr;
+  
+  public FloatMinFunction(FloatValueStream param) {
+    this.collector = new FloatMinCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public float getFloat() {
+    return collector.exists() ? collector.min() : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (FloatMinCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class DoubleMinFunction extends AbstractDoubleValue implements ReductionFunction {
+  private DoubleMinCollector collector;
+  public static final String name = MinFunction.name;
+  private final String exprStr;
+  
+  public DoubleMinFunction(DoubleValueStream param) {
+    this.collector = new DoubleMinCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public double getDouble() {
+    return collector.exists() ? collector.min() : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (DoubleMinCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class DateMinFunction extends AbstractDateValue implements ReductionFunction {
+  private LongMinCollector collector;
+  public static final String name = MinFunction.name;
+  private final String exprStr;
+  
+  public DateMinFunction(LongValueStream param) {
+    this.collector = new LongMinCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public long getLong() {
+    return collector.exists() ? collector.min() : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (LongMinCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class StringMinFunction extends AbstractStringValue implements ReductionFunction {
+  private StringMinCollector collector;
+  public static final String name = MinFunction.name;
+  private final String exprStr;
+  
+  public StringMinFunction(StringValueStream param) {
+    this.collector = new StringMinCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public String getString() {
+    return collector.exists() ? collector.min() : null;
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (StringMinCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MissingFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MissingFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MissingFunction.java
new file mode 100644
index 0000000..5fa7e64
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/MissingFunction.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.CountCollector.ExpressionCountCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the number of documents for which the given expression does not exist.
+ */
+public class MissingFunction extends AbstractLongValue implements ReductionFunction {
+  private ExpressionCountCollector collector;
+  public static final String name = "missing";
+  private final String exprStr;
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+    }
+    return new MissingFunction(params[0]);
+  });
+  
+  public MissingFunction(AnalyticsValueStream param) {
+    this.collector = new ExpressionCountCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public long getLong() {
+    return collector.missing();
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (ExpressionCountCollector)sync.apply(collector);
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/OrdinalFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/OrdinalFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/OrdinalFunction.java
new file mode 100644
index 0000000..0b86cdf
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/OrdinalFunction.java
@@ -0,0 +1,386 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+import java.util.Locale;
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedDoubleListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedFloatListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedIntListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedLongListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedStringListCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.value.constant.ConstantIntValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the given ordinal of the sorted values of the given expression.
+ */
+public class OrdinalFunction {
+  public static final String name = "ordinal";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramater, " + params.length + " found.");
+    }
+    AnalyticsValueStream percValue = params[0];
+    int ord = 0;
+    if (params[0] instanceof ConstantIntValue) {
+      ord = ((IntValue)percValue).getInt();
+      if (ord == 0) {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires the ordinal to be >= 1 or <= -1, 0 is not accepted.");
+      }
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a constant int value (the ordinal) as the first argument.");
+    }
+    AnalyticsValueStream param = params[1];
+    if (param instanceof DateValueStream) {
+      return new DateOrdinalFunction((DateValueStream)param, ord);
+    }else if (param instanceof IntValueStream) {
+      return new IntOrdinalFunction((IntValueStream)param, ord);
+    } else if (param instanceof LongValueStream) {
+      return new LongOrdinalFunction((LongValueStream)param, ord);
+    } else if (param instanceof FloatValueStream) {
+      return new FloatOrdinalFunction((FloatValueStream)param, ord);
+    } else if (param instanceof DoubleValueStream) {
+      return new DoubleOrdinalFunction((DoubleValueStream)param, ord);
+    } else if (param instanceof StringValueStream) {
+      return new StringOrdinalFunction((StringValueStream)param, ord);
+    } 
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter.");
+  });
+  
+  protected static String createOrdinalExpressionString(AnalyticsValueStream param, double perc) {
+    return String.format(Locale.ROOT, "%s(%s,%s)",
+                         name,
+                         (int)(perc*100),
+                         param.getExpressionStr());
+  }
+}
+class IntOrdinalFunction extends AbstractIntValue implements ReductionFunction {
+  private SortedIntListCollector collector;
+  private int ordinal;
+  public static final String name = OrdinalFunction.name;
+  private final String exprStr;
+  
+  public IntOrdinalFunction(IntValueStream param, int ordinal) {
+    this.collector = new SortedIntListCollector(param);
+    this.ordinal = ordinal;
+    this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+  }
+
+  @Override
+  public int getInt() {
+    int size = collector.size();
+    if (ordinal > 0) {
+      return ordinal <= size ? collector.get(ordinal - 1) : 0;
+    } else {
+      return (ordinal * -1) <= size ? collector.get(size + ordinal) : 0;
+    }
+    
+  }
+  @Override
+  public boolean exists() {
+    return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedIntListCollector)sync.apply(collector);
+    if (ordinal > 0) {
+      collector.calcOrdinal(ordinal);
+    } else {
+      collector.calcReverseOrdinal(ordinal*-1);
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class LongOrdinalFunction extends AbstractLongValue implements ReductionFunction {
+  private SortedLongListCollector collector;
+  private int ordinal;
+  public static final String name = OrdinalFunction.name;
+  private final String exprStr;
+  
+  public LongOrdinalFunction(LongValueStream param, int ordinal) {
+    this.collector = new SortedLongListCollector(param);
+    this.ordinal = ordinal;
+    this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+  }
+
+  @Override
+  public long getLong() {
+    int size = collector.size();
+    if (ordinal > 0) {
+      return ordinal <= size ? collector.get(ordinal - 1) : 0;
+    } else {
+      return (ordinal * -1) <= size ? collector.get(size + ordinal) : 0;
+    }
+    
+  }
+  @Override
+  public boolean exists() {
+    return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedLongListCollector)sync.apply(collector);
+    if (ordinal > 0) {
+      collector.calcOrdinal(ordinal);
+    } else {
+      collector.calcReverseOrdinal(ordinal*-1);
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class FloatOrdinalFunction extends AbstractFloatValue implements ReductionFunction {
+  private SortedFloatListCollector collector;
+  private int ordinal;
+  public static final String name = OrdinalFunction.name;
+  private final String exprStr;
+  
+  public FloatOrdinalFunction(FloatValueStream param, int ordinal) {
+    this.collector = new SortedFloatListCollector(param);
+    this.ordinal = ordinal;
+    this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+  }
+
+  @Override
+  public float getFloat() {
+    int size = collector.size();
+    if (ordinal > 0) {
+      return ordinal <= size ? collector.get(ordinal - 1) : 0;
+    } else {
+      return (ordinal * -1) <= size ? collector.get(size + ordinal) : 0;
+    }
+    
+  }
+  @Override
+  public boolean exists() {
+    return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedFloatListCollector)sync.apply(collector);
+    if (ordinal > 0) {
+      collector.calcOrdinal(ordinal);
+    } else {
+      collector.calcReverseOrdinal(ordinal*-1);
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class DoubleOrdinalFunction extends AbstractDoubleValue implements ReductionFunction {
+  private SortedDoubleListCollector collector;
+  private int ordinal;
+  public static final String name = OrdinalFunction.name;
+  private final String exprStr;
+  
+  public DoubleOrdinalFunction(DoubleValueStream param, int ordinal) {
+    this.collector = new SortedDoubleListCollector(param);
+    this.ordinal = ordinal;
+    this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+  }
+
+  @Override
+  public double getDouble() {
+    int size = collector.size();
+    if (ordinal > 0) {
+      return ordinal <= size ? collector.get(ordinal - 1) : 0;
+    } else {
+      return (ordinal * -1) <= size ? collector.get(size + ordinal) : 0;
+    }
+    
+  }
+  @Override
+  public boolean exists() {
+    return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedDoubleListCollector)sync.apply(collector);
+    if (ordinal > 0) {
+      collector.calcOrdinal(ordinal);
+    } else {
+      collector.calcReverseOrdinal(ordinal*-1);
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class DateOrdinalFunction extends AbstractDateValue implements ReductionFunction {
+  private SortedLongListCollector collector;
+  private int ordinal;
+  public static final String name = OrdinalFunction.name;
+  private final String exprStr;
+  
+  public DateOrdinalFunction(LongValueStream param, int ordinal) {
+    this.collector = new SortedLongListCollector(param);
+    this.ordinal = ordinal;
+    this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+  }
+
+  @Override
+  public long getLong() {
+    int size = collector.size();
+    if (ordinal > 0) {
+      return ordinal <= size ? collector.get(ordinal - 1) : 0;
+    } else {
+      return (ordinal * -1) <= size ? collector.get(size + ordinal) : 0;
+    }
+    
+  }
+  @Override
+  public boolean exists() {
+    return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedLongListCollector)sync.apply(collector);
+    collector.calcOrdinal(ordinal);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class StringOrdinalFunction extends AbstractStringValue implements ReductionFunction {
+  private SortedStringListCollector collector;
+  private int ordinal;
+  public static final String name = OrdinalFunction.name;
+  private final String exprStr;
+  
+  public StringOrdinalFunction(StringValueStream param, int ordinal) {
+    this.collector = new SortedStringListCollector(param);
+    this.ordinal = ordinal;
+    this.exprStr = OrdinalFunction.createOrdinalExpressionString(param, ordinal);
+  }
+
+  @Override
+  public String getString() {
+    int size = collector.size();
+    if (ordinal > 0) {
+      return ordinal <= size ? collector.get(ordinal - 1) : null;
+    } else {
+      return (ordinal * -1) <= size ? collector.get(size + ordinal) : null;
+    }
+    
+  }
+  @Override
+  public boolean exists() {
+    return (ordinal > 0 ? ordinal : (ordinal * -1)) <= collector.size();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedStringListCollector)sync.apply(collector);
+    if (ordinal > 0) {
+      collector.calcOrdinal(ordinal);
+    } else {
+      collector.calcReverseOrdinal(ordinal*-1);
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/PercentileFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/PercentileFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/PercentileFunction.java
new file mode 100644
index 0000000..4277d90
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/PercentileFunction.java
@@ -0,0 +1,337 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+import java.util.Locale;
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedDoubleListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedFloatListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedIntListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedLongListCollector;
+import org.apache.solr.analytics.function.reduction.data.SortedListCollector.SortedStringListCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.value.constant.ConstantIntValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the given percentile of the sorted values of the given expression.
+ */
+public class PercentileFunction {
+  public static final String name = "percentile";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramater, " + params.length + " found.");
+    }
+    AnalyticsValueStream percValue = params[0];
+    double perc = 0;
+    if (percValue instanceof ConstantIntValue) {
+      perc = ((IntValue)percValue).getInt();
+      if (perc < 0 || perc > 99) {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a percentile between 0 and 99, " + ((int)perc) + " found.");
+      }
+      perc /= 100;
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a constant int value (the percentile) as the first argument.");
+    }
+    AnalyticsValueStream param = params[1];
+    if (param instanceof DateValueStream) {
+      return new DatePercentileFunction((DateValueStream)param, perc);
+    }else if (param instanceof IntValueStream) {
+      return new IntPercentileFunction((IntValueStream)param, perc);
+    } else if (param instanceof LongValueStream) {
+      return new LongPercentileFunction((LongValueStream)param, perc);
+    } else if (param instanceof FloatValueStream) {
+      return new FloatPercentileFunction((FloatValueStream)param, perc);
+    } else if (param instanceof DoubleValueStream) {
+      return new DoublePercentileFunction((DoubleValueStream)param, perc);
+    } else if (param instanceof StringValueStream) {
+      return new StringPercentileFunction((StringValueStream)param, perc);
+    } 
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter.");
+  });
+  
+  protected static String createPercentileExpressionString(AnalyticsValueStream param, double perc) {
+    return String.format(Locale.ROOT, "%s(%s,%s)",
+                         name,
+                         (int)(perc*100),
+                         param.getExpressionStr());
+  }
+}
+class IntPercentileFunction extends AbstractIntValue implements ReductionFunction {
+  private SortedIntListCollector collector;
+  private double percentile;
+  public static final String name = PercentileFunction.name;
+  private final String exprStr;
+  
+  public IntPercentileFunction(IntValueStream param, double percentile) {
+    this.collector = new SortedIntListCollector(param);
+    this.percentile = percentile;
+    this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+  }
+
+  @Override
+  public int getInt() {
+    int size = collector.size();
+    return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.size() > 0;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedIntListCollector)sync.apply(collector);
+    collector.calcPercentile(percentile);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class LongPercentileFunction extends AbstractLongValue implements ReductionFunction {
+  private SortedLongListCollector collector;
+  private double percentile;
+  public static final String name = PercentileFunction.name;
+  private final String exprStr;
+  
+  public LongPercentileFunction(LongValueStream param, double percentile) {
+    this.collector = new SortedLongListCollector(param);
+    this.percentile = percentile;
+    this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+  }
+
+  @Override
+  public long getLong() {
+    int size = collector.size();
+    return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.size() > 0;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedLongListCollector)sync.apply(collector);
+    collector.calcPercentile(percentile);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class FloatPercentileFunction extends AbstractFloatValue implements ReductionFunction {
+  private SortedFloatListCollector collector;
+  private double percentile;
+  public static final String name = PercentileFunction.name;
+  private final String exprStr;
+  
+  public FloatPercentileFunction(FloatValueStream param, double percentile) {
+    this.collector = new SortedFloatListCollector(param);
+    this.percentile = percentile;
+    this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+  }
+
+  @Override
+  public float getFloat() {
+    int size = collector.size();
+    return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.size() > 0;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedFloatListCollector)sync.apply(collector);
+    collector.calcPercentile(percentile);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class DoublePercentileFunction extends AbstractDoubleValue implements ReductionFunction {
+  private SortedDoubleListCollector collector;
+  private double percentile;
+  public static final String name = PercentileFunction.name;
+  private final String exprStr;
+  
+  public DoublePercentileFunction(DoubleValueStream param, double percentile) {
+    this.collector = new SortedDoubleListCollector(param);
+    this.percentile = percentile;
+    this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+  }
+
+  @Override
+  public double getDouble() {
+    int size = collector.size();
+    return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.size() > 0;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedDoubleListCollector)sync.apply(collector);
+    collector.calcPercentile(percentile);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class DatePercentileFunction extends AbstractDateValue implements ReductionFunction {
+  private SortedLongListCollector collector;
+  private double percentile;
+  public static final String name = PercentileFunction.name;
+  private final String exprStr;
+  
+  public DatePercentileFunction(LongValueStream param, double percentile) {
+    this.collector = new SortedLongListCollector(param);
+    this.percentile = percentile;
+    this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+  }
+
+  @Override
+  public long getLong() {
+    int size = collector.size();
+    return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : 0;
+  }
+  @Override
+  public boolean exists() {
+    return collector.size() > 0;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedLongListCollector)sync.apply(collector);
+    collector.calcPercentile(percentile);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
+class StringPercentileFunction extends AbstractStringValue implements ReductionFunction {
+  private SortedStringListCollector collector;
+  private double percentile;
+  public static final String name = PercentileFunction.name;
+  private final String exprStr;
+  
+  public StringPercentileFunction(StringValueStream param, double percentile) {
+    this.collector = new SortedStringListCollector(param);
+    this.percentile = percentile;
+    this.exprStr = PercentileFunction.createPercentileExpressionString(param, percentile);
+  }
+
+  @Override
+  public String getString() {
+    int size = collector.size();
+    return size > 0 ? collector.get((int) Math.round(percentile * size - .5)) : null;
+  }
+  @Override
+  public boolean exists() {
+    return collector.size() > 0;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SortedStringListCollector)sync.apply(collector);
+    collector.calcPercentile(percentile);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/SumFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/SumFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/SumFunction.java
new file mode 100644
index 0000000..7d4e939
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/SumFunction.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+import java.io.Serializable;
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.function.reduction.data.SumCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the sum of the sorted values of the given expression.
+ */
+public class SumFunction extends AbstractDoubleValue implements ReductionFunction {
+  private SumCollector collector;
+  public static final String name = "sum";
+  private final String exprStr;
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+    }
+    DoubleValueStream casted;
+    try {
+      casted = (DoubleValueStream) params[0];
+    }
+    catch (ClassCastException e) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameter. " + 
+          "Incorrect parameter: "+params[0].getExpressionStr());
+    }
+    return new SumFunction(casted);
+  });
+  
+  public SumFunction(DoubleValueStream param) {
+    this.collector = new SumCollector(param);
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public double getDouble() {
+    return collector.sum();
+  }
+  @Override
+  public boolean exists() {
+    return collector.exists();
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (SumCollector) sync.apply(collector);
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+
+  protected static class SumData extends ReductionData implements Serializable {
+    private static final long serialVersionUID = 5920718235872898338L;
+    double sum;
+  }
+}
\ No newline at end of file


[50/58] [abbrv] lucene-solr:jira/solr-10879: LUCENE-5822 fix smoke test for renamed README

Posted by ab...@apache.org.
LUCENE-5822 fix smoke test for renamed README


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/5b484806
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/5b484806
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/5b484806

Branch: refs/heads/jira/solr-10879
Commit: 5b484806a07e6bb4888c4c704de4eee891d76910
Parents: 2e56e7e
Author: Mike Drob <md...@apache.org>
Authored: Fri Jun 30 16:22:37 2017 -0500
Committer: Mike Drob <md...@apache.org>
Committed: Sat Jul 1 16:10:51 2017 -0700

----------------------------------------------------------------------
 dev-tools/scripts/.smokeTestRelease.py.swp | Bin 0 -> 16384 bytes
 dev-tools/scripts/smokeTestRelease.py      |  12 ++++++++----
 2 files changed, 8 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5b484806/dev-tools/scripts/.smokeTestRelease.py.swp
----------------------------------------------------------------------
diff --git a/dev-tools/scripts/.smokeTestRelease.py.swp b/dev-tools/scripts/.smokeTestRelease.py.swp
new file mode 100644
index 0000000..3c5acb1
Binary files /dev/null and b/dev-tools/scripts/.smokeTestRelease.py.swp differ

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5b484806/dev-tools/scripts/smokeTestRelease.py
----------------------------------------------------------------------
diff --git a/dev-tools/scripts/smokeTestRelease.py b/dev-tools/scripts/smokeTestRelease.py
index 84978bb..1083a09 100644
--- a/dev-tools/scripts/smokeTestRelease.py
+++ b/dev-tools/scripts/smokeTestRelease.py
@@ -644,10 +644,14 @@ def verifyUnpacked(java, project, artifact, unpackPath, gitRevision, version, te
       textFiles.append('BUILD')
 
   for fileName in textFiles:
-    fileName += '.txt'
-    if fileName not in l:
-      raise RuntimeError('file "%s" is missing from artifact %s' % (fileName, artifact))
-    l.remove(fileName)
+    fileNameTxt = fileName + '.txt'
+    fileNameMd = fileName + '.md'
+    if fileNameTxt in l:
+      l.remove(fileNameTxt)
+    elif fileNameMd in l:
+      l.remove(fileNameMd)
+    else:
+      raise RuntimeError('file "%s".[txt|md] is missing from artifact %s' % (fileName, artifact))
 
   if project == 'lucene':
     if LUCENE_NOTICE is None:


[02/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/FunctionTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/FunctionTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/FunctionTest.java
new file mode 100644
index 0000000..dac7921
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/FunctionTest.java
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.expression;
+
+
+import org.apache.solr.analytics.AbstractAnalyticsStatsTest;
+import org.apache.solr.analytics.facet.AbstractAnalyticsFacetTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class FunctionTest extends AbstractAnalyticsStatsTest {
+  static String fileName = "functions.txt";
+
+  static public final int INT = 71;
+  static public final int LONG = 36;
+  static public final int FLOAT = 93;
+  static public final int DOUBLE = 49;
+  static public final int DATE = 12;
+  static public final int STRING = 28;
+  static public final int NUM_LOOPS = 100;
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    initCore("solrconfig-analytics.xml","schema-analytics.xml");
+    h.update("<delete><query>*:*</query></delete>");
+    
+    for (int j = 0; j < NUM_LOOPS; ++j) {
+      int i = j%INT+1;
+      long l = j%LONG+1;
+      float f = j%FLOAT+1;
+      double d = j%DOUBLE+1;
+      double d0 = j%DOUBLE;
+      String dt = (1800+j%DATE) + "-06-30T23:59:59Z";
+      String s = "str" + (j%STRING);
+
+      double add_if = (double)i+f;
+      double add_ldf = (double)l+d+f;
+      double mult_if = (double)i*f;
+      double mult_ldf = (double)l*d*f;
+      double div_if = (double)i/f;
+      double div_ld = (double)l/d;
+      double pow_if = Math.pow(i,f);
+      double pow_ld = Math.pow(l,d);
+      int neg_i = i*-1;
+      long neg_l = l*-1;
+      String dm_2y = (1802+j%DATE) + "-06-30T23:59:59Z";
+      String dm_2m = (1800+j%DATE) + "-08-30T23:59:59Z";
+      String concat_first = "this is the first"+s;
+      String concat_second = "this is the second"+s;
+      
+      assertU(adoc(AbstractAnalyticsFacetTest.filter("id", "1000" + j, "int_id", "" + i, "long_ld", "" + l, "float_fd", "" + f, 
+            "double_dd", "" + d,  "date_dtd", dt, "string_sd", s,
+            "add_if_dd", ""+add_if, "add_ldf_dd", ""+add_ldf, "mult_if_dd", ""+mult_if, "mult_ldf_dd", ""+mult_ldf,
+            "div_if_dd", ""+div_if, "div_ld_dd", ""+div_ld, "pow_if_dd", ""+pow_if, "pow_ld_dd", ""+pow_ld,
+            "neg_id", ""+neg_i, "neg_ld", ""+neg_l, "const_8_dd", "8", "const_10_dd", "10", "dm_2y_dtd", dm_2y, "dm_2m_dtd", dm_2m,
+            "const_00_dtd", "1800-06-30T23:59:59Z", "const_04_dtd", "1804-06-30T23:59:59Z", "const_first_sd", "this is the first", "const_second_sd", "this is the second",
+            "concat_first_sd", concat_first, "concat_second_sd", concat_second, "miss_dd", ""+d0 )));
+      
+      
+      if (usually()) {
+        assertU(commit()); // to have several segments
+      }
+    }
+    
+    assertU(commit()); 
+    
+    setResponse(h.query(request(fileToStringArr(FunctionTest.class, fileName))));
+  }
+      
+  @Test
+  public void addTest() throws Exception { 
+    double result = (Double)getStatResult("ar", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("ar", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    // TODO checfk why asserted 2times
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+
+    result = (Double)getStatResult("ar", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("ar", "meanc", VAL_TYPE.DOUBLE);
+    assertTrue(result==calculated);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+  }
+  
+  @Test
+  public void multiplyTest() throws Exception { 
+    double result = (Double)getStatResult("mr", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("mr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+    
+    result = (Double)getStatResult("mr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("mr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+  }
+  
+  @Test
+  public void divideTest() throws Exception { 
+    Double result = (Double)getStatResult("dr", "sum", VAL_TYPE.DOUBLE);
+    Double calculated = (Double)getStatResult("dr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+    
+    result = (Double)getStatResult("dr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("dr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+  }
+  
+  @Test
+  public void powerTest() throws Exception { 
+    double result = (Double)getStatResult("pr", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("pr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+    
+    result = (Double)getStatResult("pr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("pr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+  }
+  
+  @Test
+  public void negateTest() throws Exception { 
+    double result = (Double)getStatResult("nr", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("nr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+    
+    result = (Double)getStatResult("nr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("nr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+  }
+
+  @Test 
+  public void absoluteValueTest() throws Exception {
+    double result = (Double)getStatResult("avr", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("avr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+    
+    result = (Double)getStatResult("avr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("avr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+  }
+  
+  @Test
+  public void constantNumberTest() throws Exception { 
+    double result = (Double)getStatResult("cnr", "sum", VAL_TYPE.DOUBLE);
+    double calculated = (Double)getStatResult("cnr", "sumc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    
+    result = (Double)getStatResult("cnr", "mean", VAL_TYPE.DOUBLE);
+    calculated = (Double)getStatResult("cnr", "meanc", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), result, calculated, 0.0);
+    assertEquals(getRawResponse(),  result, calculated, 0.0);
+  }
+  
+  @Test
+  public void dateMathTest() throws Exception {
+    String result = (String)getStatResult("dmr", "median", VAL_TYPE.DATE);
+    String calculated = (String)getStatResult("dmr", "medianc", VAL_TYPE.DATE);
+    assertEquals(getRawResponse(), result, calculated);
+    
+    result = (String)getStatResult("dmr", "max", VAL_TYPE.DATE);
+    calculated = (String)getStatResult("dmr", "maxc", VAL_TYPE.DATE);
+    assertEquals(getRawResponse(), result, calculated);
+  }
+  
+  @Test
+  public void constantDateTest() throws Exception { 
+    String result = (String)getStatResult("cdr", "median", VAL_TYPE.DATE);
+    String calculated = (String)getStatResult("cdr", "medianc", VAL_TYPE.DATE);
+    assertEquals(getRawResponse(), result, calculated);
+    assertEquals(getRawResponse(), result, calculated);
+    
+    result = (String)getStatResult("cdr", "max", VAL_TYPE.DATE);
+    calculated = (String)getStatResult("cdr", "maxc", VAL_TYPE.DATE);
+    assertEquals(getRawResponse(), result, calculated);
+  }
+  
+  @Test
+  public void constantStringTest() throws Exception { 
+    String result = (String)getStatResult("csr", "min", VAL_TYPE.STRING);
+    String calculated = (String)getStatResult("csr", "minc", VAL_TYPE.STRING);
+    assertEquals(getRawResponse(), result, calculated);
+    
+    result = (String)getStatResult("csr", "max", VAL_TYPE.STRING);
+    calculated = (String)getStatResult("csr", "maxc", VAL_TYPE.STRING);
+    assertEquals(getRawResponse(), result, calculated);
+  }
+  
+  @Test
+  public void concatenateTest() throws Exception { 
+    String result = (String)getStatResult("cr", "min", VAL_TYPE.STRING);
+    String calculated = (String)getStatResult("cr", "minc", VAL_TYPE.STRING);
+    assertEquals(getRawResponse(), result, calculated);
+    
+    result = (String)getStatResult("cr", "max", VAL_TYPE.STRING);
+    calculated = (String)getStatResult("cr", "maxc", VAL_TYPE.STRING);
+    assertEquals(getRawResponse(), result, calculated);
+  }
+  
+  @Test
+  public void missingTest() throws Exception { 
+    double min = (Double)getStatResult("ms", "min", VAL_TYPE.DOUBLE);
+    double max = (Double)getStatResult("ms", "max", VAL_TYPE.DOUBLE);
+    assertEquals(getRawResponse(), 48.0d, max, 0.0);
+    assertEquals(getRawResponse(), 1.0d, min, 0.0);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetCloudTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetCloudTest.java
new file mode 100644
index 0000000..99e5103
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetCloudTest.java
@@ -0,0 +1,284 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Scanner;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.lucene.util.IOUtils;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
+import org.apache.solr.analytics.util.MedianCalculator;
+import org.apache.solr.analytics.util.OrdinalCalculator;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.cloud.AbstractDistribZkTestBase;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.junit.AfterClass;
+
+public class AbstractAnalyticsFacetCloudTest extends SolrCloudTestCase {
+  protected static final HashMap<String,Object> defaults = new HashMap<>();
+  
+  protected static final String COLLECTIONORALIAS = "collection1";
+  protected static final int TIMEOUT = DEFAULT_TIMEOUT;
+  protected static final String id = "id";
+
+  public static void setupCluster() throws Exception {
+    configureCluster(2)
+        .addConfig("conf", configset("cloud-analytics"))
+        .configure();
+
+    CollectionAdminRequest.createCollection(COLLECTIONORALIAS, "conf", 2, 1).process(cluster.getSolrClient());
+    AbstractDistribZkTestBase.waitForRecoveriesToFinish(COLLECTIONORALIAS, cluster.getSolrClient().getZkStateReader(),
+        false, true, TIMEOUT);
+    
+    cleanIndex();
+  }
+
+  public static void cleanIndex() throws Exception {
+    new UpdateRequest()
+        .deleteByQuery("*:*")
+        .commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+  }
+  
+  protected String latestType = "";
+  
+  @AfterClass
+  public static void afterClassAbstractAnalysis() {
+    defaults.clear();
+  }
+
+  protected NamedList<Object> queryCloudAnalytics(String[] testParams) throws SolrServerException, IOException, InterruptedException {
+    ModifiableSolrParams params = new ModifiableSolrParams();
+    params.set("q", "*:*");
+    params.set("indent", "true");
+    params.set("olap", "true");
+    params.set("rows", "0");
+    for (int i = 0; i + 1 < testParams.length;) {
+      params.add(testParams[i++], testParams[i++]);
+    }
+    cluster.waitForAllNodes(10000);
+    QueryRequest qreq = new QueryRequest(params);
+    QueryResponse resp = qreq.process(cluster.getSolrClient(), COLLECTIONORALIAS);
+    return resp.getResponse();
+  }
+  
+  @SuppressWarnings("unchecked")
+  protected <T> ArrayList<T> getValueList(NamedList<Object> response, String infoName, String facetType, String facetName, String exprName, boolean includeMissing) {
+    NamedList<NamedList<Object>> facetList = 
+        (NamedList<NamedList<Object>>)response.findRecursive(AnalyticsResponseHeadings.COMPLETED_OLD_HEADER,
+                                                             infoName,
+                                                             facetType,
+                                                             facetName);
+    
+    ArrayList<T> results = new ArrayList<>();
+    facetList.forEach( (name, expressions) -> {
+      if (!includeMissing && !name.equals("(MISSING)")) {
+        T result = (T)expressions.get(exprName);
+        if (result != null)
+          results.add(result);
+      }
+    });
+    return results;
+  }
+  
+  protected boolean responseContainsFacetValue(NamedList<Object> response, String infoName, String facetType, String facetName, String facetValue) {
+    return null != response.findRecursive(AnalyticsResponseHeadings.COMPLETED_OLD_HEADER,
+                                          infoName,
+                                          facetType,
+                                          facetName,
+                                          facetValue);
+  }
+
+
+  public static void increment(List<Long> list, int idx){
+    Long i = list.remove(idx);
+    list.add(idx, i+1);
+  }
+  
+  public static String[] filter(String...args){
+    List<String> l = new ArrayList<>();
+    for( int i=0; i <args.length; i+=2){
+      if( args[i+1].equals("0") || args[i+1].equals("0.0") || 
+          args[i+1].equals("1800-12-31T23:59:59Z") || args[i+1].equals("str0") ||
+          args[i+1].equals("this is the firststr0") || 
+          args[i+1].equals("this is the secondstr0") ){
+        continue;
+      }
+      l.add(args[i]);
+      l.add(args[i+1]);
+    }
+    return l.toArray(new String[0]);
+  }
+  
+  protected void setLatestType(String latestType) {
+    this.latestType = latestType;
+  }
+
+  @SuppressWarnings({ "unchecked", "rawtypes" })
+  public <T extends Number & Comparable<T>> ArrayList calculateNumberStat(ArrayList<ArrayList<T>> lists, String stat) {
+    ArrayList result;
+    if (stat.equals("median")) {
+      result = new ArrayList<Double>();
+      for (List<T> list : lists) {
+        result.add(MedianCalculator.getMedian(list));
+      }
+    } else if (stat.equals("mean")) {
+      result = new ArrayList<Double>();
+      for (List<T> list : lists) {
+        double d = 0;
+        for (T element : list) {
+          d += element.doubleValue();
+        }
+        result.add(d/list.size());
+      }
+    } else if (stat.equals("sum")) {
+      result = new ArrayList<Double>();
+      for (Collection<T> list : lists) {
+        double d = 0;
+        for (T element : list) {
+          d += element.doubleValue();
+        }
+        result.add(d);
+      }
+    } else if (stat.equals("sumOfSquares")) {
+      result = new ArrayList<Double>();
+      for (List<T> list : lists) {
+        double d = 0;
+        for (T element : list) {
+          d += element.doubleValue()*element.doubleValue();
+        }
+        result.add(d);
+      }
+    } else if (stat.equals("stddev")) {
+      result = new ArrayList<Double>();
+      for (List<T> list : lists) {
+        double sum = 0;
+        double sumSquares = 0;
+        for (T element : list) {
+          sum += element.doubleValue();
+          sumSquares += element.doubleValue()*element.doubleValue();
+        }
+        String res = Double.toString(Math.sqrt(sumSquares/list.size()-sum*sum/(list.size()*list.size())));
+        result.add(Double.parseDouble(res));
+      }
+    } else {
+      throw new IllegalArgumentException();
+    }
+    return result;
+  }
+
+  @SuppressWarnings({ "unchecked", "rawtypes" })
+  public <T extends Comparable<T>> ArrayList calculateStat(ArrayList<ArrayList<T>> lists, String stat) {
+    ArrayList result;
+    if (stat.contains("perc_")) {
+      result = new ArrayList<T>();
+      for (List<T> list : lists) {
+        if( list.size() == 0) continue;
+        int ord = (int) Math.ceil(Double.parseDouble(stat.substring(5))/100 * list.size()) - 1;
+        ArrayList<Integer> percs = new ArrayList<>(1);
+        percs.add(ord);
+        OrdinalCalculator.putOrdinalsInPosition(list, percs);
+        result.add(list.get(ord));
+      }
+    } else if (stat.equals("count")) {
+      result = new ArrayList<Long>();
+      for (List<T> list : lists) {
+        result.add((long)list.size());
+      }
+    } else if (stat.equals("missing")) {
+      result = new ArrayList<Long>();
+      for (ArrayList<T> list : lists) {
+        result.add(calculateMissing(list,latestType));
+      }
+    } else if (stat.equals("unique")) {
+      result = new ArrayList<Long>();
+      for (List<T> list : lists) {
+        HashSet<T> set = new HashSet<>();
+        set.addAll(list);
+        result.add((long)set.size());
+      }
+    } else if (stat.equals("max")) {
+      result = new ArrayList<T>();
+      for (List<T> list : lists) {
+        if( list.size() == 0) continue;
+        Collections.sort(list);
+        result.add(list.get(list.size()-1));
+      }
+    } else if (stat.equals("min")) {
+      result = new ArrayList<T>();
+      for (List<T> list : lists) {
+        if( list.size() == 0) continue;
+        Collections.sort((List<T>)list);
+        result.add(list.get(0));
+      }
+    } else {
+      result = null;
+    }
+    return result;
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T extends Comparable<T>> Long calculateMissing(ArrayList<T> list, String type) {
+    T def = (T)defaults.get(type);
+    long miss = 0;
+    for (T element : list) {
+      if (element.compareTo(def)==0) {
+        miss++;
+      }
+    }
+    return Long.valueOf(miss);
+  }
+
+  public static ModifiableSolrParams fileToParams(Class<?> clazz, String fileName) throws FileNotFoundException {
+    InputStream in = clazz.getResourceAsStream(fileName);
+    if (in == null) throw new FileNotFoundException("Resource not found: " + fileName);
+    Scanner file = new Scanner(in, "UTF-8");
+    try { 
+      ModifiableSolrParams params = new ModifiableSolrParams();
+      params.set("q", "*:*");
+      params.set("indent", "true");
+      params.set("olap", "true");
+      params.set("rows", "0");
+      while (file.hasNextLine()) {
+        String line = file.nextLine();
+        line = line.trim();
+        if( StringUtils.isBlank(line) || line.startsWith("#")){
+          continue;
+        }
+        String[] param = line.split("=");
+        params.set(param[0], param[1]);
+      }
+      return params;
+    } finally {
+      IOUtils.closeWhileHandlingException(file, in);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetTest.java
index 3660208..ff0e7da 100644
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetTest.java
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/AbstractAnalyticsFacetTest.java
@@ -31,8 +31,9 @@ import java.util.Scanner;
 
 import org.apache.lucene.util.IOUtils;
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
 import org.apache.solr.analytics.util.MedianCalculator;
-import org.apache.solr.analytics.util.PercentileCalculator;
+import org.apache.solr.analytics.util.OrdinalCalculator;
 import org.apache.solr.request.SolrQueryRequest;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -92,9 +93,10 @@ public class AbstractAnalyticsFacetTest extends SolrTestCaseJ4 {
   }
   private NodeList getNodes(String n1, String n2, String n3, String element, String n4) throws XPathExpressionException {
     // Construct the XPath expression. The form better not change or all these will fail.
-    StringBuilder sb = new StringBuilder("/response/lst[@name='stats']/lst[@name='").append(n1).append("']");
+    StringBuilder sb = new StringBuilder("/response/lst[@name='"+AnalyticsResponseHeadings.COMPLETED_OLD_HEADER+"']/lst[@name='").append(n1).append("']");
     sb.append("/lst[@name='").append(n2).append("']");
     sb.append("/lst[@name='").append(n3).append("']");
+    sb.append("/lst[@name!='(MISSING)']");
     sb.append("//").append(element).append("[@name='").append(n4).append("']");
     return (NodeList)xPathFact.newXPath().compile(sb.toString()).evaluate(doc, XPathConstants.NODESET);
 
@@ -229,11 +231,14 @@ public class AbstractAnalyticsFacetTest extends SolrTestCaseJ4 {
   public <T extends Comparable<T>> ArrayList calculateStat(ArrayList<ArrayList<T>> lists, String stat) {
     ArrayList result;
     if (stat.contains("perc_")) {
-      double[] perc = new double[]{Double.parseDouble(stat.substring(5))/100};
       result = new ArrayList<T>();
       for (List<T> list : lists) {
         if( list.size() == 0) continue;
-        result.add(PercentileCalculator.getPercentiles(list, perc).get(0));
+        int ord = (int) Math.ceil(Double.parseDouble(stat.substring(5))/100 * list.size()) - 1;
+        ArrayList<Integer> percs = new ArrayList<>(1);
+        percs.add(ord);
+        OrdinalCalculator.putOrdinalsInPosition(list, percs);
+        result.add(list.get(ord));
       }
     } else if (stat.equals("count")) {
       result = new ArrayList<Long>();
@@ -294,7 +299,7 @@ public class AbstractAnalyticsFacetTest extends SolrTestCaseJ4 {
 
   
   public static String[] fileToStringArr(Class<?> clazz, String fileName) throws FileNotFoundException {
-    InputStream in = clazz.getResourceAsStream(fileName);
+    InputStream in = clazz.getResourceAsStream("/solr/analytics/" + fileName);
     if (in == null) throw new FileNotFoundException("Resource not found: " + fileName);
     Scanner file = new Scanner(in, "UTF-8");
     try { 
@@ -304,7 +309,14 @@ public class AbstractAnalyticsFacetTest extends SolrTestCaseJ4 {
         if (line.length()<2) {
           continue;
         }
+        int commentStart = line.indexOf("//");
+        if (commentStart >= 0) {
+          line = line.substring(0,commentStart);
+        }
         String[] param = line.split("=");
+        if (param.length != 2) {
+          continue;
+        }
         strList.add(param[0]);
         strList.add(param[1]);
       }
@@ -313,4 +325,19 @@ public class AbstractAnalyticsFacetTest extends SolrTestCaseJ4 {
       IOUtils.closeWhileHandlingException(file, in);
     }
   }
+  
+  protected void removeNodes(String xPath, List<Double> string) throws XPathExpressionException {
+    NodeList missingNodes = getNodes(xPath);
+    List<Double> result = new ArrayList<Double>();
+    for (int idx = 0; idx < missingNodes.getLength(); ++idx) {
+      result.add(Double.parseDouble(missingNodes.item(idx).getTextContent()));
+    }
+    string.removeAll(result);
+  }
+
+  protected NodeList getNodes(String xPath) throws XPathExpressionException {
+    StringBuilder sb = new StringBuilder(xPath);
+    return (NodeList) xPathFact.newXPath().compile(sb.toString()).evaluate(doc, XPathConstants.NODESET);
+  }
+  
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FacetSortingTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FacetSortingTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FacetSortingTest.java
new file mode 100644
index 0000000..ef09014
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FacetSortingTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import org.apache.solr.analytics.AbstractAnalyticsStatsTest;
+import org.apache.solr.analytics.expression.ExpressionTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class FacetSortingTest extends AbstractAnalyticsStatsTest {
+  private static String fileName = "facetSorting.txt";
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    initCore("solrconfig-analytics.xml", "schema-analytics.xml");
+    h.update("<delete><query>*:*</query></delete>");
+
+    // The data set below is so generated that in bucket corresponding fieldFacet B, double_dd column has null values 
+    // and in bucket C corresponding to fieldFacet C has null values for column long_ld. 
+    // FieldFaceting occurs on string_sd field
+    assertU(adoc("id", "1001", "string_sd", "A", "double_dd", "" + 3, "long_ld", "" + 1));
+    assertU(adoc("id", "1002", "string_sd", "A", "double_dd", "" + 25, "long_ld", "" + 2));
+    assertU(adoc("id", "1003", "string_sd", "B", "long_ld", "" + 3));
+    assertU(adoc("id", "1004", "string_sd", "B", "long_ld", "" + 4));
+    assertU(adoc("id", "1005", "string_sd", "C",                       "double_dd", "" + 17));
+    
+    assertU(commit());
+    String response = h.query(request(fileToStringArr(ExpressionTest.class, fileName)));
+    setResponse(response);
+  }
+
+  @Test
+  public void addTest() throws Exception {
+    Double minResult = (Double) getStatResult("ar", "min", VAL_TYPE.DOUBLE);
+    Long maxResult = (Long) getStatResult("ar", "max", VAL_TYPE.LONG);
+    assertEquals(Double.valueOf(minResult), Double.valueOf(3.0));
+    assertEquals(Long.valueOf(maxResult),Long.valueOf(4));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetCloudTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetCloudTest.java
new file mode 100644
index 0000000..b3341b1
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/facet/FieldFacetCloudTest.java
@@ -0,0 +1,1214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.common.util.NamedList;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+public class FieldFacetCloudTest extends AbstractAnalyticsFacetCloudTest{
+  public static final int INT = 71;
+  public static final int LONG = 36;
+  public static final int LONGM = 50;
+  public static final int FLOAT = 73;
+  public static final int FLOATM = 84;
+  public static final int DOUBLE = 49;
+  public static final int DATE = 12;
+  public static final int DATEM = 30;
+  public static final int STRING = 29;
+  public static final int STRINGM = 41;
+  public static final int NUM_LOOPS = 100;
+  
+  //INT
+  private static ArrayList<ArrayList<Integer>> intDateTestStart; 
+  private static ArrayList<Long> intDateTestMissing; 
+  private static ArrayList<ArrayList<Integer>> intStringTestStart; 
+  private static ArrayList<Long> intStringTestMissing; 
+  
+  //LONG
+  private static ArrayList<ArrayList<Long>> longDateTestStart; 
+  private static ArrayList<Long> longDateTestMissing; 
+  private static ArrayList<ArrayList<Long>> longStringTestStart; 
+  private static ArrayList<Long> longStringTestMissing; 
+  
+  //FLOAT
+  private static ArrayList<ArrayList<Float>> floatDateTestStart; 
+  private static ArrayList<Long> floatDateTestMissing; 
+  private static ArrayList<ArrayList<Float>> floatStringTestStart; 
+  private static ArrayList<Long> floatStringTestMissing; 
+  
+  //DOUBLE
+  private static ArrayList<ArrayList<Double>> doubleDateTestStart; 
+  private static ArrayList<Long> doubleDateTestMissing; 
+  private static ArrayList<ArrayList<Double>> doubleStringTestStart; 
+  private static ArrayList<Long> doubleStringTestMissing; 
+  
+  //DATE
+  private static ArrayList<ArrayList<String>> dateIntTestStart; 
+  private static ArrayList<Long> dateIntTestMissing; 
+  private static ArrayList<ArrayList<String>> dateLongTestStart; 
+  private static ArrayList<Long> dateLongTestMissing; 
+  
+  //String
+  private static ArrayList<ArrayList<String>> stringIntTestStart; 
+  private static ArrayList<Long> stringIntTestMissing; 
+  private static ArrayList<ArrayList<String>> stringLongTestStart; 
+  private static ArrayList<Long> stringLongTestMissing; 
+  
+  //Multi-Valued
+  private static ArrayList<ArrayList<Integer>> multiLongTestStart; 
+  private static ArrayList<Long> multiLongTestMissing; 
+  private static ArrayList<ArrayList<Integer>> multiStringTestStart; 
+  private static ArrayList<Long> multiStringTestMissing; 
+  private static ArrayList<ArrayList<Integer>> multiDateTestStart; 
+  private static ArrayList<Long> multiDateTestMissing; 
+  
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    setupCluster();
+
+    //INT
+    intDateTestStart = new ArrayList<>();
+    intDateTestMissing = new ArrayList<>();
+    intStringTestStart = new ArrayList<>();
+    intStringTestMissing = new ArrayList<>();
+    
+    //LONG
+    longDateTestStart = new ArrayList<>();
+    longDateTestMissing = new ArrayList<>();
+    longStringTestStart = new ArrayList<>();
+    longStringTestMissing = new ArrayList<>();
+    
+    //FLOAT
+    floatDateTestStart = new ArrayList<>();
+    floatDateTestMissing = new ArrayList<>();
+    floatStringTestStart = new ArrayList<>();
+    floatStringTestMissing = new ArrayList<>();
+    
+    //DOUBLE
+    doubleDateTestStart = new ArrayList<>();
+    doubleDateTestMissing = new ArrayList<>();
+    doubleStringTestStart = new ArrayList<>();
+    doubleStringTestMissing = new ArrayList<>();
+    
+    //DATE
+    dateIntTestStart = new ArrayList<>();
+    dateIntTestMissing = new ArrayList<>();
+    dateLongTestStart = new ArrayList<>();
+    dateLongTestMissing = new ArrayList<>();
+    
+    //String
+    stringIntTestStart = new ArrayList<>();
+    stringIntTestMissing = new ArrayList<>();
+    stringLongTestStart = new ArrayList<>();
+    stringLongTestMissing = new ArrayList<>();
+    
+    //Multi-Valued
+    multiLongTestStart = new ArrayList<>();
+    multiLongTestMissing = new ArrayList<>();
+    multiStringTestStart = new ArrayList<>();
+    multiStringTestMissing = new ArrayList<>();
+    multiDateTestStart = new ArrayList<>();
+    multiDateTestMissing = new ArrayList<>();
+
+    UpdateRequest req = new UpdateRequest();
+    for (int j = 0; j < NUM_LOOPS; ++j) {
+      int i = j%INT;
+      long l = j%LONG;
+      long lm = j%LONGM;
+      float f = j%FLOAT;
+      double d = j%DOUBLE;
+      int dt = j%DATE;
+      int dtm = j%DATEM;
+      int s = j%STRING;
+      int sm = j%STRINGM;
+
+      List<String> fields = new ArrayList<>();
+      fields.add("id"); fields.add("1000"+j);
+      
+      if (dt != 0) {
+      }
+      if( i != 0 ) {
+        fields.add("int_id"); fields.add("" + i);
+      }
+      if( l != 0l ) {
+        fields.add("long_ld"); fields.add("" + l);
+        fields.add("long_ldm"); fields.add("" + l);
+      }
+      if( lm != 0l ) {
+        fields.add("long_ldm"); fields.add("" + lm);
+      }
+      if( f != 0.0f ) {
+        fields.add("float_fd"); fields.add("" + f);
+      }
+      if( d != 0.0d ) {
+        fields.add("double_dd"); fields.add("" + d);
+      }
+      if( dt != 0 ) {
+        fields.add("date_dtd"); fields.add((1800+dt) + "-12-31T23:59:59Z");
+        fields.add("date_dtdm"); fields.add((1800+dt) + "-12-31T23:59:59Z");
+      }
+      if ( dtm != 0 ) {
+        fields.add("date_dtdm"); fields.add((1800+dtm) + "-12-31T23:59:59Z");
+      }
+      if ( s != 0 ) {
+        fields.add("string_sd"); fields.add("str" + s);
+        fields.add("string_sdm"); fields.add("str" + s);
+      }
+      if ( sm != 0 ) {
+        fields.add("string_sdm"); fields.add("str" + sm);
+      }
+      if ( dtm != 0 ) {
+        fields.add("date_dtdm"); fields.add((1800+dtm) + "-12-31T23:59:59Z");
+      }
+      req.add(fields.toArray(new String[0]));
+      
+      if( dt != 0 ){
+        //Dates
+        if (j-DATE<0) {
+          ArrayList<Integer> list1 = new ArrayList<>();
+          if( i != 0 ){
+            list1.add(i);
+            intDateTestMissing.add(0l);
+          } else {
+            intDateTestMissing.add(1l);
+          }
+          intDateTestStart.add(list1);
+          ArrayList<Long> list2 = new ArrayList<>();
+          if( l != 0l ){
+            list2.add(l);
+            longDateTestMissing.add(0l);
+          } else {
+            longDateTestMissing.add(1l);
+          }
+          longDateTestStart.add(list2);
+          ArrayList<Float> list3 = new ArrayList<>();
+          if ( f != 0.0f ){
+            list3.add(f);
+            floatDateTestMissing.add(0l);
+          } else {
+            floatDateTestMissing.add(1l);
+            
+          }
+          floatDateTestStart.add(list3);
+          ArrayList<Double> list4 = new ArrayList<>();
+          if( d != 0.0d ){
+            list4.add(d);
+            doubleDateTestMissing.add(0l);
+          } else {
+            doubleDateTestMissing.add(1l);
+          }
+          doubleDateTestStart.add(list4);
+          ArrayList<Integer> list5 = new ArrayList<>();
+          if( i != 0 ){
+            list5.add(i);
+            multiDateTestMissing.add(0l);
+          } else {
+            multiDateTestMissing.add(1l);
+            
+          }
+          multiDateTestStart.add(list5);
+        } else {
+          if( i != 0 ) intDateTestStart.get(dt-1).add(i); else increment(intDateTestMissing,dt-1);
+          if( l != 0l ) longDateTestStart.get(dt-1).add(l); else increment(longDateTestMissing,dt-1);
+          if( f != 0.0f ) floatDateTestStart.get(dt-1).add(f); else increment(floatDateTestMissing,dt-1);
+          if( d != 0.0d ) doubleDateTestStart.get(dt-1).add(d); else increment(doubleDateTestMissing,dt-1);
+          if( i != 0 ) multiDateTestStart.get(dt-1).add(i); else increment(multiDateTestMissing,dt-1);
+        }
+      }
+      
+      if (j-DATEM<0 && dtm!=dt && dtm!=0) {
+        ArrayList<Integer> list1 = new ArrayList<>();
+        if( i != 0 ){
+          list1.add(i);
+          multiDateTestMissing.add(0l);
+        } else {
+          multiDateTestMissing.add(1l);
+        }
+        multiDateTestStart.add(list1);
+      } else if (dtm!=dt && dtm!=0) {
+        if( i != 0 ) multiDateTestStart.get(dtm-1).add(i);
+      }
+      
+      if( s != 0 ){
+        //Strings
+        if (j-STRING<0) {
+          ArrayList<Integer> list1 = new ArrayList<>();
+          if( i != 0 ){
+            list1.add(i);
+            intStringTestMissing.add(0l);
+          } else {
+            intStringTestMissing.add(1l);
+          }
+          intStringTestStart.add(list1);
+          ArrayList<Long> list2 = new ArrayList<>();
+          if( l != 0l ){
+            list2.add(l);
+            longStringTestMissing.add(0l);
+          } else {
+            longStringTestMissing.add(1l);
+          }
+          longStringTestStart.add(list2);
+          ArrayList<Float> list3 = new ArrayList<>();
+          if( f != 0.0f ){
+            list3.add(f);
+            floatStringTestMissing.add(0l);
+          } else {
+            floatStringTestMissing.add(1l);
+          }
+          floatStringTestStart.add(list3);
+          ArrayList<Double> list4 = new ArrayList<>();
+          if( d != 0.0d ){
+            list4.add(d);
+            doubleStringTestMissing.add(0l);
+          } else {
+            doubleStringTestMissing.add(1l);
+          }
+          doubleStringTestStart.add(list4);
+          ArrayList<Integer> list5 = new ArrayList<>();
+          if( i != 0 ){
+            list5.add(i);
+            multiStringTestMissing.add(0l);
+          } else {
+            multiStringTestMissing.add(1l);
+          }
+          multiStringTestStart.add(list5);
+        } else {
+          if( i != 0 ) intStringTestStart.get(s-1).add(i); else increment(intStringTestMissing,s-1);
+          if( l != 0l ) longStringTestStart.get(s-1).add(l); else increment(longStringTestMissing,s-1);
+          if( f != 0.0f ) floatStringTestStart.get(s-1).add(f); else increment(floatStringTestMissing,s-1);
+          if( d != 0.0d ) doubleStringTestStart.get(s-1).add(d); else increment(doubleStringTestMissing,s-1);
+          if( i != 0 ) multiStringTestStart.get(s-1).add(i); else increment(multiStringTestMissing,s-1);
+        }
+      }
+      
+      //Strings
+      if( sm != 0 ){
+        if (j-STRINGM<0&&sm!=s) {
+          ArrayList<Integer> list1 = new ArrayList<>();
+          if( i != 0 ){
+            list1.add(i);
+            multiStringTestMissing.add(0l);
+          } else {
+            multiStringTestMissing.add(1l);
+          }
+          multiStringTestStart.add(list1);
+        } else if (sm!=s) {
+          if( i != 0 ) multiStringTestStart.get(sm-1).add(i); else increment(multiStringTestMissing,sm-1);
+        }
+      }
+      
+      //Int
+      if( i != 0 ){
+        if (j-INT<0) {
+          ArrayList<String> list1 = new ArrayList<>();
+          if( dt != 0 ){
+            list1.add((1800+dt) + "-12-31T23:59:59Z");
+            dateIntTestMissing.add(0l);
+          } else {
+            dateIntTestMissing.add(1l);
+          }
+          dateIntTestStart.add(list1);
+          ArrayList<String> list2 = new ArrayList<>();
+          if( s != 0 ){
+            list2.add("str"+s);
+            stringIntTestMissing.add(0l);
+          } else {
+            stringIntTestMissing.add(1l);
+          }
+          stringIntTestStart.add(list2);
+        } else {
+          if( dt != 0 ) dateIntTestStart.get(i-1).add((1800+dt) + "-12-31T23:59:59Z"); else increment(dateIntTestMissing,i-1);
+          if( s != 0 ) stringIntTestStart.get(i-1).add("str"+s); else increment(stringIntTestMissing,i-1);
+        }
+      }
+      
+      //Long
+      if( l != 0 ){
+        if (j-LONG<0) {
+          ArrayList<String> list1 = new ArrayList<>();
+          if( dt != 0 ){
+            list1.add((1800+dt) + "-12-31T23:59:59Z");
+            dateLongTestMissing.add(0l);
+          } else {
+            dateLongTestMissing.add(1l);
+          }
+          dateLongTestStart.add(list1);
+          ArrayList<String> list2 = new ArrayList<>();
+          if( s != 0 ){
+            list2.add("str"+s);
+            stringLongTestMissing.add(0l);
+          } else {
+            stringLongTestMissing.add(1l);
+          }
+          stringLongTestStart.add(list2);
+          ArrayList<Integer> list3 = new ArrayList<>();
+          if( i != 0 ){
+            list3.add(i);
+            multiLongTestMissing.add(0l);
+          } else {
+            multiLongTestMissing.add(1l);
+          }
+          multiLongTestStart.add(list3);
+        } else {
+          if( dt != 0 ) dateLongTestStart.get((int)l-1).add((1800+dt) + "-12-31T23:59:59Z"); else increment(dateLongTestMissing,(int)l-1);
+          if( s != 0 ) stringLongTestStart.get((int)l-1).add("str"+s); else increment(stringLongTestMissing,(int)l-1);
+          if( i != 0 ) multiLongTestStart.get((int)l-1).add(i); else increment(multiLongTestMissing,(int)l-1);
+        }
+      }
+      
+      //Long
+      if( lm != 0 ){
+        if (j-LONGM<0&&lm!=l) {
+          ArrayList<Integer> list1 = new ArrayList<>();
+          if( i != 0 ){
+            list1.add(i);
+            multiLongTestMissing.add(0l);
+          } else {
+            multiLongTestMissing.add(1l);
+          }
+          multiLongTestStart.add(list1);
+        } else if (lm!=l) {
+          if( i != 0 ) multiLongTestStart.get((int)lm-1).add(i); else increment( multiLongTestMissing,(int)lm-1);
+        }
+      }
+      
+    }
+
+    req.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+    
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void sumTest() throws Exception { 
+    String[] params = new String[] {
+        "o.sum.s.int", "sum(int_id)",
+        "o.sum.s.long", "sum(long_ld)",
+        "o.sum.s.float", "sum(float_fd)",
+        "o.sum.s.double", "sum(double_dd)",
+        "o.sum.ff", "string_sd",
+        "o.sum.ff", "date_dtd"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+
+    //Int Date
+    Collection<Double> intDate = getValueList(response, "sum", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Double> intDateTest = calculateNumberStat(intDateTestStart, "sum");
+    assertEquals(responseStr.toString(),intDate,intDateTest);
+    //Int String
+    Collection<Double> intString = getValueList(response, "sum", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "sum");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Double> longDate = getValueList(response, "sum", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Double> longDateTest = calculateNumberStat(longDateTestStart, "sum");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Double> longString = getValueList(response, "sum", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Double> longStringTest = calculateNumberStat(longStringTestStart, "sum");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Double> floatDate = getValueList(response, "sum", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Double> floatDateTest = calculateNumberStat(floatDateTestStart, "sum");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Double> floatString = getValueList(response, "sum", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Double> floatStringTest = calculateNumberStat(floatStringTestStart, "sum");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "sum", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = calculateNumberStat(doubleDateTestStart, "sum");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "sum", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = calculateNumberStat(doubleStringTestStart, "sum");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void meanTest() throws Exception { 
+    String[] params = new String[] {
+        "o.mean.s.int", "mean(int_id)",
+        "o.mean.s.long", "mean(long_ld)",
+        "o.mean.s.float", "mean(float_fd)",
+        "o.mean.s.double", "mean(double_dd)",
+        "o.mean.ff", "string_sd",
+        "o.mean.ff", "date_dtd"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Double> intDate = getValueList(response, "mean", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Double> intDateTest = calculateNumberStat(intDateTestStart, "mean");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Double> intString = getValueList(response, "mean", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "mean");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Double> longDate = getValueList(response, "mean", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Double> longDateTest = calculateNumberStat(longDateTestStart, "mean");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Double> longString = getValueList(response, "mean", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Double> longStringTest = calculateNumberStat(longStringTestStart, "mean");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Double> floatDate = getValueList(response, "mean", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Double> floatDateTest = calculateNumberStat(floatDateTestStart, "mean");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Double> floatString = getValueList(response, "mean", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Double> floatStringTest = calculateNumberStat(floatStringTestStart, "mean");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "mean", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = calculateNumberStat(doubleDateTestStart, "mean");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "mean", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = calculateNumberStat(doubleStringTestStart, "mean");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void stddevFacetAscTest() throws Exception { 
+    String[] params = new String[] {
+        "o.stddev.s.int", "stddev(int_id)",
+        "o.stddev.s.long", "stddev(long_ld)",
+        "o.stddev.s.float", "stddev(float_fd)",
+        "o.stddev.s.double", "stddev(double_dd)",
+        "o.stddev.ff", "string_sd",
+        "o.stddev.ff", "date_dtd"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    
+    //Int Date
+    ArrayList<Double> intDate = getValueList(response, "stddev", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Double> intDateTest = calculateNumberStat(intDateTestStart, "stddev");
+    checkStddevs(response, intDate, intDateTest);
+    //Int String
+    ArrayList<Double> intString = getValueList(response, "stddev", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "stddev");
+    checkStddevs(response, intString, intStringTest);
+
+    //Long Date
+    ArrayList<Double> longDate = getValueList(response, "stddev", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Double> longDateTest = calculateNumberStat(longDateTestStart, "stddev");
+    checkStddevs(response, longDate, longDateTest);
+    //Long String
+    ArrayList<Double> longString = getValueList(response, "stddev", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Double> longStringTest = calculateNumberStat(longStringTestStart, "stddev");
+    checkStddevs(response, longString, longStringTest);
+
+    //Float Date
+    ArrayList<Double> floatDate = getValueList(response, "stddev", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Double> floatDateTest = calculateNumberStat(floatDateTestStart, "stddev");
+    checkStddevs(response, floatDate, floatDateTest);
+    //Float String
+    ArrayList<Double> floatString = getValueList(response, "stddev", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Double> floatStringTest = calculateNumberStat(floatStringTestStart, "stddev");
+    checkStddevs(response, floatString, floatStringTest);
+
+    //Double Date
+    ArrayList<Double> doubleDate = getValueList(response, "stddev", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = calculateNumberStat(doubleDateTestStart, "stddev");
+    checkStddevs(response, doubleDate, doubleDateTest);
+    //Double String
+    ArrayList<Double> doubleString = getValueList(response, "stddev", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = calculateNumberStat(doubleStringTestStart, "stddev");
+    checkStddevs(response, doubleString, doubleStringTest);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void medianFacetAscTest() throws Exception { 
+    String[] params = new String[] {
+        "o.median.s.int", "median(int_id)",
+        "o.median.s.long", "median(long_ld)",
+        "o.median.s.float", "median(float_fd)",
+        "o.median.s.double", "median(double_dd)",
+        "o.median.ff", "string_sd",
+        "o.median.ff", "date_dtd"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Double> intDate = getValueList(response, "median","fieldFacets", "date_dtd", "int", false);
+    ArrayList<Double> intDateTest = calculateNumberStat(intDateTestStart, "median");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Double> intString = getValueList(response, "median", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "median");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Double> longDate = getValueList(response, "median", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Double> longDateTest = calculateNumberStat(longDateTestStart, "median");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Double> longString = getValueList(response, "median", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Double> longStringTest = calculateNumberStat(longStringTestStart, "median");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Double> floatDate = getValueList(response, "median", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Double> floatDateTest = calculateNumberStat(floatDateTestStart, "median");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Double> floatString = getValueList(response, "median", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Double> floatStringTest = calculateNumberStat(floatStringTestStart, "median");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "median", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = calculateNumberStat(doubleDateTestStart, "median");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "median", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = calculateNumberStat(doubleStringTestStart, "median");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void perc20Test() throws Exception { 
+    String[] params = new String[] {
+        "o.percentile_20n.s.int", "percentile(20,int_id)",
+        "o.percentile_20n.s.long", "percentile(20,long_ld)",
+        "o.percentile_20n.s.float", "percentile(20,float_fd)",
+        "o.percentile_20n.s.double", "percentile(20,double_dd)",
+        "o.percentile_20n.ff", "string_sd",
+        "o.percentile_20n.ff", "date_dtd",
+
+        "o.percentile_20.s.str", "percentile(20,string_sd)",
+        "o.percentile_20.s.date", "string(percentile(20,date_dtd))",
+        "o.percentile_20.ff", "int_id",
+        "o.percentile_20.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Integer> intDate = getValueList(response, "percentile_20n", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Integer> intDateTest = (ArrayList<Integer>)calculateStat(intDateTestStart, "perc_20");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Integer> intString = getValueList(response, "percentile_20n", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Integer> intStringTest = (ArrayList<Integer>)calculateStat(intStringTestStart, "perc_20");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "percentile_20n", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "perc_20");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Long> longString = getValueList(response, "percentile_20n", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "perc_20");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Float> floatDate = getValueList(response, "percentile_20n", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Float> floatDateTest = (ArrayList<Float>)calculateStat(floatDateTestStart, "perc_20");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Float> floatString = getValueList(response, "percentile_20n", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Float> floatStringTest = (ArrayList<Float>)calculateStat(floatStringTestStart, "perc_20");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "percentile_20n", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = (ArrayList<Double>)calculateStat(doubleDateTestStart, "perc_20");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "percentile_20n", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = (ArrayList<Double>)calculateStat(doubleStringTestStart, "perc_20");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+
+    //Date Int
+    Collection<String> dateInt = getValueList(response, "percentile_20", "fieldFacets", "int_id", "date", false);
+    ArrayList<String> dateIntTest = (ArrayList<String>)calculateStat(dateIntTestStart, "perc_20");
+    assertEquals(responseStr,dateInt,dateIntTest);
+    //Date Long
+    Collection<String> dateString = getValueList(response, "percentile_20", "fieldFacets", "long_ld", "date", false);
+    ArrayList<String> dateLongTest = (ArrayList<String>)calculateStat(dateLongTestStart, "perc_20");
+    assertEquals(responseStr,dateString,dateLongTest);
+
+    //String Int
+    Collection<String> stringInt = getValueList(response, "percentile_20", "fieldFacets", "int_id", "str", false);
+    ArrayList<String> stringIntTest = (ArrayList<String>)calculateStat(stringIntTestStart, "perc_20");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    //String Long
+    Collection<String> stringLong = getValueList(response, "percentile_20", "fieldFacets", "long_ld", "str", false);
+    ArrayList<String> stringLongTest = (ArrayList<String>)calculateStat(stringLongTestStart, "perc_20");
+    assertEquals(responseStr,stringLong,stringLongTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void perc60Test() throws Exception { 
+    String[] params = new String[] {
+        "o.percentile_60n.s.int", "percentile(60,int_id)",
+        "o.percentile_60n.s.long", "percentile(60,long_ld)",
+        "o.percentile_60n.s.float", "percentile(60,float_fd)",
+        "o.percentile_60n.s.double", "percentile(60,double_dd)",
+        "o.percentile_60n.ff", "string_sd",
+        "o.percentile_60n.ff", "date_dtd",
+
+        "o.percentile_60.s.str", "percentile(60,string_sd)",
+        "o.percentile_60.s.date", "string(percentile(60,date_dtd))",
+        "o.percentile_60.ff", "int_id",
+        "o.percentile_60.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Integer> intDate = getValueList(response, "percentile_60n", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Integer> intDateTest = (ArrayList<Integer>)calculateStat(intDateTestStart, "perc_60");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Integer> intString = getValueList(response, "percentile_60n", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Integer> intStringTest = (ArrayList<Integer>)calculateStat(intStringTestStart, "perc_60");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "percentile_60n", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "perc_60");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Long> longString = getValueList(response, "percentile_60n", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "perc_60");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Float> floatDate = getValueList(response, "percentile_60n", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Float> floatDateTest = (ArrayList<Float>)calculateStat(floatDateTestStart, "perc_60");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Float> floatString = getValueList(response, "percentile_60n", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Float> floatStringTest = (ArrayList<Float>)calculateStat(floatStringTestStart, "perc_60");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "percentile_60n", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = (ArrayList<Double>)calculateStat(doubleDateTestStart, "perc_60");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "percentile_60n", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = (ArrayList<Double>)calculateStat(doubleStringTestStart, "perc_60");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+
+    //Date Int
+    Collection<String> dateInt = getValueList(response, "percentile_60", "fieldFacets", "int_id", "date", false);
+    ArrayList<String> dateIntTest = (ArrayList<String>)calculateStat(dateIntTestStart, "perc_60");
+    assertEquals(responseStr,dateInt,dateIntTest);
+    //Date Long
+    Collection<String> dateString = getValueList(response, "percentile_60", "fieldFacets", "long_ld", "date", false);
+    ArrayList<String> dateLongTest = (ArrayList<String>)calculateStat(dateLongTestStart, "perc_60");
+    assertEquals(responseStr,dateString,dateLongTest);
+
+    //String Int
+    Collection<String> stringInt = getValueList(response, "percentile_60", "fieldFacets", "int_id", "str", false);
+    ArrayList<String> stringIntTest = (ArrayList<String>)calculateStat(stringIntTestStart, "perc_60");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    //String Long
+    Collection<String> stringLong = getValueList(response, "percentile_60", "fieldFacets", "long_ld", "str", false);
+    ArrayList<String> stringLongTest = (ArrayList<String>)calculateStat(stringLongTestStart, "perc_60");
+    assertEquals(responseStr,stringLong,stringLongTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void minTest() throws Exception { 
+    String[] params = new String[] {
+        "o.minn.s.int", "min(int_id)",
+        "o.minn.s.long", "min(long_ld)",
+        "o.minn.s.float", "min(float_fd)",
+        "o.minn.s.double", "min(double_dd)",
+        "o.minn.ff", "string_sd",
+        "o.minn.ff", "date_dtd",
+
+        "o.min.s.str", "min(string_sd)",
+        "o.min.s.date", "string(min(date_dtd))",
+        "o.min.ff", "int_id",
+        "o.min.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Integer> intDate = getValueList(response, "minn", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Integer> intDateTest = (ArrayList<Integer>)calculateStat(intDateTestStart, "min");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Integer> intString = getValueList(response, "minn", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Integer> intStringTest = (ArrayList<Integer>)calculateStat(intStringTestStart, "min");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "minn", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "min");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Long> longString = getValueList(response, "minn", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "min");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Float> floatDate = getValueList(response, "minn", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Float> floatDateTest = (ArrayList<Float>)calculateStat(floatDateTestStart, "min");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Float> floatString = getValueList(response, "minn", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Float> floatStringTest = (ArrayList<Float>)calculateStat(floatStringTestStart, "min");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "minn", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = (ArrayList<Double>)calculateStat(doubleDateTestStart, "min");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "minn", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = (ArrayList<Double>)calculateStat(doubleStringTestStart, "min");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+
+    //Date Int
+    Collection<String> dateInt = getValueList(response, "min", "fieldFacets", "int_id", "date", false);
+    ArrayList<String> dateIntTest = (ArrayList<String>)calculateStat(dateIntTestStart, "min");
+    assertEquals(responseStr,dateInt,dateIntTest);
+    //Date Long
+    Collection<String> dateString = getValueList(response, "min", "fieldFacets", "long_ld", "date", false);
+    ArrayList<String> dateLongTest = (ArrayList<String>)calculateStat(dateLongTestStart, "min");
+    assertEquals(responseStr,dateString,dateLongTest);
+
+    //String Int
+    Collection<String> stringInt = getValueList(response, "min", "fieldFacets", "int_id", "str", false);
+    ArrayList<String> stringIntTest = (ArrayList<String>)calculateStat(stringIntTestStart, "min");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    //String Long
+    Collection<String> stringLong = getValueList(response, "min", "fieldFacets", "long_ld", "str", false);
+    ArrayList<String> stringLongTest = (ArrayList<String>)calculateStat(stringLongTestStart, "min");
+    assertEquals(responseStr,stringLong,stringLongTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void maxTest() throws Exception { 
+    String[] params = new String[] {
+        "o.maxn.s.int", "max(int_id)",
+        "o.maxn.s.long", "max(long_ld)",
+        "o.maxn.s.float", "max(float_fd)",
+        "o.maxn.s.double", "max(double_dd)",
+        "o.maxn.ff", "string_sd",
+        "o.maxn.ff", "date_dtd",
+
+        "o.max.s.str", "max(string_sd)",
+        "o.max.s.date", "string(max(date_dtd))",
+        "o.max.ff", "int_id",
+        "o.max.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Integer> intDate = getValueList(response, "maxn", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Integer> intDateTest = (ArrayList<Integer>)calculateStat(intDateTestStart, "max");
+    //assertEquals(responseStr,intDate,intDateTest);
+    
+    //Int String
+    Collection<Integer> intString = getValueList(response, "maxn", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Integer> intStringTest = (ArrayList<Integer>)calculateStat(intStringTestStart, "max");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "maxn", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "max");
+    assertEquals(responseStr,longDate,longDateTest);
+    
+    //Long String
+    Collection<Long> longString = getValueList(response, "maxn", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "max");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Float> floatDate = getValueList(response, "maxn", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Float> floatDateTest = (ArrayList<Float>)calculateStat(floatDateTestStart, "max");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    
+    //Float String
+    Collection<Float> floatString = getValueList(response, "maxn", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Float> floatStringTest = (ArrayList<Float>)calculateStat(floatStringTestStart, "max");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Double> doubleDate = getValueList(response, "maxn", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Double> doubleDateTest = (ArrayList<Double>)calculateStat(doubleDateTestStart, "max");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    
+    //Double String
+    Collection<Double> doubleString = getValueList(response, "maxn", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Double> doubleStringTest = (ArrayList<Double>)calculateStat(doubleStringTestStart, "max");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+    
+    //String Int
+    Collection<String> stringInt = getValueList(response, "max", "fieldFacets", "int_id", "str", false);
+    ArrayList<String> stringIntTest = (ArrayList<String>)calculateStat(stringIntTestStart, "max");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    
+    //String Long
+    Collection<String> stringLong = getValueList(response, "max", "fieldFacets", "long_ld", "str", false);
+    ArrayList<String> stringLongTest = (ArrayList<String>)calculateStat(stringLongTestStart, "max");
+    assertEquals(responseStr,stringLong,stringLongTest);
+
+    //Date Int
+    Collection<String> dateInt = getValueList(response, "max", "fieldFacets", "int_id", "date", false);
+    ArrayList<String> dateIntTest = (ArrayList<String>)calculateStat(dateIntTestStart, "max");
+    assertEquals(responseStr,dateInt,dateIntTest);
+    
+    //Date Long
+    Collection<String> dateString = getValueList(response, "max", "fieldFacets", "long_ld", "date", false);
+    ArrayList<String> dateLongTest = (ArrayList<String>)calculateStat(dateLongTestStart, "max");
+    assertEquals(responseStr,dateString,dateLongTest);
+
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void uniqueTest() throws Exception { 
+    String[] params = new String[] {
+        "o.uniquen.s.int", "unique(int_id)",
+        "o.uniquen.s.long", "unique(long_ld)",
+        "o.uniquen.s.float", "unique(float_fd)",
+        "o.uniquen.s.double", "unique(double_dd)",
+        "o.uniquen.ff", "string_sd",
+        "o.uniquen.ff", "date_dtd",
+
+        "o.unique.s.str", "unique(string_sd)",
+        "o.unique.s.date", "unique(date_dtd)",
+        "o.unique.ff", "int_id",
+        "o.unique.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Long> intDate = getValueList(response, "uniquen", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Long> intDateTest = (ArrayList<Long>)calculateStat(intDateTestStart, "unique");
+    assertEquals(responseStr,intDate,intDateTest);
+    //Int String
+    Collection<Long> intString = getValueList(response, "uniquen", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Long> intStringTest = (ArrayList<Long>)calculateStat(intStringTestStart, "unique");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "uniquen", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "unique");
+    assertEquals(responseStr,longDate,longDateTest);
+    //Long String
+    Collection<Long> longString = getValueList(response, "uniquen", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "unique");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Long> floatDate = getValueList(response, "uniquen", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Long> floatDateTest = (ArrayList<Long>)calculateStat(floatDateTestStart, "unique");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    //Float String
+    Collection<Long> floatString = getValueList(response, "uniquen", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Long> floatStringTest = (ArrayList<Long>)calculateStat(floatStringTestStart, "unique");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Long> doubleDate = getValueList(response, "uniquen", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Long> doubleDateTest = (ArrayList<Long>)calculateStat(doubleDateTestStart, "unique");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    //Double String
+    Collection<Long> doubleString = getValueList(response, "uniquen", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Long> doubleStringTest = (ArrayList<Long>)calculateStat(doubleStringTestStart, "unique");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+
+    //Date Int
+    Collection<Long> dateInt = getValueList(response, "unique", "fieldFacets", "int_id", "date", false);
+    ArrayList<Long> dateIntTest = (ArrayList<Long>)calculateStat(dateIntTestStart, "unique");
+    assertEquals(responseStr,dateInt,dateIntTest);
+    //Date Long
+    Collection<Long> dateString = getValueList(response, "unique", "fieldFacets", "long_ld", "date", false);
+    ArrayList<Long> dateLongTest = (ArrayList<Long>)calculateStat(dateLongTestStart, "unique");
+    assertEquals(responseStr,dateString,dateLongTest);
+
+    //String Int
+    Collection<Long> stringInt = getValueList(response, "unique", "fieldFacets", "int_id", "str", false);
+    ArrayList<Long> stringIntTest = (ArrayList<Long>)calculateStat(stringIntTestStart, "unique");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    //String Long
+    Collection<Long> stringLong = getValueList(response, "unique", "fieldFacets", "long_ld", "str", false);
+    ArrayList<Long> stringLongTest = (ArrayList<Long>)calculateStat(stringLongTestStart, "unique");
+    assertEquals(responseStr,stringLong,stringLongTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void countTest() throws Exception { 
+    String[] params = new String[] {
+        "o.countn.s.int", "count(int_id)",
+        "o.countn.s.long", "count(long_ld)",
+        "o.countn.s.float", "count(float_fd)",
+        "o.countn.s.double", "count(double_dd)",
+        "o.countn.ff", "string_sd",
+        "o.countn.ff", "date_dtd",
+
+        "o.count.s.str", "count(string_sd)",
+        "o.count.s.date", "count(date_dtd)",
+        "o.count.ff", "int_id",
+        "o.count.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Long> intDate = getValueList(response, "countn", "fieldFacets", "date_dtd", "int", false);
+    ArrayList<Long> intDateTest = (ArrayList<Long>)calculateStat(intDateTestStart, "count");
+    assertEquals(responseStr,intDate,intDateTest);
+    
+    //Int String
+    Collection<Long> intString = getValueList(response, "countn", "fieldFacets", "string_sd", "int", false);
+    ArrayList<Long> intStringTest = (ArrayList<Long>)calculateStat(intStringTestStart, "count");
+    assertEquals(responseStr,intString,intStringTest);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "countn", "fieldFacets", "date_dtd", "long", false);
+    ArrayList<Long> longDateTest = (ArrayList<Long>)calculateStat(longDateTestStart, "count");
+    assertEquals(responseStr,longDate,longDateTest);
+    
+    //Long String
+    Collection<Long> longString = getValueList(response, "countn", "fieldFacets", "string_sd", "long", false);
+    ArrayList<Long> longStringTest = (ArrayList<Long>)calculateStat(longStringTestStart, "count");
+    assertEquals(responseStr,longString,longStringTest);
+
+    //Float Date
+    Collection<Long> floatDate = getValueList(response, "countn", "fieldFacets", "date_dtd", "float", false);
+    ArrayList<Long> floatDateTest = (ArrayList<Long>)calculateStat(floatDateTestStart, "count");
+    assertEquals(responseStr,floatDate,floatDateTest);
+    
+    //Float String
+    Collection<Long> floatString = getValueList(response, "countn", "fieldFacets", "string_sd", "float", false);
+    ArrayList<Long> floatStringTest = (ArrayList<Long>)calculateStat(floatStringTestStart, "count");
+    assertEquals(responseStr,floatString,floatStringTest);
+
+    //Double Date
+    Collection<Long> doubleDate = getValueList(response, "countn", "fieldFacets", "date_dtd", "double", false);
+    ArrayList<Long> doubleDateTest = (ArrayList<Long>)calculateStat(doubleDateTestStart, "count");
+    assertEquals(responseStr,doubleDate,doubleDateTest);
+    
+    //Double String
+    Collection<Long> doubleString = getValueList(response, "countn", "fieldFacets", "string_sd", "double", false);
+    ArrayList<Long> doubleStringTest = (ArrayList<Long>)calculateStat(doubleStringTestStart, "count");
+    assertEquals(responseStr,doubleString,doubleStringTest);
+
+    //Date Int
+    Collection<Long> dateInt = getValueList(response, "count", "fieldFacets", "int_id", "date", false);
+    ArrayList<Long> dateIntTest = (ArrayList<Long>)calculateStat(dateIntTestStart, "count");
+    assertEquals(responseStr,dateIntTest,dateInt);
+    
+    //Date Long
+    Collection<Long> dateLong = getValueList(response, "count", "fieldFacets", "long_ld", "date", false);
+    ArrayList<Long> dateLongTest = (ArrayList<Long>)calculateStat(dateLongTestStart, "count");
+    assertEquals(responseStr,dateLong,dateLongTest);
+
+    //String Int
+    Collection<Long> stringInt = getValueList(response, "count", "fieldFacets", "int_id", "str", false);
+    ArrayList<Long> stringIntTest = (ArrayList<Long>)calculateStat(stringIntTestStart, "count");
+    assertEquals(responseStr,stringInt,stringIntTest);
+    
+    //String Long
+    Collection<Long> stringLong = getValueList(response, "count", "fieldFacets", "long_ld", "str", false);
+    ArrayList<Long> stringLongTest = (ArrayList<Long>)calculateStat(stringLongTestStart, "count");
+    assertEquals(responseStr,stringLong,stringLongTest);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void missingTest() throws Exception { 
+    String[] params = new String[] {
+        "o.missingn.s.int", "missing(int_id)",
+        "o.missingn.s.long", "missing(long_ld)",
+        "o.missingn.s.float", "missing(float_fd)",
+        "o.missingn.s.double", "missing(double_dd)",
+        "o.missingn.ff", "string_sd",
+        "o.missingn.ff", "date_dtd",
+
+        "o.missing.s.str", "missing(string_sd)",
+        "o.missing.s.date", "missing(date_dtd)",
+        "o.missing.ff", "int_id",
+        "o.missing.ff", "long_ld"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int Date
+    Collection<Long> intDate = getValueList(response, "missingn", "fieldFacets", "date_dtd", "int", false);
+    setLatestType("int");
+    assertEquals(responseStr,intDateTestMissing,intDate);
+    
+    //Int String
+    Collection<Long> intString = getValueList(response, "missingn", "fieldFacets", "string_sd", "int", false);
+    assertEquals(responseStr,intStringTestMissing,intString);
+
+    //Long Date
+    Collection<Long> longDate = getValueList(response, "missingn", "fieldFacets", "date_dtd", "long", false);
+    setLatestType("long");
+    assertEquals(responseStr,longDateTestMissing,longDate);
+    
+    //Long String
+    Collection<Long> longString = getValueList(response, "missingn", "fieldFacets", "string_sd", "long", false);
+    assertEquals(responseStr,longStringTestMissing,longString);
+
+    //Float Date
+    Collection<Long> floatDate = getValueList(response, "missingn", "fieldFacets", "date_dtd", "float", false);
+    setLatestType("float");
+    assertEquals(responseStr,floatDateTestMissing,floatDate);
+    
+    //Float String
+    Collection<Long> floatString = getValueList(response, "missingn", "fieldFacets", "string_sd", "float", false);
+    assertEquals(responseStr,floatStringTestMissing,floatString);
+
+    //Double Date
+    Collection<Long> doubleDate = getValueList(response, "missingn", "fieldFacets", "date_dtd", "double", false);
+    setLatestType("double");
+    assertEquals(responseStr,doubleDateTestMissing,doubleDate);
+    
+    //Double String
+    Collection<Long> doubleString = getValueList(response, "missingn", "fieldFacets", "string_sd", "double", false);
+    assertEquals(responseStr,doubleStringTestMissing,doubleString);
+
+    //Date Int
+    Collection<Long> dateInt = getValueList(response, "missing", "fieldFacets", "int_id", "date", false);
+    setLatestType("date");
+    assertEquals(responseStr,dateIntTestMissing,dateInt);
+    
+    //Date Long
+    Collection<Long> dateLong = getValueList(response, "missing", "fieldFacets", "long_ld", "date", false);
+    assertEquals(responseStr,dateLongTestMissing,dateLong);
+
+    //String Int
+    Collection<Long> stringInt = getValueList(response, "missing", "fieldFacets", "int_id", "str", false);
+    setLatestType("string");
+    assertEquals(responseStr,stringIntTestMissing,stringInt);
+    
+    //String Long
+    Collection<Long> stringLong = getValueList(response, "missing", "fieldFacets", "long_ld", "str", false);
+    assertEquals(responseStr,stringLongTestMissing,stringLong);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void multiValueTest() throws Exception { 
+    String[] params = new String[] {
+        "o.multivalued.s.mean", "mean(int_id)",
+        "o.multivalued.ff", "long_ldm",
+        "o.multivalued.ff", "string_sdm",
+        "o.multivalued.ff", "date_dtdm"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Long
+    Collection<Double> lon = getValueList(response, "multivalued", "fieldFacets", "long_ldm", "mean", false);
+    ArrayList<Double> longTest = calculateNumberStat(multiLongTestStart, "mean");
+    assertEquals(responseStr,lon,longTest);
+    //Date
+    Collection<Double> date = getValueList(response, "multivalued", "fieldFacets", "date_dtdm", "mean", false);
+    ArrayList<Double> dateTest = calculateNumberStat(multiDateTestStart, "mean");
+    assertEquals(responseStr,date,dateTest);
+    //String
+    Collection<Double> string = getValueList(response, "multivalued", "fieldFacets", "string_sdm", "mean", false);
+    ArrayList<Double> stringTest = calculateNumberStat(multiStringTestStart, "mean");
+    assertEquals(responseStr,string,stringTest);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void missingFacetTest() throws Exception { 
+    String[] params = new String[] {
+        "o.func.facet_show_missing(a)", "fillmissing(a,\"(MISSING)\")",
+        "o.missingf.s.mean", "mean(int_id)",
+        "o.missingf.ff", "date_dtd",
+        "o.missingf.ff", "string_sd",
+        "o.missingf.ff.string_sd.sm", "true",
+        "o.missingf.ff", "date_dtdm",
+        "o.missingf.ff.date_dtdm.sm", "true"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //int MultiDate
+    assertTrue(responseStr, responseContainsFacetValue(response, "missingf", "fieldFacets", "date_dtdm", "(MISSING)"));
+    ArrayList<Double> string = getValueList(response, "missingf", "fieldFacets", "date_dtdm", "mean", false);
+    ArrayList<Double> stringTest = calculateNumberStat(multiDateTestStart, "mean");
+    assertEquals(responseStr, string,stringTest);
+    
+    //Int String
+    assertTrue(responseStr, responseContainsFacetValue(response, "missingf", "fieldFacets", "string_sd", "(MISSING)"));
+    assertTrue(responseStr, !responseContainsFacetValue(response, "missingf", "fieldFacets", "string_sd", "str0"));
+    List<Double> intString = getValueList(response, "missingf", "fieldFacets", "string_sd", "mean", false);
+    ArrayList<Double> intStringTest = calculateNumberStat(intStringTestStart, "mean");
+    assertEquals(responseStr, intString,intStringTest);
+    
+    //Int Date
+    Collection<Double> intDate = getValueList(response, "missingf", "fieldFacets", "date_dtd", "mean", false);
+    ArrayList<ArrayList<Double>> intDateMissingTestStart = (ArrayList<ArrayList<Double>>) intDateTestStart.clone();
+    ArrayList<Double> intDateTest = calculateNumberStat(intDateMissingTestStart, "mean");
+    assertEquals(responseStr,intDate,intDateTest);
+  }
+
+  private void checkStddevs(NamedList<Object> response, ArrayList<Double> list1, ArrayList<Double> list2) {
+    Collections.sort(list1);
+    Collections.sort(list2);
+    for (int i = 0; i<list2.size(); i++) {
+      if ((Math.abs(list1.get(i)-list2.get(i))<.00000000001) == false) {
+        Assert.assertEquals(response.toString(), list1.get(i), list2.get(i), 0.00000000001);
+      }
+    }
+  }
+
+  public static void assertEquals(String mes, Object actual, Object expected) {
+    Collections.sort((List<Comparable>) actual);
+    Collections.sort((List<Comparable>)  expected);
+    Assert.assertEquals(mes, actual, expected);
+  }
+}


[48/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10864: Fixup: Restore the DV vs trie vs points intent of TestRandomDVFaceting

Posted by ab...@apache.org.
SOLR-10864: Fixup: Restore the DV vs trie vs points intent of TestRandomDVFaceting


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

Branch: refs/heads/jira/solr-10879
Commit: f3c851a015e5d8c775f0fb28ffbd8f5725f2f11b
Parents: 26d2ed7
Author: Chris Hostetter <ho...@apache.org>
Authored: Fri Jun 30 11:23:28 2017 -0700
Committer: Chris Hostetter <ho...@apache.org>
Committed: Fri Jun 30 11:23:28 2017 -0700

----------------------------------------------------------------------
 .../org/apache/solr/TestRandomDVFaceting.java   | 28 +++++++++++++++++---
 1 file changed, 24 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f3c851a0/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java b/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
index 46762ea..aaeab54 100644
--- a/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
+++ b/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
@@ -28,6 +28,8 @@ import org.apache.lucene.util.LuceneTestCase.Slow;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.schema.SchemaField;
+import org.apache.solr.schema.TrieIntField;
+import org.apache.solr.schema.IntPointField;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.slf4j.Logger;
@@ -39,18 +41,36 @@ import org.slf4j.LoggerFactory;
  * to the indexed facet results as if it were just another faceting method.
  */
 @Slow
+@SolrTestCaseJ4.SuppressPointFields(bugUrl="Test explicitly compares Trie to Points, randomization defeats the point")
 public class TestRandomDVFaceting extends SolrTestCaseJ4 {
 
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
   @BeforeClass
   public static void beforeTests() throws Exception {
-    // we need DVs on point fields to compute stats & facets
-    // but test also has hard coded assumptions about these field types *NOT* having DV when *NOT* points
-    // so use docvalue if and only if we are using points...
-    System.setProperty(NUMERIC_DOCVALUES_SYSPROP, System.getProperty(NUMERIC_POINTS_SYSPROP));
+    // This tests explicitly compares Trie DV with non-DV Trie with DV Points
+    // so we don't want randomized DocValues on all Trie fields
+    System.setProperty(NUMERIC_DOCVALUES_SYSPROP, "false");
     
     initCore("solrconfig-basic.xml","schema-docValuesFaceting.xml");
+
+    assertEquals("DocValues: Schema assumptions are broken",
+                 false, h.getCore().getLatestSchema().getField("foo_i").hasDocValues());
+    assertEquals("DocValues: Schema assumptions are broken",
+                 true, h.getCore().getLatestSchema().getField("foo_i_dv").hasDocValues());
+    assertEquals("DocValues: Schema assumptions are broken",
+                 true, h.getCore().getLatestSchema().getField("foo_i_p").hasDocValues());
+    
+    assertEquals("Type: Schema assumptions are broken",
+                 TrieIntField.class,
+                 h.getCore().getLatestSchema().getField("foo_i").getType().getClass());
+    assertEquals("Type: Schema assumptions are broken",
+                 TrieIntField.class,
+                 h.getCore().getLatestSchema().getField("foo_i_dv").getType().getClass());
+    assertEquals("Type: Schema assumptions are broken",
+                 IntPointField.class,
+                 h.getCore().getLatestSchema().getField("foo_i_p").getType().getClass());
+    
   }
 
   int indexSize;


[30/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10272: Adding user _default configset to test-files, fixing solr & solr.cmd script bugs

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml
index 09d8e5a..f75303f 100644
--- a/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" ?>
-
+<?xml version="1.0" encoding="UTF-8" ?>
 <!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
@@ -17,16 +16,1358 @@
  limitations under the License.
 -->
 
+<!-- 
+     For more details about configurations options that may appear in
+     this file, see http://wiki.apache.org/solr/SolrConfigXml. 
+-->
 <config>
+  <!-- In all configuration below, a prefix of "solr." for class names
+       is an alias that causes solr to search appropriate packages,
+       including org.apache.solr.(search|update|request|core|analysis)
+
+       You may also specify a fully qualified Java classname if you
+       have your own custom plugins.
+    -->
+
+  <!-- Controls what version of Lucene various components of Solr
+       adhere to.  Generally, you want to use the latest version to
+       get all bug fixes and improvements. It is highly recommended
+       that you fully re-index after changing this setting as it can
+       affect both how text is indexed and queried.
+  -->
+  <luceneMatchVersion>7.0.0</luceneMatchVersion>
+
+  <!-- <lib/> directives can be used to instruct Solr to load any Jars
+       identified and use them to resolve any "plugins" specified in
+       your solrconfig.xml or schema.xml (ie: Analyzers, Request
+       Handlers, etc...).
+
+       All directories and paths are resolved relative to the
+       instanceDir.
+
+       Please note that <lib/> directives are processed in the order
+       that they appear in your solrconfig.xml file, and are "stacked" 
+       on top of each other when building a ClassLoader - so if you have 
+       plugin jars with dependencies on other jars, the "lower level" 
+       dependency jars should be loaded first.
+
+       If a "./lib" directory exists in your instanceDir, all files
+       found in it are included as if you had used the following
+       syntax...
+       
+              <lib dir="./lib" />
+    -->
+
+  <!-- A 'dir' option by itself adds any files found in the directory 
+       to the classpath, this is useful for including all jars in a
+       directory.
+
+       When a 'regex' is specified in addition to a 'dir', only the
+       files in that directory which completely match the regex
+       (anchored on both ends) will be included.
+
+       If a 'dir' option (with or without a regex) is used and nothing
+       is found that matches, a warning will be logged.
+
+       The examples below can be used to load some solr-contribs along 
+       with their external dependencies.
+    -->
+  <lib dir="${solr.install.dir:../../../..}/contrib/extraction/lib" regex=".*\.jar" />
+  <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-cell-\d.*\.jar" />
+
+  <lib dir="${solr.install.dir:../../../..}/contrib/clustering/lib/" regex=".*\.jar" />
+  <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-clustering-\d.*\.jar" />
+
+  <lib dir="${solr.install.dir:../../../..}/contrib/langid/lib/" regex=".*\.jar" />
+  <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-langid-\d.*\.jar" />
+
+  <lib dir="${solr.install.dir:../../../..}/contrib/velocity/lib" regex=".*\.jar" />
+  <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-velocity-\d.*\.jar" />
+  <!-- an exact 'path' can be used instead of a 'dir' to specify a 
+       specific jar file.  This will cause a serious error to be logged 
+       if it can't be loaded.
+    -->
+  <!--
+     <lib path="../a-jar-that-does-not-exist.jar" /> 
+  -->
+
+  <!-- Data Directory
+
+       Used to specify an alternate directory to hold all index data
+       other than the default ./data under the Solr home.  If
+       replication is in use, this should match the replication
+       configuration.
+    -->
+  <dataDir>${solr.data.dir:}</dataDir>
+
+
+  <!-- The DirectoryFactory to use for indexes.
+       
+       solr.StandardDirectoryFactory is filesystem
+       based and tries to pick the best implementation for the current
+       JVM and platform.  solr.NRTCachingDirectoryFactory, the default,
+       wraps solr.StandardDirectoryFactory and caches small files in memory
+       for better NRT performance.
+
+       One can force a particular implementation via solr.MMapDirectoryFactory,
+       solr.NIOFSDirectoryFactory, or solr.SimpleFSDirectoryFactory.
+
+       solr.RAMDirectoryFactory is memory based and not persistent.
+    -->
+  <directoryFactory name="DirectoryFactory"
+                    class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
+
+  <!-- The CodecFactory for defining the format of the inverted index.
+       The default implementation is SchemaCodecFactory, which is the official Lucene
+       index format, but hooks into the schema to provide per-field customization of
+       the postings lists and per-document values in the fieldType element
+       (postingsFormat/docValuesFormat). Note that most of the alternative implementations
+       are experimental, so if you choose to customize the index format, it's a good
+       idea to convert back to the official format e.g. via IndexWriter.addIndexes(IndexReader)
+       before upgrading to a newer version to avoid unnecessary reindexing.
+       A "compressionMode" string element can be added to <codecFactory> to choose 
+       between the existing compression modes in the default codec: "BEST_SPEED" (default)
+       or "BEST_COMPRESSION".
+  -->
+  <codecFactory class="solr.SchemaCodecFactory"/>
+
+  <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+       Index Config - These settings control low-level behavior of indexing
+       Most example settings here show the default value, but are commented
+       out, to more easily see where customizations have been made.
+       
+       Note: This replaces <indexDefaults> and <mainIndex> from older versions
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+  <indexConfig>
+    <!-- maxFieldLength was removed in 4.0. To get similar behavior, include a 
+         LimitTokenCountFilterFactory in your fieldType definition. E.g. 
+     <filter class="solr.LimitTokenCountFilterFactory" maxTokenCount="10000"/>
+    -->
+    <!-- Maximum time to wait for a write lock (ms) for an IndexWriter. Default: 1000 -->
+    <!-- <writeLockTimeout>1000</writeLockTimeout>  -->
+
+    <!-- Expert: Enabling compound file will use less files for the index, 
+         using fewer file descriptors on the expense of performance decrease. 
+         Default in Lucene is "true". Default in Solr is "false" (since 3.6) -->
+    <!-- <useCompoundFile>false</useCompoundFile> -->
+
+    <!-- ramBufferSizeMB sets the amount of RAM that may be used by Lucene
+         indexing for buffering added documents and deletions before they are
+         flushed to the Directory.
+         maxBufferedDocs sets a limit on the number of documents buffered
+         before flushing.
+         If both ramBufferSizeMB and maxBufferedDocs is set, then
+         Lucene will flush based on whichever limit is hit first.  -->
+    <!-- <ramBufferSizeMB>100</ramBufferSizeMB> -->
+    <!-- <maxBufferedDocs>1000</maxBufferedDocs> -->
+
+    <!-- Expert: Merge Policy 
+         The Merge Policy in Lucene controls how merging of segments is done.
+         The default since Solr/Lucene 3.3 is TieredMergePolicy.
+         The default since Lucene 2.3 was the LogByteSizeMergePolicy,
+         Even older versions of Lucene used LogDocMergePolicy.
+      -->
+    <!--
+        <mergePolicyFactory class="org.apache.solr.index.TieredMergePolicyFactory">
+          <int name="maxMergeAtOnce">10</int>
+          <int name="segmentsPerTier">10</int>
+          <double name="noCFSRatio">0.1</double>
+        </mergePolicyFactory>
+      -->
+
+    <!-- Expert: Merge Scheduler
+         The Merge Scheduler in Lucene controls how merges are
+         performed.  The ConcurrentMergeScheduler (Lucene 2.3 default)
+         can perform merges in the background using separate threads.
+         The SerialMergeScheduler (Lucene 2.2 default) does not.
+     -->
+    <!-- 
+       <mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>
+       -->
+
+    <!-- LockFactory 
+
+         This option specifies which Lucene LockFactory implementation
+         to use.
+      
+         single = SingleInstanceLockFactory - suggested for a
+                  read-only index or when there is no possibility of
+                  another process trying to modify the index.
+         native = NativeFSLockFactory - uses OS native file locking.
+                  Do not use when multiple solr webapps in the same
+                  JVM are attempting to share a single index.
+         simple = SimpleFSLockFactory  - uses a plain file for locking
+
+         Defaults: 'native' is default for Solr3.6 and later, otherwise
+                   'simple' is the default
+
+         More details on the nuances of each LockFactory...
+         http://wiki.apache.org/lucene-java/AvailableLockFactories
+    -->
+    <lockType>${solr.lock.type:native}</lockType>
+
+    <!-- Commit Deletion Policy
+         Custom deletion policies can be specified here. The class must
+         implement org.apache.lucene.index.IndexDeletionPolicy.
+
+         The default Solr IndexDeletionPolicy implementation supports
+         deleting index commit points on number of commits, age of
+         commit point and optimized status.
+         
+         The latest commit point should always be preserved regardless
+         of the criteria.
+    -->
+    <!-- 
+    <deletionPolicy class="solr.SolrDeletionPolicy">
+    -->
+    <!-- The number of commit points to be kept -->
+    <!-- <str name="maxCommitsToKeep">1</str> -->
+    <!-- The number of optimized commit points to be kept -->
+    <!-- <str name="maxOptimizedCommitsToKeep">0</str> -->
+    <!--
+        Delete all commit points once they have reached the given age.
+        Supports DateMathParser syntax e.g.
+      -->
+    <!--
+       <str name="maxCommitAge">30MINUTES</str>
+       <str name="maxCommitAge">1DAY</str>
+    -->
+    <!-- 
+    </deletionPolicy>
+    -->
+
+    <!-- Lucene Infostream
+       
+         To aid in advanced debugging, Lucene provides an "InfoStream"
+         of detailed information when indexing.
+
+         Setting The value to true will instruct the underlying Lucene
+         IndexWriter to write its debugging info the specified file
+      -->
+    <!-- <infoStream file="INFOSTREAM.txt">false</infoStream> -->
+  </indexConfig>
+
+
+  <!-- JMX
+       
+       This example enables JMX if and only if an existing MBeanServer
+       is found, use this if you want to configure JMX through JVM
+       parameters. Remove this to disable exposing Solr configuration
+       and statistics to JMX.
+
+       For more details see http://wiki.apache.org/solr/SolrJmx
+    -->
+  <jmx />
+  <!-- If you want to connect to a particular server, specify the
+       agentId 
+    -->
+  <!-- <jmx agentId="myAgent" /> -->
+  <!-- If you want to start a new MBeanServer, specify the serviceUrl -->
+  <!-- <jmx serviceUrl="service:jmx:rmi:///jndi/rmi://localhost:9999/solr"/>
+    -->
+
+  <!-- The default high-performance update handler -->
+  <updateHandler class="solr.DirectUpdateHandler2">
+
+    <!-- Enables a transaction log, used for real-time get, durability, and
+         and solr cloud replica recovery.  The log can grow as big as
+         uncommitted changes to the index, so use of a hard autoCommit
+         is recommended (see below).
+         "dir" - the target directory for transaction logs, defaults to the
+                solr data directory.
+         "numVersionBuckets" - sets the number of buckets used to keep
+                track of max version values when checking for re-ordered
+                updates; increase this value to reduce the cost of
+                synchronizing access to version buckets during high-volume
+                indexing, this requires 8 bytes (long) * numVersionBuckets
+                of heap space per Solr core.
+    -->
+    <updateLog>
+      <str name="dir">${solr.ulog.dir:}</str>
+      <int name="numVersionBuckets">${solr.ulog.numVersionBuckets:65536}</int>
+    </updateLog>
+
+    <!-- AutoCommit
+
+         Perform a hard commit automatically under certain conditions.
+         Instead of enabling autoCommit, consider using "commitWithin"
+         when adding documents. 
+
+         http://wiki.apache.org/solr/UpdateXmlMessages
+
+         maxDocs - Maximum number of documents to add since the last
+                   commit before automatically triggering a new commit.
+
+         maxTime - Maximum amount of time in ms that is allowed to pass
+                   since a document was added before automatically
+                   triggering a new commit. 
+         openSearcher - if false, the commit causes recent index changes
+           to be flushed to stable storage, but does not cause a new
+           searcher to be opened to make those changes visible.
+
+         If the updateLog is enabled, then it's highly recommended to
+         have some sort of hard autoCommit to limit the log size.
+      -->
+    <autoCommit>
+      <maxTime>${solr.autoCommit.maxTime:15000}</maxTime>
+      <openSearcher>false</openSearcher>
+    </autoCommit>
+
+    <!-- softAutoCommit is like autoCommit except it causes a
+         'soft' commit which only ensures that changes are visible
+         but does not ensure that data is synced to disk.  This is
+         faster and more near-realtime friendly than a hard commit.
+      -->
+
+    <autoSoftCommit>
+      <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime>
+    </autoSoftCommit>
+
+    <!-- Update Related Event Listeners
+         
+         Various IndexWriter related events can trigger Listeners to
+         take actions.
+
+         postCommit - fired after every commit or optimize command
+         postOptimize - fired after every optimize command
+      -->
+    <!-- The RunExecutableListener executes an external command from a
+         hook such as postCommit or postOptimize.
+         
+         exe - the name of the executable to run
+         dir - dir to use as the current working directory. (default=".")
+         wait - the calling thread waits until the executable returns. 
+                (default="true")
+         args - the arguments to pass to the program.  (default is none)
+         env - environment variables to set.  (default is none)
+      -->
+    <!-- This example shows how RunExecutableListener could be used
+         with the script based replication...
+         http://wiki.apache.org/solr/CollectionDistribution
+      -->
+    <!--
+       <listener event="postCommit" class="solr.RunExecutableListener">
+         <str name="exe">solr/bin/snapshooter</str>
+         <str name="dir">.</str>
+         <bool name="wait">true</bool>
+         <arr name="args"> <str>arg1</str> <str>arg2</str> </arr>
+         <arr name="env"> <str>MYVAR=val1</str> </arr>
+       </listener>
+      -->
+
+  </updateHandler>
+
+  <!-- IndexReaderFactory
+
+       Use the following format to specify a custom IndexReaderFactory,
+       which allows for alternate IndexReader implementations.
+
+       ** Experimental Feature **
+
+       Please note - Using a custom IndexReaderFactory may prevent
+       certain other features from working. The API to
+       IndexReaderFactory may change without warning or may even be
+       removed from future releases if the problems cannot be
+       resolved.
+
+
+       ** Features that may not work with custom IndexReaderFactory **
+
+       The ReplicationHandler assumes a disk-resident index. Using a
+       custom IndexReader implementation may cause incompatibility
+       with ReplicationHandler and may cause replication to not work
+       correctly. See SOLR-1366 for details.
+
+    -->
+  <!--
+  <indexReaderFactory name="IndexReaderFactory" class="package.class">
+    <str name="someArg">Some Value</str>
+  </indexReaderFactory >
+  -->
+
+  <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+       Query section - these settings control query time things like caches
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
+  <query>
+
+    <!-- Maximum number of clauses in each BooleanQuery,  an exception
+         is thrown if exceeded.  It is safe to increase or remove this setting,
+         since it is purely an arbitrary limit to try and catch user errors where
+         large boolean queries may not be the best implementation choice.
+      -->
+    <maxBooleanClauses>1024</maxBooleanClauses>
+
+    <!-- Solr Internal Query Caches
+
+         There are two implementations of cache available for Solr,
+         LRUCache, based on a synchronized LinkedHashMap, and
+         FastLRUCache, based on a ConcurrentHashMap.  
+
+         FastLRUCache has faster gets and slower puts in single
+         threaded operation and thus is generally faster than LRUCache
+         when the hit ratio of the cache is high (> 75%), and may be
+         faster under other scenarios on multi-cpu systems.
+    -->
+
+    <!-- Filter Cache
+
+         Cache used by SolrIndexSearcher for filters (DocSets),
+         unordered sets of *all* documents that match a query.  When a
+         new searcher is opened, its caches may be prepopulated or
+         "autowarmed" using data from caches in the old searcher.
+         autowarmCount is the number of items to prepopulate.  For
+         LRUCache, the autowarmed items will be the most recently
+         accessed items.
+
+         Parameters:
+           class - the SolrCache implementation LRUCache or
+               (LRUCache or FastLRUCache)
+           size - the maximum number of entries in the cache
+           initialSize - the initial capacity (number of entries) of
+               the cache.  (see java.util.HashMap)
+           autowarmCount - the number of entries to prepopulate from
+               and old cache.
+           maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed
+                      to occupy. Note that when this option is specified, the size
+                      and initialSize parameters are ignored.
+      -->
+    <filterCache class="solr.FastLRUCache"
+                 size="512"
+                 initialSize="512"
+                 autowarmCount="0"/>
+
+    <!-- Query Result Cache
+         
+         Caches results of searches - ordered lists of document ids
+         (DocList) based on a query, a sort, and the range of documents requested.
+         Additional supported parameter by LRUCache:
+            maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed
+                       to occupy
+      -->
+    <queryResultCache class="solr.LRUCache"
+                      size="512"
+                      initialSize="512"
+                      autowarmCount="0"/>
+
+    <!-- Document Cache
+
+         Caches Lucene Document objects (the stored fields for each
+         document).  Since Lucene internal document ids are transient,
+         this cache will not be autowarmed.
+      -->
+    <documentCache class="solr.LRUCache"
+                   size="512"
+                   initialSize="512"
+                   autowarmCount="0"/>
+
+    <!-- custom cache currently used by block join -->
+    <cache name="perSegFilter"
+           class="solr.search.LRUCache"
+           size="10"
+           initialSize="0"
+           autowarmCount="10"
+           regenerator="solr.NoOpRegenerator" />
+
+    <!-- Field Value Cache
+         
+         Cache used to hold field values that are quickly accessible
+         by document id.  The fieldValueCache is created by default
+         even if not configured here.
+      -->
+    <!--
+       <fieldValueCache class="solr.FastLRUCache"
+                        size="512"
+                        autowarmCount="128"
+                        showItems="32" />
+      -->
+
+    <!-- Custom Cache
+
+         Example of a generic cache.  These caches may be accessed by
+         name through SolrIndexSearcher.getCache(),cacheLookup(), and
+         cacheInsert().  The purpose is to enable easy caching of
+         user/application level data.  The regenerator argument should
+         be specified as an implementation of solr.CacheRegenerator 
+         if autowarming is desired.  
+      -->
+    <!--
+       <cache name="myUserCache"
+              class="solr.LRUCache"
+              size="4096"
+              initialSize="1024"
+              autowarmCount="1024"
+              regenerator="com.mycompany.MyRegenerator"
+              />
+      -->
+
+
+    <!-- Lazy Field Loading
+
+         If true, stored fields that are not requested will be loaded
+         lazily.  This can result in a significant speed improvement
+         if the usual case is to not load all stored fields,
+         especially if the skipped fields are large compressed text
+         fields.
+    -->
+    <enableLazyFieldLoading>true</enableLazyFieldLoading>
+
+    <!-- Use Filter For Sorted Query
+ 
+         A possible optimization that attempts to use a filter to
+         satisfy a search.  If the requested sort does not include
+         score, then the filterCache will be checked for a filter
+         matching the query. If found, the filter will be used as the
+         source of document ids, and then the sort will be applied to
+         that.
+ 
+         For most situations, this will not be useful unless you
+         frequently get the same search repeatedly with different sort
+         options, and none of them ever use "score"
+      -->
+    <!--
+       <useFilterForSortedQuery>true</useFilterForSortedQuery>
+      -->
+
+    <!-- Result Window Size
+ 
+         An optimization for use with the queryResultCache.  When a search
+         is requested, a superset of the requested number of document ids
+         are collected.  For example, if a search for a particular query
+         requests matching documents 10 through 19, and queryWindowSize is 50,
+         then documents 0 through 49 will be collected and cached.  Any further
+         requests in that range can be satisfied via the cache.  
+      -->
+    <queryResultWindowSize>20</queryResultWindowSize>
+
+    <!-- Maximum number of documents to cache for any entry in the
+         queryResultCache. 
+      -->
+    <queryResultMaxDocsCached>200</queryResultMaxDocsCached>
+
+    <!-- Query Related Event Listeners
+ 
+         Various IndexSearcher related events can trigger Listeners to
+         take actions.
+ 
+         newSearcher - fired whenever a new searcher is being prepared
+         and there is a current searcher handling requests (aka
+         registered).  It can be used to prime certain caches to
+         prevent long request times for certain requests.
+ 
+         firstSearcher - fired whenever a new searcher is being
+         prepared but there is no current registered searcher to handle
+         requests or to gain autowarming data from.
+ 
+         
+      -->
+    <!-- QuerySenderListener takes an array of NamedList and executes a
+         local query request for each NamedList in sequence. 
+      -->
+    <listener event="newSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <!--
+           <lst><str name="q">solr</str><str name="sort">price asc</str></lst>
+           <lst><str name="q">rocks</str><str name="sort">weight asc</str></lst>
+          -->
+      </arr>
+    </listener>
+    <listener event="firstSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <!--
+        <lst>
+          <str name="q">static firstSearcher warming in solrconfig.xml</str>
+        </lst>
+        -->
+      </arr>
+    </listener>
+
+    <!-- Use Cold Searcher
+
+         If a search request comes in and there is no current
+         registered searcher, then immediately register the still
+         warming searcher and use it.  If "false" then all requests
+         will block until the first searcher is done warming.
+      -->
+    <useColdSearcher>false</useColdSearcher>
+
+  </query>
+
+
+  <!-- Request Dispatcher
+
+       This section contains instructions for how the SolrDispatchFilter
+       should behave when processing requests for this SolrCore.
+
+    -->
+  <requestDispatcher>
+    <!-- Request Parsing
+
+         These settings indicate how Solr Requests may be parsed, and
+         what restrictions may be placed on the ContentStreams from
+         those requests
+
+         enableRemoteStreaming - enables use of the stream.file
+         and stream.url parameters for specifying remote streams.
+
+         multipartUploadLimitInKB - specifies the max size (in KiB) of
+         Multipart File Uploads that Solr will allow in a Request.
+         
+         formdataUploadLimitInKB - specifies the max size (in KiB) of
+         form data (application/x-www-form-urlencoded) sent via
+         POST. You can use POST to pass request parameters not
+         fitting into the URL.
+         
+         addHttpRequestToContext - if set to true, it will instruct
+         the requestParsers to include the original HttpServletRequest
+         object in the context map of the SolrQueryRequest under the 
+         key "httpRequest". It will not be used by any of the existing
+         Solr components, but may be useful when developing custom 
+         plugins.
+         
+         *** WARNING ***
+         Before enabling remote streaming, you should make sure your
+         system has authentication enabled.
+
+    <requestParsers enableRemoteStreaming="false"
+                    multipartUploadLimitInKB="-1"
+                    formdataUploadLimitInKB="-1"
+                    addHttpRequestToContext="false"/>
+      -->
+
+    <!-- HTTP Caching
+
+         Set HTTP caching related parameters (for proxy caches and clients).
+
+         The options below instruct Solr not to output any HTTP Caching
+         related headers
+      -->
+    <httpCaching never304="true" />
+    <!-- If you include a <cacheControl> directive, it will be used to
+         generate a Cache-Control header (as well as an Expires header
+         if the value contains "max-age=")
+         
+         By default, no Cache-Control header is generated.
+         
+         You can use the <cacheControl> option even if you have set
+         never304="true"
+      -->
+    <!--
+       <httpCaching never304="true" >
+         <cacheControl>max-age=30, public</cacheControl> 
+       </httpCaching>
+      -->
+    <!-- To enable Solr to respond with automatically generated HTTP
+         Caching headers, and to response to Cache Validation requests
+         correctly, set the value of never304="false"
+         
+         This will cause Solr to generate Last-Modified and ETag
+         headers based on the properties of the Index.
 
-  <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
+         The following options can also be specified to affect the
+         values of these headers...
 
-  <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
+         lastModFrom - the default value is "openTime" which means the
+         Last-Modified value (and validation against If-Modified-Since
+         requests) will all be relative to when the current Searcher
+         was opened.  You can change it to lastModFrom="dirLastMod" if
+         you want the value to exactly correspond to when the physical
+         index was last modified.
 
-  <requestHandler name="my_error_handler" class="solr.ThrowErrorOnInitRequestHandler">
-    <str name="error">This is the _default configset, which is designed to throw error upon collection creation from unit tests. If you see this error while running a unit test, you might want to explicitly specify the configset (when creating a collection) you intend to use (usually named "conf1" or "conf" etc.).</str>
+         etagSeed="..." is an option you can change to force the ETag
+         header (and validation against If-None-Match requests) to be
+         different even if the index has not changed (ie: when making
+         significant changes to your config file)
+
+         (lastModifiedFrom and etagSeed are both ignored if you use
+         the never304="true" option)
+      -->
+    <!--
+       <httpCaching lastModifiedFrom="openTime"
+                    etagSeed="Solr">
+         <cacheControl>max-age=30, public</cacheControl> 
+       </httpCaching>
+      -->
+  </requestDispatcher>
+
+  <!-- Request Handlers 
+
+       http://wiki.apache.org/solr/SolrRequestHandler
+
+       Incoming queries will be dispatched to a specific handler by name
+       based on the path specified in the request.
+
+       If a Request Handler is declared with startup="lazy", then it will
+       not be initialized until the first request that uses it.
+
+    -->
+  <!-- SearchHandler
+
+       http://wiki.apache.org/solr/SearchHandler
+
+       For processing Search Queries, the primary Request Handler
+       provided with Solr is "SearchHandler" It delegates to a sequent
+       of SearchComponents (see below) and supports distributed
+       queries across multiple shards
+    -->
+  <requestHandler name="/select" class="solr.SearchHandler">
+    <!-- default values for query parameters can be specified, these
+         will be overridden by parameters in the request
+      -->
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <int name="rows">10</int>
+      <!-- <str name="df">text</str> -->
+    </lst>
+    <!-- In addition to defaults, "appends" params can be specified
+         to identify values which should be appended to the list of
+         multi-val params from the query (or the existing "defaults").
+      -->
+    <!-- In this example, the param "fq=instock:true" would be appended to
+         any query time fq params the user may specify, as a mechanism for
+         partitioning the index, independent of any user selected filtering
+         that may also be desired (perhaps as a result of faceted searching).
+
+         NOTE: there is *absolutely* nothing a client can do to prevent these
+         "appends" values from being used, so don't use this mechanism
+         unless you are sure you always want it.
+      -->
+    <!--
+       <lst name="appends">
+         <str name="fq">inStock:true</str>
+       </lst>
+      -->
+    <!-- "invariants" are a way of letting the Solr maintainer lock down
+         the options available to Solr clients.  Any params values
+         specified here are used regardless of what values may be specified
+         in either the query, the "defaults", or the "appends" params.
+
+         In this example, the facet.field and facet.query params would
+         be fixed, limiting the facets clients can use.  Faceting is
+         not turned on by default - but if the client does specify
+         facet=true in the request, these are the only facets they
+         will be able to see counts for; regardless of what other
+         facet.field or facet.query params they may specify.
+
+         NOTE: there is *absolutely* nothing a client can do to prevent these
+         "invariants" values from being used, so don't use this mechanism
+         unless you are sure you always want it.
+      -->
+    <!--
+       <lst name="invariants">
+         <str name="facet.field">cat</str>
+         <str name="facet.field">manu_exact</str>
+         <str name="facet.query">price:[* TO 500]</str>
+         <str name="facet.query">price:[500 TO *]</str>
+       </lst>
+      -->
+    <!-- If the default list of SearchComponents is not desired, that
+         list can either be overridden completely, or components can be
+         prepended or appended to the default list.  (see below)
+      -->
+    <!--
+       <arr name="components">
+         <str>nameOfCustomComponent1</str>
+         <str>nameOfCustomComponent2</str>
+       </arr>
+      -->
+  </requestHandler>
+
+  <!-- A request handler that returns indented JSON by default -->
+  <requestHandler name="/query" class="solr.SearchHandler">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <str name="wt">json</str>
+      <str name="indent">true</str>
+    </lst>
+  </requestHandler>
+
+
+  <!-- A Robust Example
+       
+       This example SearchHandler declaration shows off usage of the
+       SearchHandler with many defaults declared
+
+       Note that multiple instances of the same Request Handler
+       (SearchHandler) can be registered multiple times with different
+       names (and different init parameters)
+    -->
+  <requestHandler name="/browse" class="solr.SearchHandler" useParams="query,facets,velocity,browse">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+    </lst>
+  </requestHandler>
+
+  <initParams path="/update/**,/query,/select,/tvrh,/elevate,/spell,/browse">
+    <lst name="defaults">
+      <str name="df">_text_</str>
+    </lst>
+  </initParams>
+
+  <!-- Solr Cell Update Request Handler
+
+       http://wiki.apache.org/solr/ExtractingRequestHandler 
+
+    -->
+  <requestHandler name="/update/extract"
+                  startup="lazy"
+                  class="solr.extraction.ExtractingRequestHandler" >
+    <lst name="defaults">
+      <str name="lowernames">true</str>
+      <str name="fmap.meta">ignored_</str>
+      <str name="fmap.content">_text_</str>
+    </lst>
+  </requestHandler>
+
+  <!-- Search Components
+
+       Search components are registered to SolrCore and used by 
+       instances of SearchHandler (which can access them by name)
+       
+       By default, the following components are available:
+       
+       <searchComponent name="query"     class="solr.QueryComponent" />
+       <searchComponent name="facet"     class="solr.FacetComponent" />
+       <searchComponent name="mlt"       class="solr.MoreLikeThisComponent" />
+       <searchComponent name="highlight" class="solr.HighlightComponent" />
+       <searchComponent name="stats"     class="solr.StatsComponent" />
+       <searchComponent name="debug"     class="solr.DebugComponent" />
+   
+       Default configuration in a requestHandler would look like:
+
+       <arr name="components">
+         <str>query</str>
+         <str>facet</str>
+         <str>mlt</str>
+         <str>highlight</str>
+         <str>stats</str>
+         <str>debug</str>
+       </arr>
+
+       If you register a searchComponent to one of the standard names, 
+       that will be used instead of the default.
+
+       To insert components before or after the 'standard' components, use:
+    
+       <arr name="first-components">
+         <str>myFirstComponentName</str>
+       </arr>
+    
+       <arr name="last-components">
+         <str>myLastComponentName</str>
+       </arr>
+
+       NOTE: The component registered with the name "debug" will
+       always be executed after the "last-components" 
+       
+     -->
+
+  <!-- Spell Check
+
+       The spell check component can return a list of alternative spelling
+       suggestions.  
+
+       http://wiki.apache.org/solr/SpellCheckComponent
+    -->
+  <searchComponent name="spellcheck" class="solr.SpellCheckComponent">
+
+    <str name="queryAnalyzerFieldType">text_general</str>
+
+    <!-- Multiple "Spell Checkers" can be declared and used by this
+         component
+      -->
+
+    <!-- a spellchecker built from a field of the main index -->
+    <lst name="spellchecker">
+      <str name="name">default</str>
+      <str name="field">_text_</str>
+      <str name="classname">solr.DirectSolrSpellChecker</str>
+      <!-- the spellcheck distance measure used, the default is the internal levenshtein -->
+      <str name="distanceMeasure">internal</str>
+      <!-- minimum accuracy needed to be considered a valid spellcheck suggestion -->
+      <float name="accuracy">0.5</float>
+      <!-- the maximum #edits we consider when enumerating terms: can be 1 or 2 -->
+      <int name="maxEdits">2</int>
+      <!-- the minimum shared prefix when enumerating terms -->
+      <int name="minPrefix">1</int>
+      <!-- maximum number of inspections per result. -->
+      <int name="maxInspections">5</int>
+      <!-- minimum length of a query term to be considered for correction -->
+      <int name="minQueryLength">4</int>
+      <!-- maximum threshold of documents a query term can appear to be considered for correction -->
+      <float name="maxQueryFrequency">0.01</float>
+      <!-- uncomment this to require suggestions to occur in 1% of the documents
+        <float name="thresholdTokenFrequency">.01</float>
+      -->
+    </lst>
+
+    <!-- a spellchecker that can break or combine words.  See "/spell" handler below for usage -->
+    <!--
+    <lst name="spellchecker">
+      <str name="name">wordbreak</str>
+      <str name="classname">solr.WordBreakSolrSpellChecker</str>
+      <str name="field">name</str>
+      <str name="combineWords">true</str>
+      <str name="breakWords">true</str>
+      <int name="maxChanges">10</int>
+    </lst>
+    -->
+  </searchComponent>
+
+  <!-- A request handler for demonstrating the spellcheck component.  
+
+       NOTE: This is purely as an example.  The whole purpose of the
+       SpellCheckComponent is to hook it into the request handler that
+       handles your normal user queries so that a separate request is
+       not needed to get suggestions.
+
+       IN OTHER WORDS, THERE IS REALLY GOOD CHANCE THE SETUP BELOW IS
+       NOT WHAT YOU WANT FOR YOUR PRODUCTION SYSTEM!
+       
+       See http://wiki.apache.org/solr/SpellCheckComponent for details
+       on the request parameters.
+    -->
+  <requestHandler name="/spell" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <!-- Solr will use suggestions from both the 'default' spellchecker
+           and from the 'wordbreak' spellchecker and combine them.
+           collations (re-written queries) can include a combination of
+           corrections from both spellcheckers -->
+      <str name="spellcheck.dictionary">default</str>
+      <str name="spellcheck">on</str>
+      <str name="spellcheck.extendedResults">true</str>
+      <str name="spellcheck.count">10</str>
+      <str name="spellcheck.alternativeTermCount">5</str>
+      <str name="spellcheck.maxResultsForSuggest">5</str>
+      <str name="spellcheck.collate">true</str>
+      <str name="spellcheck.collateExtendedResults">true</str>
+      <str name="spellcheck.maxCollationTries">10</str>
+      <str name="spellcheck.maxCollations">5</str>
+    </lst>
+    <arr name="last-components">
+      <str>spellcheck</str>
+    </arr>
+  </requestHandler>
+
+  <!-- Term Vector Component
+
+       http://wiki.apache.org/solr/TermVectorComponent
+    -->
+  <searchComponent name="tvComponent" class="solr.TermVectorComponent"/>
+
+  <!-- A request handler for demonstrating the term vector component
+
+       This is purely as an example.
+
+       In reality you will likely want to add the component to your 
+       already specified request handlers. 
+    -->
+  <requestHandler name="/tvrh" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <bool name="tv">true</bool>
+    </lst>
+    <arr name="last-components">
+      <str>tvComponent</str>
+    </arr>
   </requestHandler>
 
-  <schemaFactory class="ClassicIndexSchemaFactory"/>
+  <!-- Clustering Component. (Omitted here. See the default Solr example for a typical configuration.) -->
+
+  <!-- Terms Component
+
+       http://wiki.apache.org/solr/TermsComponent
+
+       A component to return terms and document frequency of those
+       terms
+    -->
+  <searchComponent name="terms" class="solr.TermsComponent"/>
+
+  <!-- A request handler for demonstrating the terms component -->
+  <requestHandler name="/terms" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <bool name="terms">true</bool>
+      <bool name="distrib">false</bool>
+    </lst>
+    <arr name="components">
+      <str>terms</str>
+    </arr>
+  </requestHandler>
+
+
+  <!-- Query Elevation Component
+
+       http://wiki.apache.org/solr/QueryElevationComponent
+
+       a search component that enables you to configure the top
+       results for a given query regardless of the normal lucene
+       scoring.
+    -->
+  <searchComponent name="elevator" class="solr.QueryElevationComponent" >
+    <!-- pick a fieldType to analyze queries -->
+    <str name="queryFieldType">string</str>
+    <str name="config-file">elevate.xml</str>
+  </searchComponent>
+
+  <!-- A request handler for demonstrating the elevator component -->
+  <requestHandler name="/elevate" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+    </lst>
+    <arr name="last-components">
+      <str>elevator</str>
+    </arr>
+  </requestHandler>
+
+  <!-- Highlighting Component
+
+       http://wiki.apache.org/solr/HighlightingParameters
+    -->
+  <searchComponent class="solr.HighlightComponent" name="highlight">
+    <highlighting>
+      <!-- Configure the standard fragmenter -->
+      <!-- This could most likely be commented out in the "default" case -->
+      <fragmenter name="gap"
+                  default="true"
+                  class="solr.highlight.GapFragmenter">
+        <lst name="defaults">
+          <int name="hl.fragsize">100</int>
+        </lst>
+      </fragmenter>
+
+      <!-- A regular-expression-based fragmenter 
+           (for sentence extraction) 
+        -->
+      <fragmenter name="regex"
+                  class="solr.highlight.RegexFragmenter">
+        <lst name="defaults">
+          <!-- slightly smaller fragsizes work better because of slop -->
+          <int name="hl.fragsize">70</int>
+          <!-- allow 50% slop on fragment sizes -->
+          <float name="hl.regex.slop">0.5</float>
+          <!-- a basic sentence pattern -->
+          <str name="hl.regex.pattern">[-\w ,/\n\&quot;&apos;]{20,200}</str>
+        </lst>
+      </fragmenter>
+
+      <!-- Configure the standard formatter -->
+      <formatter name="html"
+                 default="true"
+                 class="solr.highlight.HtmlFormatter">
+        <lst name="defaults">
+          <str name="hl.simple.pre"><![CDATA[<em>]]></str>
+          <str name="hl.simple.post"><![CDATA[</em>]]></str>
+        </lst>
+      </formatter>
+
+      <!-- Configure the standard encoder -->
+      <encoder name="html"
+               class="solr.highlight.HtmlEncoder" />
+
+      <!-- Configure the standard fragListBuilder -->
+      <fragListBuilder name="simple"
+                       class="solr.highlight.SimpleFragListBuilder"/>
+
+      <!-- Configure the single fragListBuilder -->
+      <fragListBuilder name="single"
+                       class="solr.highlight.SingleFragListBuilder"/>
+
+      <!-- Configure the weighted fragListBuilder -->
+      <fragListBuilder name="weighted"
+                       default="true"
+                       class="solr.highlight.WeightedFragListBuilder"/>
+
+      <!-- default tag FragmentsBuilder -->
+      <fragmentsBuilder name="default"
+                        default="true"
+                        class="solr.highlight.ScoreOrderFragmentsBuilder">
+        <!-- 
+        <lst name="defaults">
+          <str name="hl.multiValuedSeparatorChar">/</str>
+        </lst>
+        -->
+      </fragmentsBuilder>
+
+      <!-- multi-colored tag FragmentsBuilder -->
+      <fragmentsBuilder name="colored"
+                        class="solr.highlight.ScoreOrderFragmentsBuilder">
+        <lst name="defaults">
+          <str name="hl.tag.pre"><![CDATA[
+               <b style="background:yellow">,<b style="background:lawgreen">,
+               <b style="background:aquamarine">,<b style="background:magenta">,
+               <b style="background:palegreen">,<b style="background:coral">,
+               <b style="background:wheat">,<b style="background:khaki">,
+               <b style="background:lime">,<b style="background:deepskyblue">]]></str>
+          <str name="hl.tag.post"><![CDATA[</b>]]></str>
+        </lst>
+      </fragmentsBuilder>
+
+      <boundaryScanner name="default"
+                       default="true"
+                       class="solr.highlight.SimpleBoundaryScanner">
+        <lst name="defaults">
+          <str name="hl.bs.maxScan">10</str>
+          <str name="hl.bs.chars">.,!? &#9;&#10;&#13;</str>
+        </lst>
+      </boundaryScanner>
+
+      <boundaryScanner name="breakIterator"
+                       class="solr.highlight.BreakIteratorBoundaryScanner">
+        <lst name="defaults">
+          <!-- type should be one of CHARACTER, WORD(default), LINE and SENTENCE -->
+          <str name="hl.bs.type">WORD</str>
+          <!-- language and country are used when constructing Locale object.  -->
+          <!-- And the Locale object will be used when getting instance of BreakIterator -->
+          <str name="hl.bs.language">en</str>
+          <str name="hl.bs.country">US</str>
+        </lst>
+      </boundaryScanner>
+    </highlighting>
+  </searchComponent>
+
+  <!-- Update Processors
+
+       Chains of Update Processor Factories for dealing with Update
+       Requests can be declared, and then used by name in Update
+       Request Processors
+
+       http://wiki.apache.org/solr/UpdateRequestProcessor
+
+    -->
+  
+  <!-- Add unknown fields to the schema 
+  
+       Field type guessing update processors that will
+       attempt to parse string-typed field values as Booleans, Longs,
+       Doubles, or Dates, and then add schema fields with the guessed
+       field types.  
+       
+       These require that the schema is both managed and mutable, by
+       declaring schemaFactory as ManagedIndexSchemaFactory, with
+       mutable specified as true. 
+       
+       See http://wiki.apache.org/solr/GuessingFieldTypes
+    -->
+  <updateProcessor class="solr.UUIDUpdateProcessorFactory" name="uuid"/>
+  <updateProcessor class="solr.RemoveBlankFieldUpdateProcessorFactory" name="remove-blank"/>
+  <updateProcessor class="solr.FieldNameMutatingUpdateProcessorFactory" name="field-name-mutating">
+    <str name="pattern">[^\w-\.]</str>
+    <str name="replacement">_</str>
+  </updateProcessor>
+  <updateProcessor class="solr.ParseBooleanFieldUpdateProcessorFactory" name="parse-boolean"/>
+  <updateProcessor class="solr.ParseLongFieldUpdateProcessorFactory" name="parse-long"/>
+  <updateProcessor class="solr.ParseDoubleFieldUpdateProcessorFactory" name="parse-double"/>
+  <updateProcessor class="solr.ParseDateFieldUpdateProcessorFactory" name="parse-date">
+    <arr name="format">
+      <str>yyyy-MM-dd'T'HH:mm:ss.SSSZ</str>
+      <str>yyyy-MM-dd'T'HH:mm:ss,SSSZ</str>
+      <str>yyyy-MM-dd'T'HH:mm:ss.SSS</str>
+      <str>yyyy-MM-dd'T'HH:mm:ss,SSS</str>
+      <str>yyyy-MM-dd'T'HH:mm:ssZ</str>
+      <str>yyyy-MM-dd'T'HH:mm:ss</str>
+      <str>yyyy-MM-dd'T'HH:mmZ</str>
+      <str>yyyy-MM-dd'T'HH:mm</str>
+      <str>yyyy-MM-dd HH:mm:ss.SSSZ</str>
+      <str>yyyy-MM-dd HH:mm:ss,SSSZ</str>
+      <str>yyyy-MM-dd HH:mm:ss.SSS</str>
+      <str>yyyy-MM-dd HH:mm:ss,SSS</str>
+      <str>yyyy-MM-dd HH:mm:ssZ</str>
+      <str>yyyy-MM-dd HH:mm:ss</str>
+      <str>yyyy-MM-dd HH:mmZ</str>
+      <str>yyyy-MM-dd HH:mm</str>
+      <str>yyyy-MM-dd</str>
+    </arr>
+  </updateProcessor>
+  <updateProcessor class="solr.AddSchemaFieldsUpdateProcessorFactory" name="add-schema-fields">
+    <str name="defaultFieldType">strings</str>
+    <lst name="typeMapping">
+      <str name="valueClass">java.lang.Boolean</str>
+      <str name="fieldType">booleans</str>
+    </lst>
+    <lst name="typeMapping">
+      <str name="valueClass">java.util.Date</str>
+      <str name="fieldType">pdates</str>
+    </lst>
+    <lst name="typeMapping">
+      <str name="valueClass">java.lang.Long</str>
+      <str name="valueClass">java.lang.Integer</str>
+      <str name="fieldType">plongs</str>
+    </lst>
+    <lst name="typeMapping">
+      <str name="valueClass">java.lang.Number</str>
+      <str name="fieldType">pdoubles</str>
+    </lst>
+  </updateProcessor>
+
+  <!-- The update.autoCreateFields property can be turned to false to disable schemaless mode -->
+  <updateRequestProcessorChain name="add-unknown-fields-to-the-schema" default="${update.autoCreateFields:true}"
+           processor="uuid,remove-blank,field-name-mutating,parse-boolean,parse-long,parse-double,parse-date,add-schema-fields">
+    <processor class="solr.LogUpdateProcessorFactory"/>
+    <processor class="solr.DistributedUpdateProcessorFactory"/>
+    <processor class="solr.RunUpdateProcessorFactory"/>
+  </updateRequestProcessorChain>
+
+  <!-- Deduplication
+
+       An example dedup update processor that creates the "id" field
+       on the fly based on the hash code of some other fields.  This
+       example has overwriteDupes set to false since we are using the
+       id field as the signatureField and Solr will maintain
+       uniqueness based on that anyway.  
+       
+    -->
+  <!--
+     <updateRequestProcessorChain name="dedupe">
+       <processor class="solr.processor.SignatureUpdateProcessorFactory">
+         <bool name="enabled">true</bool>
+         <str name="signatureField">id</str>
+         <bool name="overwriteDupes">false</bool>
+         <str name="fields">name,features,cat</str>
+         <str name="signatureClass">solr.processor.Lookup3Signature</str>
+       </processor>
+       <processor class="solr.LogUpdateProcessorFactory" />
+       <processor class="solr.RunUpdateProcessorFactory" />
+     </updateRequestProcessorChain>
+    -->
+
+  <!-- Language identification
+
+       This example update chain identifies the language of the incoming
+       documents using the langid contrib. The detected language is
+       written to field language_s. No field name mapping is done.
+       The fields used for detection are text, title, subject and description,
+       making this example suitable for detecting languages form full-text
+       rich documents injected via ExtractingRequestHandler.
+       See more about langId at http://wiki.apache.org/solr/LanguageDetection
+    -->
+  <!--
+   <updateRequestProcessorChain name="langid">
+     <processor class="org.apache.solr.update.processor.TikaLanguageIdentifierUpdateProcessorFactory">
+       <str name="langid.fl">text,title,subject,description</str>
+       <str name="langid.langField">language_s</str>
+       <str name="langid.fallback">en</str>
+     </processor>
+     <processor class="solr.LogUpdateProcessorFactory" />
+     <processor class="solr.RunUpdateProcessorFactory" />
+   </updateRequestProcessorChain>
+  -->
+
+  <!-- Script update processor
+
+    This example hooks in an update processor implemented using JavaScript.
+
+    See more about the script update processor at http://wiki.apache.org/solr/ScriptUpdateProcessor
+  -->
+  <!--
+    <updateRequestProcessorChain name="script">
+      <processor class="solr.StatelessScriptUpdateProcessorFactory">
+        <str name="script">update-script.js</str>
+        <lst name="params">
+          <str name="config_param">example config parameter</str>
+        </lst>
+      </processor>
+      <processor class="solr.RunUpdateProcessorFactory" />
+    </updateRequestProcessorChain>
+  -->
+
+  <!-- Response Writers
+
+       http://wiki.apache.org/solr/QueryResponseWriter
+
+       Request responses will be written using the writer specified by
+       the 'wt' request parameter matching the name of a registered
+       writer.
+
+       The "default" writer is the default and will be used if 'wt' is
+       not specified in the request.
+    -->
+  <!-- The following response writers are implicitly configured unless
+       overridden...
+    -->
+  <!--
+     <queryResponseWriter name="xml" 
+                          default="true"
+                          class="solr.XMLResponseWriter" />
+     <queryResponseWriter name="json" class="solr.JSONResponseWriter"/>
+     <queryResponseWriter name="python" class="solr.PythonResponseWriter"/>
+     <queryResponseWriter name="ruby" class="solr.RubyResponseWriter"/>
+     <queryResponseWriter name="php" class="solr.PHPResponseWriter"/>
+     <queryResponseWriter name="phps" class="solr.PHPSerializedResponseWriter"/>
+     <queryResponseWriter name="csv" class="solr.CSVResponseWriter"/>
+     <queryResponseWriter name="schema.xml" class="solr.SchemaXmlResponseWriter"/>
+    -->
+
+  <queryResponseWriter name="json" class="solr.JSONResponseWriter">
+    <!-- For the purposes of the tutorial, JSON responses are written as
+     plain text so that they are easy to read in *any* browser.
+     If you expect a MIME type of "application/json" just remove this override.
+    -->
+    <str name="content-type">text/plain; charset=UTF-8</str>
+  </queryResponseWriter>
+
+  <!--
+     Custom response writers can be declared as needed...
+    -->
+  <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" startup="lazy">
+    <str name="template.base.dir">${velocity.template.base.dir:}</str>
+    <str name="solr.resource.loader.enabled">${velocity.solr.resource.loader.enabled:true}</str>
+    <str name="params.resource.loader.enabled">${velocity.params.resource.loader.enabled:false}</str>
+  </queryResponseWriter>
+
+  <!-- XSLT response writer transforms the XML output by any xslt file found
+       in Solr's conf/xslt directory.  Changes to xslt files are checked for
+       every xsltCacheLifetimeSeconds.  
+    -->
+  <queryResponseWriter name="xslt" class="solr.XSLTResponseWriter">
+    <int name="xsltCacheLifetimeSeconds">5</int>
+  </queryResponseWriter>
+
+  <!-- Query Parsers
+
+       https://cwiki.apache.org/confluence/display/solr/Query+Syntax+and+Parsing
+
+       Multiple QParserPlugins can be registered by name, and then
+       used in either the "defType" param for the QueryComponent (used
+       by SearchHandler) or in LocalParams
+    -->
+  <!-- example of registering a query parser -->
+  <!--
+     <queryParser name="myparser" class="com.mycompany.MyQParserPlugin"/>
+    -->
+
+  <!-- Function Parsers
+
+       http://wiki.apache.org/solr/FunctionQuery
+
+       Multiple ValueSourceParsers can be registered by name, and then
+       used as function names when using the "func" QParser.
+    -->
+  <!-- example of registering a custom function parser  -->
+  <!--
+     <valueSourceParser name="myfunc" 
+                        class="com.mycompany.MyValueSourceParser" />
+    -->
+
+
+  <!-- Document Transformers
+       http://wiki.apache.org/solr/DocTransformers
+    -->
+  <!--
+     Could be something like:
+     <transformer name="db" class="com.mycompany.LoadFromDatabaseTransformer" >
+       <int name="connection">jdbc://....</int>
+     </transformer>
+     
+     To add a constant value to all docs, use:
+     <transformer name="mytrans2" class="org.apache.solr.response.transform.ValueAugmenterFactory" >
+       <int name="value">5</int>
+     </transformer>
+     
+     If you want the user to still be able to change it with _value:something_ use this:
+     <transformer name="mytrans3" class="org.apache.solr.response.transform.ValueAugmenterFactory" >
+       <double name="defaultValue">5</double>
+     </transformer>
 
+      If you are using the QueryElevationComponent, you may wish to mark documents that get boosted.  The
+      EditorialMarkerFactory will do exactly that:
+     <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" />
+    -->
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/stopwords.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/stopwords.txt b/solr/core/src/test-files/solr/configsets/_default/conf/stopwords.txt
new file mode 100644
index 0000000..ae1e83e
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/stopwords.txt
@@ -0,0 +1,14 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/synonyms.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/synonyms.txt b/solr/core/src/test-files/solr/configsets/_default/conf/synonyms.txt
new file mode 100644
index 0000000..eab4ee8
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/synonyms.txt
@@ -0,0 +1,29 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+#some test synonym mappings unlikely to appear in real input text
+aaafoo => aaabar
+bbbfoo => bbbfoo bbbbar
+cccfoo => cccbar cccbaz
+fooaaa,baraaa,bazaaa
+
+# Some synonym groups specific to this example
+GB,gib,gigabyte,gigabytes
+MB,mib,megabyte,megabytes
+Television, Televisions, TV, TVs
+#notice we use "gib" instead of "GiB" so any WordDelimiterGraphFilter coming
+#after us won't split it into two words.
+
+# Synonym mappings can be used for spelling correction too
+pixima => pixma
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
index a4ed93f..f2027b0 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
@@ -62,16 +62,27 @@ public class CollectionsAPISolrJTest extends SolrCloudTestCase {
   @Test
   public void testCreateWithDefaultConfigSet() throws Exception {
     String collectionName = "solrj_default_configset";
-    CollectionAdminResponse response = CollectionAdminRequest.createCollection(collectionName, 2, 2) // no configset specified
+    CollectionAdminResponse response = CollectionAdminRequest.createCollection(collectionName, 2, 2)
         .process(cluster.getSolrClient());
 
-    // The _default configset (for the tests) is designed to error out upon collection creation,
-    // so we just ensure that the correct error message was obtained.
-    assertFalse(response.isSuccess());
-    System.out.println("Errors are: "+response.getErrorMessages());
-    assertTrue(response.getErrorMessages() != null && response.getErrorMessages().size() > 0);
-    assertTrue(response.getErrorMessages().getVal(0).contains("This is the _default configset, which is designed"
-        + " to throw error upon collection creation"));
+    assertEquals(0, response.getStatus());
+    assertTrue(response.isSuccess());
+    Map<String, NamedList<Integer>> coresStatus = response.getCollectionCoresStatus();
+    assertEquals(4, coresStatus.size());
+    for (int i=0; i<4; i++) {
+      NamedList<Integer> status = coresStatus.get(Assign.buildCoreName(collectionName, "shard" + (i/2+1), Replica.Type.NRT, (i%2+1)));
+      assertEquals(0, (int)status.get("status"));
+      assertTrue(status.get("QTime") > 0);
+    }
+
+    response = CollectionAdminRequest.deleteCollection(collectionName).process(cluster.getSolrClient());
+
+    assertEquals(0, response.getStatus());
+    assertTrue(response.isSuccess());
+    Map<String,NamedList<Integer>> nodesStatus = response.getCollectionNodesStatus();
+    assertEquals(4, nodesStatus.size());
+
+    waitForState("Expected " + collectionName + " to disappear from cluster state", collectionName, (n, c) -> c == null);
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
index 27fcfc0..a9e5837 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
@@ -34,6 +34,10 @@ import java.lang.invoke.MethodHandles;
 import java.net.URI;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Deque;
@@ -43,6 +47,7 @@ import java.util.LinkedList;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.nio.file.SimpleFileVisitor;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
@@ -87,6 +92,7 @@ import org.apache.solr.common.util.Utils;
 import org.apache.solr.core.ConfigSetProperties;
 import org.apache.solr.core.TestDynamicLoading;
 import org.apache.solr.security.BasicAuthIntegrationTest;
+import org.apache.solr.util.ExternalPaths;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
 import org.junit.After;
@@ -714,7 +720,46 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 {
 
     solrClient.close();
   }
+  
+  @Test
+  public void testUserAndTestDefaultConfigsetsAreSame() throws IOException {
+    File testDefaultConf = configset("_default").toFile();
+    log.info("Test _default path: " + testDefaultConf);
+    
+    File userDefaultConf = new File(ExternalPaths.DEFAULT_CONFIGSET);
+    log.info("User _default path: " + userDefaultConf);
+    
+    compareDirectories(userDefaultConf, testDefaultConf);
+  }
 
+  private static void compareDirectories(File userDefault, File testDefault) throws IOException {
+    assertTrue("Test _default doesn't exist: " + testDefault.getAbsolutePath(), testDefault.exists());
+    assertTrue("Test _default not a directory: " + testDefault.getAbsolutePath(),testDefault.isDirectory());
+    assertTrue("User _default doesn't exist: " + userDefault.getAbsolutePath(), userDefault.exists());
+    assertTrue("User _default not a directory: " + userDefault.getAbsolutePath(),userDefault.isDirectory());
+
+    Files.walkFileTree(userDefault.toPath(), new SimpleFileVisitor<Path>() {
+      @Override
+      public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+        FileVisitResult result = super.preVisitDirectory(dir, attrs);
+        Path relativePath = userDefault.toPath().relativize(dir);
+        File testDefaultFile = testDefault.toPath().resolve(relativePath).toFile();
+        assertEquals("Mismatch in files", Arrays.toString(dir.toFile().list()), Arrays.toString(testDefaultFile.list()));
+        return result;
+      }
+      @Override
+      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+        FileVisitResult result = super.visitFile(file, attrs);
+        Path relativePath = userDefault.toPath().relativize(file);
+        File testDefaultFile = testDefault.toPath().resolve(relativePath).toFile();
+        String userDefaultContents = FileUtils.readFileToString(file.toFile(), "UTF-8");
+        String testDefaultContents = FileUtils.readFileToString(testDefaultFile, "UTF-8");
+        assertEquals(testDefaultFile+" contents doesn't match expected ("+file+")", userDefaultContents, testDefaultContents);                    
+        return result;
+      }
+    });
+  }
+  
   private StringBuilder getConfigSetProps(Map<String, String> map) {
     return new StringBuilder(new String(Utils.toJSON(map), StandardCharsets.UTF_8));
   }


[55/58] [abbrv] lucene-solr:jira/solr-10879: LUCENE-7888: fix concurrency hazards between merge completing and DV updates applying

Posted by ab...@apache.org.
LUCENE-7888: fix concurrency hazards between merge completing and DV updates applying


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

Branch: refs/heads/jira/solr-10879
Commit: eaf1d45a1cad74a1037c7c4178fd2379a903f8cc
Parents: ee1edd9
Author: Mike McCandless <mi...@apache.org>
Authored: Sun Jul 2 15:58:53 2017 -0400
Committer: Mike McCandless <mi...@apache.org>
Committed: Sun Jul 2 15:58:53 2017 -0400

----------------------------------------------------------------------
 .../lucene/index/FrozenBufferedUpdates.java      | 19 +++++++++++++++----
 .../org/apache/lucene/index/IndexWriter.java     |  5 +++--
 .../apache/lucene/index/ReadersAndUpdates.java   |  8 +++++---
 3 files changed, 23 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/eaf1d45a/lucene/core/src/java/org/apache/lucene/index/FrozenBufferedUpdates.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/FrozenBufferedUpdates.java b/lucene/core/src/java/org/apache/lucene/index/FrozenBufferedUpdates.java
index 8248841..c4e60db 100644
--- a/lucene/core/src/java/org/apache/lucene/index/FrozenBufferedUpdates.java
+++ b/lucene/core/src/java/org/apache/lucene/index/FrozenBufferedUpdates.java
@@ -262,6 +262,8 @@ class FrozenBufferedUpdates {
     int totalSegmentCount = 0;
     long totalDelCount = 0;
 
+    boolean finished = false;
+
     // Optimistic concurrency: assume we are free to resolve the deletes against all current segments in the index, despite that
     // concurrent merges are running.  Once we are done, we check to see if a merge completed while we were running.  If so, we must retry
     // resolving against the newly merged segment(s).  Eventually no merge finishes while we were running and we are done.
@@ -334,7 +336,7 @@ class FrozenBufferedUpdates {
 
       if (infoStream.isEnabled("BD")) {
         infoStream.message("BD", String.format(Locale.ROOT,
-                                               messagePrefix + "done apply del packet (%s) to %d segments; %d new deletes/updates; took %.3f sec",
+                                               messagePrefix + "done inner apply del packet (%s) to %d segments; %d new deletes/updates; took %.3f sec",
                                                this, segStates.length, delCount, (System.nanoTime() - iterStartNS) / 1000000000.));
       }
       
@@ -352,6 +354,13 @@ class FrozenBufferedUpdates {
 
         if (mergeGenCur == mergeGenStart) {
 
+          // Must do this while still holding IW lock else a merge could finish and skip carrying over our updates:
+          
+          // Record that this packet is finished:
+          writer.bufferedUpdatesStream.finished(this);
+
+          finished = true;
+
           // No merge finished while we were applying, so we are done!
           break;
         }
@@ -367,9 +376,11 @@ class FrozenBufferedUpdates {
       iter++;
     }
 
-    // Record that this packet is finished:
-    writer.bufferedUpdatesStream.finished(this);
-
+    if (finished == false) {
+      // Record that this packet is finished:
+      writer.bufferedUpdatesStream.finished(this);
+    }
+        
     if (infoStream.isEnabled("BD")) {
       String message = String.format(Locale.ROOT,
                                      "done apply del packet (%s) to %d segments; %d new deletes/updates; took %.3f sec",

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/eaf1d45a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
index 2ef928b..26a25a5 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
@@ -642,12 +642,13 @@ public class IndexWriter implements Closeable, TwoPhaseCommit, Accountable {
       }
     }
 
-    void writeDocValuesUpdates(List<SegmentCommitInfo> infos) throws IOException {
+    void writeDocValuesUpdatesForMerge(List<SegmentCommitInfo> infos) throws IOException {
       boolean any = false;
       for (SegmentCommitInfo info : infos) {
         ReadersAndUpdates rld = get(info, false);
         if (rld != null) {
           any |= rld.writeFieldUpdates(directory, bufferedUpdatesStream.getCompletedDelGen(), infoStream);
+          rld.setIsMerging();
         }
       }
       if (any) {
@@ -4216,7 +4217,7 @@ public class IndexWriter implements Closeable, TwoPhaseCommit, Accountable {
     // Must move the pending doc values updates to disk now, else the newly merged segment will not see them:
     // TODO: we could fix merging to pull the merged DV iterator so we don't have to move these updates to disk first, i.e. just carry them
     // in memory:
-    readerPool.writeDocValuesUpdates(merge.segments);
+    readerPool.writeDocValuesUpdatesForMerge(merge.segments);
     
     // Bind a new segment name here so even with
     // ConcurrentMergePolicy we keep deterministic segment

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/eaf1d45a/lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java b/lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java
index 630131e..dd49fcb 100644
--- a/lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java
+++ b/lucene/core/src/java/org/apache/lucene/index/ReadersAndUpdates.java
@@ -808,14 +808,16 @@ class ReadersAndUpdates {
     return true;
   }
 
-  /** Returns a reader for merge, with the latest doc values updates and deletions. */
-  synchronized SegmentReader getReaderForMerge(IOContext context) throws IOException {
-
+  synchronized public void setIsMerging() {
     // This ensures any newly resolved doc value updates while we are merging are
     // saved for re-applying after this segment is done merging:
     isMerging = true;
 
     assert mergingDVUpdates.isEmpty();
+  }
+
+  /** Returns a reader for merge, with the latest doc values updates and deletions. */
+  synchronized SegmentReader getReaderForMerge(IOContext context) throws IOException {
 
     // We must carry over any still-pending DV updates because they were not
     // successfully written, e.g. because there was a hole in the delGens,


[34/58] [abbrv] lucene-solr:jira/solr-10879: LUCENE-7838 - removed dep from sandbox, created a minimal FLT version specific for knn classification

Posted by ab...@apache.org.
LUCENE-7838 - removed dep from sandbox, created a minimal FLT version specific for knn classification


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/92e46038
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/92e46038
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/92e46038

Branch: refs/heads/jira/solr-10879
Commit: 92e460389dc9b0af83c445cb029e3a51799a37dc
Parents: 85069cac
Author: Tommaso Teofili <to...@apache.org>
Authored: Thu Jun 29 10:01:49 2017 +0200
Committer: Tommaso Teofili <to...@apache.org>
Committed: Thu Jun 29 10:01:49 2017 +0200

----------------------------------------------------------------------
 .../lucene/classification/classification.iml    |   1 -
 lucene/classification/build.xml                 |   6 +-
 .../classification/KNearestFuzzyClassifier.java |  29 +-
 .../classification/utils/NearestFuzzyQuery.java | 333 +++++++++++++++++++
 .../KNearestFuzzyClassifierTest.java            |   2 +-
 5 files changed, 348 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/92e46038/dev-tools/idea/lucene/classification/classification.iml
----------------------------------------------------------------------
diff --git a/dev-tools/idea/lucene/classification/classification.iml b/dev-tools/idea/lucene/classification/classification.iml
index 44af1e4..25810ed 100644
--- a/dev-tools/idea/lucene/classification/classification.iml
+++ b/dev-tools/idea/lucene/classification/classification.iml
@@ -19,6 +19,5 @@
     <orderEntry type="module" module-name="analysis-common" />
     <orderEntry type="module" module-name="grouping" />
     <orderEntry type="module" module-name="misc" />
-    <orderEntry type="module" module-name="sandbox" />
   </component>
 </module>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/92e46038/lucene/classification/build.xml
----------------------------------------------------------------------
diff --git a/lucene/classification/build.xml b/lucene/classification/build.xml
index af7d2b1..43bcb4b 100644
--- a/lucene/classification/build.xml
+++ b/lucene/classification/build.xml
@@ -28,7 +28,6 @@
     <path refid="base.classpath"/>
     <pathelement path="${queries.jar}"/>
     <pathelement path="${grouping.jar}"/>
-    <pathelement path="${sandbox.jar}"/>
     <pathelement path="${analyzers-common.jar}"/>
   </path>
 
@@ -38,18 +37,17 @@
     <path refid="test.base.classpath"/>
   </path>
 
-  <target name="compile-core" depends="jar-sandbox,jar-grouping,jar-queries,jar-analyzers-common,common.compile-core" />
+  <target name="compile-core" depends="jar-grouping,jar-queries,jar-analyzers-common,common.compile-core" />
 
   <target name="jar-core" depends="common.jar-core" />
 
-  <target name="javadocs" depends="javadocs-sandbox,javadocs-grouping,compile-core,check-javadocs-uptodate"
+  <target name="javadocs" depends="javadocs-grouping,compile-core,check-javadocs-uptodate"
           unless="javadocs-uptodate-${name}">
     <invoke-module-javadoc>
       <links>
         <link href="../queries"/>
         <link href="../analyzers-common"/>
         <link href="../grouping"/>
-        <link href="../sandbox"/>
       </links>
     </invoke-module-javadoc>
   </target>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/92e46038/lucene/classification/src/java/org/apache/lucene/classification/KNearestFuzzyClassifier.java
----------------------------------------------------------------------
diff --git a/lucene/classification/src/java/org/apache/lucene/classification/KNearestFuzzyClassifier.java b/lucene/classification/src/java/org/apache/lucene/classification/KNearestFuzzyClassifier.java
index 7bbdbab..cbd241b 100644
--- a/lucene/classification/src/java/org/apache/lucene/classification/KNearestFuzzyClassifier.java
+++ b/lucene/classification/src/java/org/apache/lucene/classification/KNearestFuzzyClassifier.java
@@ -25,11 +25,11 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.classification.utils.NearestFuzzyQuery;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.sandbox.queries.FuzzyLikeThisQuery;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.IndexSearcher;
@@ -42,7 +42,7 @@ import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.BytesRef;
 
 /**
- * A k-Nearest Neighbor classifier based on {@link FuzzyLikeThisQuery}.
+ * A k-Nearest Neighbor classifier based on {@link NearestFuzzyQuery}.
  *
  * @lucene.experimental
  */
@@ -51,27 +51,27 @@ public class KNearestFuzzyClassifier implements Classifier<BytesRef> {
   /**
    * the name of the fields used as the input text
    */
-  protected final String[] textFieldNames;
+  private final String[] textFieldNames;
 
   /**
    * the name of the field used as the output text
    */
-  protected final String classFieldName;
+  private final String classFieldName;
 
   /**
    * an {@link IndexSearcher} used to perform queries
    */
-  protected final IndexSearcher indexSearcher;
+  private final IndexSearcher indexSearcher;
 
   /**
    * the no. of docs to compare in order to find the nearest neighbor to the input text
    */
-  protected final int k;
+  private final int k;
 
   /**
    * a {@link Query} used to filter the documents that should be used from this classifier's underlying {@link LeafReader}
    */
-  protected final Query query;
+  private final Query query;
   private final Analyzer analyzer;
 
   /**
@@ -145,11 +145,11 @@ public class KNearestFuzzyClassifier implements Classifier<BytesRef> {
 
   private TopDocs knnSearch(String text) throws IOException {
     BooleanQuery.Builder bq = new BooleanQuery.Builder();
-    FuzzyLikeThisQuery fuzzyLikeThisQuery = new FuzzyLikeThisQuery(300, analyzer);
+    NearestFuzzyQuery nearestFuzzyQuery = new NearestFuzzyQuery(analyzer);
     for (String fieldName : textFieldNames) {
-      fuzzyLikeThisQuery.addTerms(text, fieldName, 1f, 2); // TODO: make this parameters configurable
+      nearestFuzzyQuery.addTerms(text, fieldName);
     }
-    bq.add(fuzzyLikeThisQuery, BooleanClause.Occur.MUST);
+    bq.add(nearestFuzzyQuery, BooleanClause.Occur.MUST);
     Query classFieldQuery = new WildcardQuery(new Term(classFieldName, "*"));
     bq.add(new BooleanClause(classFieldQuery, BooleanClause.Occur.MUST));
     if (query != null) {
@@ -165,7 +165,7 @@ public class KNearestFuzzyClassifier implements Classifier<BytesRef> {
    * @return a {@link List} of {@link ClassificationResult}, one for each existing class
    * @throws IOException if it's not possible to get the stored value of class field
    */
-  protected List<ClassificationResult<BytesRef>> buildListFromTopDocs(TopDocs topDocs) throws IOException {
+  private List<ClassificationResult<BytesRef>> buildListFromTopDocs(TopDocs topDocs) throws IOException {
     Map<BytesRef, Integer> classCounts = new HashMap<>();
     Map<BytesRef, Double> classBoosts = new HashMap<>(); // this is a boost based on class ranking positions in topDocs
     float maxScore = topDocs.getMaxScore();
@@ -174,12 +174,7 @@ public class KNearestFuzzyClassifier implements Classifier<BytesRef> {
       if (storableField != null) {
         BytesRef cl = new BytesRef(storableField.stringValue());
         //update count
-        Integer count = classCounts.get(cl);
-        if (count != null) {
-          classCounts.put(cl, count + 1);
-        } else {
-          classCounts.put(cl, 1);
-        }
+        classCounts.merge(cl, 1, (a, b) -> a + b);
         //update boost, the boost is based on the best score
         Double totalBoost = classBoosts.get(cl);
         double singleBoost = scoreDoc.score / maxScore;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/92e46038/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java
----------------------------------------------------------------------
diff --git a/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java b/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java
new file mode 100644
index 0000000..d4a2634
--- /dev/null
+++ b/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java
@@ -0,0 +1,333 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.classification.utils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Objects;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.MultiFields;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.Terms;
+import org.apache.lucene.index.TermsEnum;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.BoostAttribute;
+import org.apache.lucene.search.BoostQuery;
+import org.apache.lucene.search.FuzzyTermsEnum;
+import org.apache.lucene.search.MaxNonCompetitiveBoostAttribute;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.util.AttributeSource;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.PriorityQueue;
+import org.apache.lucene.util.automaton.LevenshteinAutomata;
+
+/**
+ * Simplification of FuzzyLikeThisQuery, to be used in the context of KNN classification.
+ */
+public class NearestFuzzyQuery extends Query {
+
+  private final ArrayList<FieldVals> fieldVals = new ArrayList<>();
+  private final Analyzer analyzer;
+
+  // fixed parameters
+  private static final int MAX_VARIANTS_PER_TERM = 50;
+  private static final float MIN_SIMILARITY = 1f;
+  private static final int PREFIX_LENGTH = 2;
+  private static final int MAX_NUM_TERMS = 300;
+
+  /**
+   * Default constructor
+   *
+   * @param analyzer the analyzer used to proecss the query text
+   */
+  public NearestFuzzyQuery(Analyzer analyzer) {
+    this.analyzer = analyzer;
+  }
+
+  static class FieldVals {
+    final String queryString;
+    final String fieldName;
+    final int maxEdits;
+    final int prefixLength;
+
+    FieldVals(String name, int maxEdits, String queryString) {
+      this.fieldName = name;
+      this.maxEdits = maxEdits;
+      this.queryString = queryString;
+      this.prefixLength = NearestFuzzyQuery.PREFIX_LENGTH;
+    }
+
+    @Override
+    public int hashCode() {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result
+          + ((fieldName == null) ? 0 : fieldName.hashCode());
+      result = prime * result + maxEdits;
+      result = prime * result + prefixLength;
+      result = prime * result
+          + ((queryString == null) ? 0 : queryString.hashCode());
+      return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if (this == obj)
+        return true;
+      if (obj == null)
+        return false;
+      if (getClass() != obj.getClass())
+        return false;
+      FieldVals other = (FieldVals) obj;
+      if (fieldName == null) {
+        if (other.fieldName != null)
+          return false;
+      } else if (!fieldName.equals(other.fieldName))
+        return false;
+      if (maxEdits != other.maxEdits) {
+        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;
+    }
+
+
+  }
+
+  /**
+   * Adds user input for "fuzzification"
+   *
+   * @param queryString The string which will be parsed by the analyzer and for which fuzzy variants will be parsed
+   */
+  public void addTerms(String queryString, String fieldName) {
+    int maxEdits = (int) MIN_SIMILARITY;
+    if (maxEdits != MIN_SIMILARITY) {
+      throw new IllegalArgumentException("MIN_SIMILARITY must integer value between 0 and " + LevenshteinAutomata.MAXIMUM_SUPPORTED_DISTANCE + ", inclusive; got " + MIN_SIMILARITY);
+    }
+    fieldVals.add(new FieldVals(fieldName, maxEdits, queryString));
+  }
+
+
+  private void addTerms(IndexReader reader, FieldVals f, ScoreTermQueue q) throws IOException {
+    if (f.queryString == null) return;
+    final Terms terms = MultiFields.getTerms(reader, f.fieldName);
+    if (terms == null) {
+      return;
+    }
+    try (TokenStream ts = analyzer.tokenStream(f.fieldName, f.queryString)) {
+      CharTermAttribute termAtt = ts.addAttribute(CharTermAttribute.class);
+
+      int corpusNumDocs = reader.numDocs();
+      HashSet<String> processedTerms = new HashSet<>();
+      ts.reset();
+      while (ts.incrementToken()) {
+        String term = termAtt.toString();
+        if (!processedTerms.contains(term)) {
+          processedTerms.add(term);
+          ScoreTermQueue variantsQ = new ScoreTermQueue(MAX_VARIANTS_PER_TERM); //maxNum variants considered for any one term
+          float minScore = 0;
+          Term startTerm = new Term(f.fieldName, term);
+          AttributeSource atts = new AttributeSource();
+          MaxNonCompetitiveBoostAttribute maxBoostAtt =
+              atts.addAttribute(MaxNonCompetitiveBoostAttribute.class);
+          FuzzyTermsEnum fe = new FuzzyTermsEnum(terms, atts, startTerm, f.maxEdits, f.prefixLength, true);
+          //store the df so all variants use same idf
+          int df = reader.docFreq(startTerm);
+          int numVariants = 0;
+          int totalVariantDocFreqs = 0;
+          BytesRef possibleMatch;
+          BoostAttribute boostAtt =
+              fe.attributes().addAttribute(BoostAttribute.class);
+          while ((possibleMatch = fe.next()) != null) {
+            numVariants++;
+            totalVariantDocFreqs += fe.docFreq();
+            float score = boostAtt.getBoost();
+            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; // maintain minScore
+            }
+            maxBoostAtt.setMaxNonCompetitiveBoost(variantsQ.size() >= MAX_VARIANTS_PER_TERM ? minScore : Float.NEGATIVE_INFINITY);
+          }
+
+          if (numVariants > 0) {
+            int avgDf = totalVariantDocFreqs / numVariants;
+            if (df == 0)//no direct match we can use as df for all variants
+            {
+              df = avgDf; //use avg df of all variants
+            }
+
+            // take the top variants (scored by edit distance) and reset the score
+            // to include an IDF factor then add to the global queue for ranking
+            // overall top query terms
+            int size = variantsQ.size();
+            for (int i = 0; i < size; i++) {
+              ScoreTerm st = variantsQ.pop();
+              if (st != null) {
+                st.score = (st.score * st.score) * idf(df, corpusNumDocs);
+                q.insertWithOverflow(st);
+              }
+            }
+          }
+        }
+      }
+      ts.end();
+    }
+  }
+
+  private float idf(int docFreq, int docCount) {
+    return (float)(Math.log((docCount+1)/(double)(docFreq+1)) + 1.0);
+  }
+
+  private Query newTermQuery(IndexReader reader, Term term) throws IOException {
+    // we build an artificial TermContext that will give an overall df and ttf
+    // equal to 1
+    TermContext context = new TermContext(reader.getContext());
+    for (LeafReaderContext leafContext : reader.leaves()) {
+      Terms terms = leafContext.reader().terms(term.field());
+      if (terms != null) {
+        TermsEnum termsEnum = terms.iterator();
+        if (termsEnum.seekExact(term.bytes())) {
+          int freq = 1 - context.docFreq(); // we want the total df and ttf to be 1
+          context.register(termsEnum.termState(), leafContext.ord, freq, freq);
+        }
+      }
+    }
+    return new TermQuery(term, context);
+  }
+
+  @Override
+  public Query rewrite(IndexReader reader) throws IOException {
+    ScoreTermQueue q = new ScoreTermQueue(MAX_NUM_TERMS);
+    //load up the list of possible terms
+    for (FieldVals f : fieldVals) {
+      addTerms(reader, f, q);
+    }
+
+    BooleanQuery.Builder bq = new BooleanQuery.Builder();
+
+    //create BooleanQueries to hold the variants for each token/field pair and ensure it
+    // has no coord factor
+    //Step 1: sort the termqueries by term/field
+    HashMap<Term, ArrayList<ScoreTerm>> variantQueries = new HashMap<>();
+    int size = q.size();
+    for (int i = 0; i < size; i++) {
+      ScoreTerm st = q.pop();
+      if (st != null) {
+        ArrayList<ScoreTerm> l = variantQueries.computeIfAbsent(st.fuzziedSourceTerm, k -> new ArrayList<>());
+        l.add(st);
+      }
+    }
+    //Step 2: Organize the sorted termqueries into zero-coord scoring boolean queries
+    for (ArrayList<ScoreTerm> variants : variantQueries.values()) {
+      if (variants.size() == 1) {
+        //optimize where only one selected variant
+        ScoreTerm st = variants.get(0);
+        Query tq = newTermQuery(reader, st.term);
+        // set the boost to a mix of IDF and score
+        bq.add(new BoostQuery(tq, st.score), BooleanClause.Occur.SHOULD);
+      } else {
+        BooleanQuery.Builder termVariants = new BooleanQuery.Builder();
+        for (ScoreTerm st : variants) {
+          // found a match
+          Query tq = newTermQuery(reader, st.term);
+          // set the boost using the ScoreTerm's score
+          termVariants.add(new BoostQuery(tq, st.score), BooleanClause.Occur.SHOULD);          // add to query
+        }
+        bq.add(termVariants.build(), BooleanClause.Occur.SHOULD);          // add to query
+      }
+    }
+    //TODO possible alternative step 3 - organize above booleans into a new layer of field-based
+    // booleans with a minimum-should-match of NumFields-1?
+    return bq.build();
+  }
+
+  //Holds info for a fuzzy term variant - initially score is set to edit distance (for ranking best
+  // term variants) then is reset with IDF for use in ranking against all other
+  // terms/fields
+  private static class ScoreTerm {
+    public final Term term;
+    public float score;
+    final Term fuzziedSourceTerm;
+
+    ScoreTerm(Term term, float score, Term fuzziedSourceTerm) {
+      this.term = term;
+      this.score = score;
+      this.fuzziedSourceTerm = fuzziedSourceTerm;
+    }
+  }
+
+  private static class ScoreTermQueue extends PriorityQueue<ScoreTerm> {
+    ScoreTermQueue(int size) {
+      super(size);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.lucene.util.PriorityQueue#lessThan(java.lang.Object, java.lang.Object)
+     */
+    @Override
+    protected boolean lessThan(ScoreTerm termA, ScoreTerm termB) {
+      if (termA.score == termB.score)
+        return termA.term.compareTo(termB.term) > 0;
+      else
+        return termA.score < termB.score;
+    }
+
+  }
+
+  @Override
+  public String toString(String field) {
+    return null;
+  }
+
+  @Override
+  public int hashCode() {
+    int prime = 31;
+    int result = classHash();
+    result = prime * result + Objects.hashCode(analyzer);
+    result = prime * result + Objects.hashCode(fieldVals);
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object other) {
+    return sameClassAs(other) &&
+        equalsTo(getClass().cast(other));
+  }
+
+  private boolean equalsTo(NearestFuzzyQuery other) {
+    return Objects.equals(analyzer, other.analyzer) &&
+        Objects.equals(fieldVals, other.fieldVals);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/92e46038/lucene/classification/src/test/org/apache/lucene/classification/KNearestFuzzyClassifierTest.java
----------------------------------------------------------------------
diff --git a/lucene/classification/src/test/org/apache/lucene/classification/KNearestFuzzyClassifierTest.java b/lucene/classification/src/test/org/apache/lucene/classification/KNearestFuzzyClassifierTest.java
index 1f70eb4..5c5122a 100644
--- a/lucene/classification/src/test/org/apache/lucene/classification/KNearestFuzzyClassifierTest.java
+++ b/lucene/classification/src/test/org/apache/lucene/classification/KNearestFuzzyClassifierTest.java
@@ -28,7 +28,7 @@ import org.apache.lucene.util.BytesRef;
 import org.junit.Test;
 
 /**
- * Testcase for {@link KNearestFuzzyClassifier}
+ * Tests for {@link KNearestFuzzyClassifier}
  */
 public class KNearestFuzzyClassifierTest extends ClassificationTestBase<BytesRef> {
 


[35/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10973: Use the correct constructor for InputStreamBody.

Posted by ab...@apache.org.
SOLR-10973: Use the correct constructor for InputStreamBody.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/224f3498
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/224f3498
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/224f3498

Branch: refs/heads/jira/solr-10879
Commit: 224f349857889d4ac8493cce0008eb51a2b7cb9b
Parents: 3291ef8
Author: Karl Wright <Da...@gmail.com>
Authored: Thu Jun 29 04:58:51 2017 -0400
Committer: Karl Wright <Da...@gmail.com>
Committed: Thu Jun 29 04:58:51 2017 -0400

----------------------------------------------------------------------
 .../src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/224f3498/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
index c1e9576..6ea4201 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
@@ -421,7 +421,7 @@ public class HttpSolrClient extends SolrClient {
             parts.add(new FormBodyPart(name,
                 new InputStreamBody(
                     content.getStream(),
-                    contentType,
+                    ContentType.parse(contentType),
                     content.getName())));
           }
         }


[54/58] [abbrv] lucene-solr:jira/solr-10879: LUCENE-7894: make sure IW finishes segment flush so we don't see a temporary drop in IW.maxDoc()

Posted by ab...@apache.org.
LUCENE-7894: make sure IW finishes segment flush so we don't see a temporary drop in IW.maxDoc()


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

Branch: refs/heads/jira/solr-10879
Commit: ee1edd9d467bbccfe7015ec5ebee93f8b5bd4b14
Parents: 80ae5e2
Author: Mike McCandless <mi...@apache.org>
Authored: Sun Jul 2 15:32:44 2017 -0400
Committer: Mike McCandless <mi...@apache.org>
Committed: Sun Jul 2 15:32:44 2017 -0400

----------------------------------------------------------------------
 .../apache/lucene/index/DocumentsWriter.java    | 20 +++---
 .../lucene/index/DocumentsWriterFlushQueue.java |  4 ++
 .../lucene/index/TestIndexManyDocuments.java    | 71 ++++++++++++++++++++
 3 files changed, 86 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ee1edd9d/lucene/core/src/java/org/apache/lucene/index/DocumentsWriter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/DocumentsWriter.java b/lucene/core/src/java/org/apache/lucene/index/DocumentsWriter.java
index 27e28c0..0e2a067 100644
--- a/lucene/core/src/java/org/apache/lucene/index/DocumentsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/index/DocumentsWriter.java
@@ -544,11 +544,11 @@ final class DocumentsWriter implements Closeable, Accountable {
             dwptSuccess = true;
           } finally {
             subtractFlushedNumDocs(flushingDocsInRam);
-            if (!flushingDWPT.pendingFilesToDelete().isEmpty()) {
+            if (flushingDWPT.pendingFilesToDelete().isEmpty() == false) {
               putEvent(new DeleteNewFilesEvent(flushingDWPT.pendingFilesToDelete()));
               hasEvents = true;
             }
-            if (!dwptSuccess) {
+            if (dwptSuccess == false) {
               putEvent(new FlushFailedEvent(flushingDWPT.getSegmentInfo()));
               hasEvents = true;
             }
@@ -582,6 +582,10 @@ final class DocumentsWriter implements Closeable, Accountable {
       flushingDWPT = flushControl.nextPendingFlush();
     }
 
+    if (hasEvents) {
+      writer.doAfterSegmentFlushed(false, false);
+    }
+
     // If deletes alone are consuming > 1/2 our RAM
     // buffer, force them all to apply now. This is to
     // prevent too-frequent flushing of a long tail of
@@ -605,7 +609,7 @@ final class DocumentsWriter implements Closeable, Accountable {
   
   void subtractFlushedNumDocs(int numFlushed) {
     int oldValue = numDocsInRAM.get();
-    while (!numDocsInRAM.compareAndSet(oldValue, oldValue - numFlushed)) {
+    while (numDocsInRAM.compareAndSet(oldValue, oldValue - numFlushed) == false) {
       oldValue = numDocsInRAM.get();
     }
     assert numDocsInRAM.get() >= 0;
@@ -726,10 +730,9 @@ final class DocumentsWriter implements Closeable, Accountable {
 
   static final class ApplyDeletesEvent implements Event {
     static final Event INSTANCE = new ApplyDeletesEvent();
-    private int instCount = 0;
+
     private ApplyDeletesEvent() {
-      assert instCount == 0;
-      instCount++;
+      // only one instance
     }
     
     @Override
@@ -740,10 +743,9 @@ final class DocumentsWriter implements Closeable, Accountable {
 
   static final class ForcedPurgeEvent implements Event {
     static final Event INSTANCE = new ForcedPurgeEvent();
-    private int instCount = 0;
+
     private ForcedPurgeEvent() {
-      assert instCount == 0;
-      instCount++;
+      // only one instance
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ee1edd9d/lucene/core/src/java/org/apache/lucene/index/DocumentsWriterFlushQueue.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/DocumentsWriterFlushQueue.java b/lucene/core/src/java/org/apache/lucene/index/DocumentsWriterFlushQueue.java
index df1b38c..b051545 100644
--- a/lucene/core/src/java/org/apache/lucene/index/DocumentsWriterFlushQueue.java
+++ b/lucene/core/src/java/org/apache/lucene/index/DocumentsWriterFlushQueue.java
@@ -119,6 +119,10 @@ class DocumentsWriterFlushQueue {
           synchronized (this) {
             // finally remove the published ticket from the queue
             final FlushTicket poll = queue.poll();
+
+            // we hold the purgeLock so no other thread should have polled:
+            assert poll == head;
+            
             ticketCount.decrementAndGet();
             assert poll == head;
           }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/ee1edd9d/lucene/core/src/test/org/apache/lucene/index/TestIndexManyDocuments.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexManyDocuments.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexManyDocuments.java
new file mode 100644
index 0000000..eb31e73
--- /dev/null
+++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexManyDocuments.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.lucene.index;
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.IOUtils;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.TestUtil;
+
+public class TestIndexManyDocuments extends LuceneTestCase {
+
+  public void test() throws Exception {
+    Directory dir = newFSDirectory(createTempDir());
+    IndexWriterConfig iwc = new IndexWriterConfig();
+    iwc.setMaxBufferedDocs(TestUtil.nextInt(random(), 100, 2000));
+
+    int numDocs = atLeast(10000);
+
+    final IndexWriter w = new IndexWriter(dir, iwc);
+    final AtomicInteger count = new AtomicInteger();
+    Thread[] threads = new Thread[2];
+    for(int i=0;i<threads.length;i++) {
+      threads[i] = new Thread() {
+          @Override
+          public void run() {
+           while (count.getAndIncrement() < numDocs) {
+              Document doc = new Document();
+              doc.add(newTextField("field", "text", Field.Store.NO));
+              try {
+                w.addDocument(doc);
+              } catch (IOException ioe) {
+                throw new RuntimeException(ioe);
+              }
+            }
+          }
+        };
+      threads[i].start();
+    }
+
+    for (Thread thread : threads) {
+      thread.join();
+    }
+
+    assertEquals("lost " + (numDocs - w.maxDoc()) + " documents; maxBufferedDocs=" + iwc.getMaxBufferedDocs(), numDocs, w.maxDoc());
+    w.close();
+             
+    IndexReader r = DirectoryReader.open(dir);
+    assertEquals(numDocs, r.maxDoc());
+    IOUtils.close(r, dir);
+  }
+}


[18/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/FieldFacetAccumulator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/FieldFacetAccumulator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/FieldFacetAccumulator.java
deleted file mode 100644
index fb0884b..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/FieldFacetAccumulator.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.accumulator.facet;
-
-import java.io.IOException;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.NumericDocValues;
-import org.apache.lucene.index.SortedDocValues;
-import org.apache.lucene.index.SortedSetDocValues;
-import org.apache.lucene.util.BytesRef;
-import org.apache.solr.analytics.accumulator.FacetingAccumulator;
-import org.apache.solr.analytics.accumulator.ValueAccumulator;
-import org.apache.solr.analytics.util.AnalyticsParsers.NumericParser;
-import org.apache.solr.analytics.util.AnalyticsParsers.Parser;
-import org.apache.solr.analytics.util.AnalyticsParsers;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.schema.DateValueFieldType;
-import org.apache.solr.schema.SchemaField;
-import org.apache.solr.search.SolrIndexSearcher;
-
-/**
- * An Accumulator that manages the faceting for fieldFacets.
- * Collects the field facet values.
- */
-public class FieldFacetAccumulator extends ValueAccumulator {
-  protected final Parser parser;
-  protected final FacetValueAccumulator parent;
-  protected final String name;
-  protected final SolrIndexSearcher searcher;
-  protected final SchemaField schemaField;
-  protected final boolean multiValued;
-  protected final boolean numField;
-  protected final boolean dateField;
-  protected SortedSetDocValues setValues;
-  protected SortedDocValues sortValues;
-  protected NumericDocValues numValues;
-  
-  public FieldFacetAccumulator(SolrIndexSearcher searcher, FacetValueAccumulator parent, SchemaField schemaField) throws IOException {  
-    if( !schemaField.hasDocValues() ){
-      throw new IOException("Field '"+schemaField.getName()+"' does not have docValues and therefore cannot be faceted over.");
-    }
-    this.searcher = searcher;
-    this.schemaField = schemaField;
-    this.name = schemaField.getName();
-    this.multiValued = schemaField.multiValued();
-    this.numField = schemaField.getType().getNumberType()!=null;
-    this.dateField = schemaField.getType() instanceof DateValueFieldType;
-    this.parent = parent;  
-    this.parser = AnalyticsParsers.getParser(schemaField.getType().getClass());
-  }
-
-  public static FieldFacetAccumulator create(SolrIndexSearcher searcher, FacetValueAccumulator parent, SchemaField facetField) throws IOException{
-    return new FieldFacetAccumulator(searcher,parent,facetField);
-  }
-
-  /**
-   * Move to the next set of documents to add to the field facet.
-   */
-  @Override
-  protected void doSetNextReader(LeafReaderContext context) throws IOException {
-    if (multiValued) {
-      setValues = context.reader().getSortedSetDocValues(name);
-    } else {
-      if (numField) {
-        numValues = context.reader().getNumericDocValues(name);
-      } else {
-        sortValues = context.reader().getSortedDocValues(name);
-      }
-    }
-  }
-
-  /**
-   * Tell the FacetingAccumulator to collect the doc with the 
-   * given fieldFacet and value(s).
-   */
-  @Override
-  public void collect(int doc) throws IOException {
-    if (multiValued) {
-      boolean exists = false;
-      if (setValues!=null) {
-        if (doc > setValues.docID()) {
-          setValues.advance(doc);
-        }
-        if (doc == setValues.docID()) {
-          int term;
-          while ((term = (int)setValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
-            exists = true;
-            final BytesRef value = setValues.lookupOrd(term);
-            parent.collectField(doc, name, parser.parse(value) );
-          }
-        }
-      }
-      if (!exists) {
-        parent.collectField(doc, name, FacetingAccumulator.MISSING_VALUE );
-      }
-    } else {
-      if(numField){
-        if(numValues != null) {
-          int valuesDocID = numValues.docID();
-          if (valuesDocID < doc) {
-            valuesDocID = numValues.advance(doc);
-          }
-          if (valuesDocID == doc) {
-            parent.collectField(doc, name, ((NumericParser)parser).parseNum(numValues.longValue()));
-          } else {
-            parent.collectField(doc, name, FacetingAccumulator.MISSING_VALUE );
-          }
-        } else {
-          parent.collectField(doc, name, FacetingAccumulator.MISSING_VALUE );
-        }
-      } else {
-        if(sortValues != null) {
-          if (doc > sortValues.docID()) {
-            sortValues.advance(doc);
-          }
-          if (doc == sortValues.docID()) {
-            parent.collectField(doc, name, parser.parse(sortValues.lookupOrd(sortValues.ordValue())) );
-          } else {
-            parent.collectField(doc, name, FacetingAccumulator.MISSING_VALUE );
-          }
-        } else {
-          parent.collectField(doc, name, FacetingAccumulator.MISSING_VALUE );
-        }
-      }
-    }
-  }
-
-  @Override
-  public void compute() {}
- 
-  @Override
-  public NamedList<?> export() { return null; }
-
-  @Override
-  public boolean needsScores() {
-    return true; // TODO: is this true?
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/QueryFacetAccumulator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/QueryFacetAccumulator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/QueryFacetAccumulator.java
deleted file mode 100644
index 8b92ba0..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/QueryFacetAccumulator.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.accumulator.facet;
-
-import java.io.IOException;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.solr.analytics.accumulator.ValueAccumulator;
-import org.apache.solr.analytics.statistics.StatsCollector;
-import org.apache.solr.common.util.NamedList;
-
-/**
- * An Accumulator that manages a certain query of a given query facet.
- */
-public class QueryFacetAccumulator extends ValueAccumulator {
-  protected final FacetValueAccumulator parent;
-  protected final String facetName;
-  protected final String facetValue;
-
-  public QueryFacetAccumulator(FacetValueAccumulator parent, String facetName, String facetValue) {
-    this.parent = parent;
-    this.facetName = facetName;
-    this.facetValue = facetValue;
-  }
-
-  /**
-   * Tell the FacetingAccumulator to collect the doc with the 
-   * given queryFacet and query.
-   */
-  @Override
-  public void collect(int doc) throws IOException {
-    parent.collectQuery(doc, facetName, facetValue);
-  }
-
-  /**
-   * Update the readers of the queryFacet {@link StatsCollector}s in FacetingAccumulator
-   */
-  @Override
-  protected void doSetNextReader(LeafReaderContext context) throws IOException {
-    parent.setQueryStatsCollectorReaders(context);
-  }
-
-  @Override
-  public void compute() {
-    // NOP
-  }
-
-  @Override
-  public NamedList<?> export() {
-    // NOP
-    return null;
-  }
-
-  @Override
-  public boolean needsScores() {
-    return true; // TODO: is this true?
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/RangeFacetAccumulator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/RangeFacetAccumulator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/RangeFacetAccumulator.java
deleted file mode 100644
index 59cf428..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/RangeFacetAccumulator.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.accumulator.facet;
-
-import java.io.IOException;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.solr.analytics.statistics.StatsCollector;
-
-/**
- * An Accumulator that manages a certain range of a given range facet.
- */
-public class RangeFacetAccumulator extends QueryFacetAccumulator {
-  public RangeFacetAccumulator(FacetValueAccumulator parent, String facetName, String facetValue) {
-    super(parent, facetName, facetValue);
-  }
-
-  /**
-   * Tell the FacetingAccumulator to collect the doc with the 
-   * given rangeFacet and range.
-   */
-  @Override
-  public void collect(int doc) throws IOException {
-    parent.collectRange(doc, facetName, facetValue);
-  }
-
-  /**
-   * Update the readers of the rangeFacet {@link StatsCollector}s in FacetingAccumulator
-   */
-  @Override
-  protected void doSetNextReader(LeafReaderContext context) throws IOException {
-    parent.setRangeStatsCollectorReaders(context);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/package-info.java
deleted file mode 100644
index 3daf103..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-/** 
- * Accumulators for accumulating over differnt types of facets
-
- */
-package org.apache.solr.analytics.accumulator.facet;
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/package-info.java
deleted file mode 100644
index 0abe00a..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-/** 
- * Accumulators accumulate values over different types of strucuture (eg result, facet, etc..)
- */
-package org.apache.solr.analytics.accumulator;
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/BaseExpression.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/BaseExpression.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/BaseExpression.java
deleted file mode 100644
index 2f0326b..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/BaseExpression.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.expression;
-
-import java.util.Date;
-
-import org.apache.solr.analytics.statistics.StatsCollector;
-
-
-/**
- * <code>BaseExpression</code> returns the value returned by the {@link StatsCollector} for the specified stat.
- */
-public class BaseExpression extends Expression {
-  protected final StatsCollector statsCollector;
-  protected final String stat;
-  
-  public BaseExpression(StatsCollector statsCollector, String stat) {
-    this.statsCollector = statsCollector;
-    this.stat = stat;
-  }
-  
-  public Comparable getValue() {
-    if(statsCollector.getStatsList().contains(stat)) {
-      return statsCollector.getStat(stat);
-    }
-    return null;
-  }
-}
-/**
- * <code>ConstantStringExpression</code> returns the specified constant double.
- */
-class ConstantNumberExpression extends Expression {
-  protected final Double constant;
-  
-  public ConstantNumberExpression(double d) {
-    constant = new Double(d);
-  }
-  
-  public Comparable getValue() {
-    return constant;
-  }
-}
-/**
- * <code>ConstantStringExpression</code> returns the specified constant date.
- */
-class ConstantDateExpression extends Expression {
-  protected final Date constant;
-  
-  public ConstantDateExpression(Date date) {
-    constant = date;
-  }
-  
-  public ConstantDateExpression(Long date) {
-    constant = new Date(date);
-  }
-  
-  public Comparable getValue() {
-    return constant;
-  }
-}
-/**
- * <code>ConstantStringExpression</code> returns the specified constant string.
- */
-class ConstantStringExpression extends Expression {
-  protected final String constant;
-  
-  public ConstantStringExpression(String str) {
-    constant = str;
-  }
-  
-  public Comparable getValue() {
-    return constant;
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/DualDelegateExpression.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/DualDelegateExpression.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/DualDelegateExpression.java
deleted file mode 100644
index f906b47..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/DualDelegateExpression.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.expression;
-
-/**
- * Abstraction of an expression that applies a function to two delegate expressions.
- */
-public abstract class DualDelegateExpression extends Expression {
-  protected Expression a;
-  protected Expression b;
-  public DualDelegateExpression(Expression a, Expression b) {
-    this.a = a;
-    this.b = b;
-  }
-}
-/**
- * <code>DivideExpression</code> returns the quotient of 'a' and 'b'.
- */
-class DivideExpression extends DualDelegateExpression {
-  
-  /**
-   * @param a numerator
-   * @param b divisor
-   */
-  public DivideExpression(Expression a, Expression b) {
-    super(a,b);
-  }
-
-  @Override
-  public Comparable getValue() {
-    Comparable aComp = a.getValue();
-    Comparable bComp = b.getValue();
-    if (aComp==null || bComp==null) {
-      return null;
-    }
-    double div = ((Number)aComp).doubleValue();
-    div = div / ((Number)bComp).doubleValue();
-    return new Double(div);
-  }
-}
-/**
- * <code>PowerExpression</code> returns 'a' to the power of 'b'.
- */
-class PowerExpression extends DualDelegateExpression {
-
-  /**
-   * @param a base
-   * @param b exponent
-   */
-  public PowerExpression(Expression a, Expression b) {
-    super(a,b);
-  }
-
-  @Override
-  public Comparable getValue() {
-    Comparable aComp = a.getValue();
-    Comparable bComp = b.getValue();
-    if (aComp==null || bComp==null) {
-      return null;
-    }
-    return new Double(Math.pow(((Number)aComp).doubleValue(),((Number)bComp).doubleValue()));
-  }
-}
-/**
- * <code>LogExpression</code> returns the log of the delegate's value given a base number.
- */
-class LogExpression extends DualDelegateExpression {
-  /**
-   * @param a number
-   * @param b base
-   */
-  public LogExpression(Expression a, Expression b) {
-    super(a,b);
-  }
-
-  @Override
-  public Comparable getValue() {
-    Comparable aComp = a.getValue();
-    Comparable bComp = b.getValue();
-    if (aComp==null || bComp==null) {
-      return null;
-    }
-    return Math.log(((Number)aComp).doubleValue())/Math.log(((Number)bComp).doubleValue());
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/Expression.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/Expression.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/Expression.java
deleted file mode 100644
index ba26d9a..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/Expression.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.expression;
-
-import java.util.Comparator;
-
-import org.apache.solr.analytics.request.FieldFacetRequest.FacetSortDirection;
-
-/**
- * Expressions map either zero, one, two or many inputs to a single value. 
- * They can be defined recursively to compute complex math.
- */
-public abstract class Expression {
-  public abstract Comparable getValue();
-
-  public Comparator<Expression> comparator(final FacetSortDirection direction) {
-    return (a, b) -> {
-      if( direction == FacetSortDirection.ASCENDING ){
-        return a.getValue().compareTo(b.getValue());
-      } else {
-        return b.getValue().compareTo(a.getValue());
-      }
-    };
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/ExpressionFactory.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/ExpressionFactory.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/ExpressionFactory.java
deleted file mode 100644
index 1f2d0e0..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/ExpressionFactory.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.expression;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.solr.analytics.statistics.StatsCollector;
-import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.util.DateMathParser;
-
-public class ExpressionFactory {
-
-  /**
-   * Creates a single expression that contains delegate expressions and/or 
-   * a StatsCollector.
-   * StatsCollectors are given as input and not created within the method so that
-   * expressions can share the same StatsCollectors, minimizing computation.
-   * 
-   * @param expression String representation of the desired expression
-   * @param statsCollectors List of StatsCollectors to build the expression with. 
-   * @return the expression
-   */
-  @SuppressWarnings("deprecation")
-  public static Expression create(String expression, StatsCollector[] statsCollectors) {
-    int paren = expression.indexOf('(');
-    if (paren<=0) {
-      throw new SolrException(ErrorCode.BAD_REQUEST, "The expression ["+expression+"] has no arguments and is not supported.");
-    }
-    String topOperation = expression.substring(0,paren).trim();
-    String operands;
-    try {
-      operands = expression.substring(paren+1, expression.lastIndexOf(')')).trim();
-    } catch (Exception e) {
-      throw new SolrException(ErrorCode.BAD_REQUEST,"Missing closing parenthesis in ["+expression+"]",e);
-    }
-    
-    // Builds a statistic, constant or recursively builds an expression tree
-    
-    // Statistic 
-    if (AnalyticsParams.ALL_STAT_SET.contains(topOperation)) {
-      if (topOperation.equals(AnalyticsParams.STAT_PERCENTILE)) {
-        operands = expression.substring(expression.indexOf(',')+1, expression.lastIndexOf(')')).trim();
-        topOperation = topOperation+"_"+expression.substring(expression.indexOf('(')+1, expression.indexOf(',')).trim();
-      }
-      StatsCollector collector = null;
-      // Finds the desired counter and builds an expression around it and the desired statistic.
-      for (StatsCollector c : statsCollectors) {
-        if (c.valueSourceString().equals(operands)) { 
-          collector = c;
-          break;
-        }
-      }
-      if (collector == null) {
-        throw new SolrException(ErrorCode.BAD_REQUEST, "ValueSource ["+operands+"] in Expression ["+expression+"] not found.");
-      }
-      return new BaseExpression(collector, topOperation);
-    }
-    // Constant
-    if (topOperation.equals(AnalyticsParams.CONSTANT_NUMBER)) {
-      try {
-        return new ConstantNumberExpression(Double.parseDouble(operands));
-      } catch (NumberFormatException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST, "The constant "+operands+" cannot be converted into a number.",e);
-      }
-    } else if (topOperation.equals(AnalyticsParams.CONSTANT_DATE)) {
-      return new ConstantDateExpression(DateMathParser.parseMath(null, operands));
-    } else if (topOperation.equals(AnalyticsParams.CONSTANT_STRING)) {
-      operands = expression.substring(paren+1, expression.lastIndexOf(')'));
-      return new ConstantStringExpression(operands);
-    }
-    
-    // Complex Delegating Expressions
-    String[] arguments = getArguments(operands);
-    Expression[] expArgs = new Expression[arguments.length];
-    for (int count = 0; count < arguments.length; count++) {
-      // Recursively builds delegate expressions
-      expArgs[count] = create(arguments[count], statsCollectors);
-    }
-    
-    // Single Delegate Expressions
-    if (expArgs.length==1) {
-      // Numeric Expression
-      if (topOperation.equals(AnalyticsParams.NEGATE)) {
-        return new NegateExpression(expArgs[0]);
-      }
-      if (topOperation.equals(AnalyticsParams.ABSOLUTE_VALUE)) {
-        return new AbsoluteValueExpression(expArgs[0]);
-      }
-      // String Expression
-      else if (topOperation.equals(AnalyticsParams.REVERSE)) {
-        return new ReverseExpression(expArgs[0]);
-      }
-      throw new SolrException(ErrorCode.BAD_REQUEST, topOperation+" does not have the correct number of arguments.");
-    }  else {
-      // Multi Delegate Expressions
-      // Numeric Expression
-      if (topOperation.equals(AnalyticsParams.ADD)) {
-        return new AddExpression(expArgs);
-      } else if (topOperation.equals(AnalyticsParams.MULTIPLY)) {
-        return new MultiplyExpression(expArgs);
-      }
-      // Date Expression
-      else if (topOperation.equals(AnalyticsParams.DATE_MATH)) {
-        return new DateMathExpression(expArgs);
-      } 
-      // String Expression
-      else if (topOperation.equals(AnalyticsParams.CONCATENATE)) {
-        return new ConcatenateExpression(expArgs);
-      } 
-      // Dual Delegate Expressions
-      else if (expArgs.length==2 && (topOperation.equals(AnalyticsParams.DIVIDE) || topOperation.equals(AnalyticsParams.POWER) 
-          || topOperation.equals(AnalyticsParams.LOG))) {
-        // Numeric Expression
-        if (topOperation.equals(AnalyticsParams.DIVIDE)) {
-          return new DivideExpression(expArgs[0], expArgs[1]);
-        } else if (topOperation.equals(AnalyticsParams.POWER)) {
-          return new PowerExpression(expArgs[0], expArgs[1]);
-        } else if (topOperation.equals(AnalyticsParams.LOG)) {
-          return new LogExpression(expArgs[0], expArgs[1]);
-        }
-        return null;
-      }
-      throw new SolrException(ErrorCode.BAD_REQUEST, topOperation+" does not have the correct number of arguments or is unsupported.");
-    }
-    
-  }
-  
-  /**
-   * Splits up an Expression's arguments.
-   * 
-   * @param expression Current expression string
-   * @return List The list of arguments
-   */
-  public static String[] getArguments(String expression) {
-    String[] strings = new String[1];
-    int stack = 0;
-    int start = 0;
-    List<String> arguments = new ArrayList<>();
-    char[] chars = expression.toCharArray();
-    for (int count = 0; count < expression.length(); count++) {
-      char c = chars[count];
-      if (c==',' && stack == 0) {
-        arguments.add(expression.substring(start, count).replace("\\(","(").replace("\\)",")").replace("\\,",",").trim());
-        start = count+1;
-      } else if (c == '(') {
-        stack ++;
-      } else if (c == ')') {
-        stack --;
-      } else if (c == '\\') {
-        ; // Do nothing.
-      }
-    }
-    if (stack==0) {
-      arguments.add(expression.substring(start).trim());
-    }
-    return arguments.toArray(strings);
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/MultiDelegateExpression.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/MultiDelegateExpression.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/MultiDelegateExpression.java
deleted file mode 100644
index 4ea66fa..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/MultiDelegateExpression.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.expression;
-
-import java.text.ParseException;
-import java.util.Date;
-
-import org.apache.solr.util.DateMathParser;
-
-/**
- * Abstraction of an expression that applies a function to an array of delegate expressions.
- */
-public abstract class MultiDelegateExpression extends Expression {
-  protected final Expression[] delegates;
-  
-  public MultiDelegateExpression(Expression[] delegates) {
-    this.delegates = delegates;
-  }
-}
-/**
- * <code>AddExpression</code> returns the sum of its components' values.
- */
-class AddExpression extends MultiDelegateExpression {
-  public AddExpression(Expression[] delegates) {
-    super(delegates);
-  }
-
-  @Override
-  public Comparable getValue() {
-    double sum = 0;
-    for (Expression delegate : delegates) {
-      Comparable dComp = delegate.getValue();
-      if (dComp==null) {
-        return null;
-      } else if (dComp.getClass().equals(Date.class)) {
-        dComp = new Long(((Date)dComp).getTime());
-      }
-      sum += ((Number)dComp).doubleValue();
-    }
-    return new Double(sum);
-  }
-}
-/**
- * <code>MultiplyExpression</code> returns the product of its delegates' values.
- */
-class MultiplyExpression extends MultiDelegateExpression {
-  public MultiplyExpression(Expression[] delegates) {
-    super(delegates);
-  }
-
-  @Override
-  public Comparable getValue() {
-    double prod = 1;
-    for (Expression delegate : delegates) {
-      Comparable dComp = delegate.getValue();
-      if (dComp==null) {
-        return null;
-      }
-      prod *= ((Number)dComp).doubleValue();
-    }
-    return new Double(prod);
-  }
-}
-/**
- * <code>DateMathExpression</code> returns the start date modified by the DateMath operations
- */
-class DateMathExpression extends MultiDelegateExpression {
-  /**
-   * @param delegates A list of Expressions. The first element in the list
-   * should be a numeric Expression which represents the starting date. 
-   * The rest of the field should be string Expression objects which contain
-   * the DateMath operations to perform on the start date.
-   */
-  public DateMathExpression(Expression[] delegates) {
-    super(delegates);
-  }
-
-  @Override
-  public Comparable getValue() {
-    DateMathParser parser = new DateMathParser();
-    parser.setNow((Date)delegates[0].getValue());
-    try {
-      for (int count = 1; count<delegates.length; count++) {
-        Comparable dComp = delegates[count].getValue();
-        if (dComp==null) {
-          return null;
-        }
-        parser.setNow(parser.parseMath((String)dComp));
-      }
-      return parser.getNow();
-    } catch (ParseException e) {
-      e.printStackTrace();
-      return parser.getNow();
-    }
-  }
-}
-/**
- * <code>ConcatenateExpression</code> returns the concatenation of its delegates' values in the order given.
- */
-class ConcatenateExpression extends MultiDelegateExpression {
-  public ConcatenateExpression(Expression[] delegates) {
-    super(delegates);
-  }
-
-  @Override
-  public Comparable getValue() {
-    StringBuilder builder = new StringBuilder();
-    for (Expression delegate : delegates) {
-      Comparable dComp = delegate.getValue();
-      if (dComp==null) {
-        return null;
-      }
-      builder.append(dComp.toString());
-    }
-    return builder.toString();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/SingleDelegateExpression.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/SingleDelegateExpression.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/SingleDelegateExpression.java
deleted file mode 100644
index 8d94ece..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/SingleDelegateExpression.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.expression;
-
-import java.util.Date;
-
-/**
- * Abstraction of an expression that applies a function to one delegate expression.
- */
-public abstract class SingleDelegateExpression extends Expression {
-  protected Expression delegate;
-  
-  public SingleDelegateExpression(Expression delegate) {
-    this.delegate = delegate;
-  }
-}
-/**
- * <code>NegateExpression</code> returns the negation of the delegate's value.
- */
-class NegateExpression extends SingleDelegateExpression {
-  public NegateExpression(Expression delegate) {
-    super(delegate);
-  }
-
-  @Override
-  public Comparable getValue() {
-    Comparable nComp = delegate.getValue();
-    if (nComp==null) {
-      return null;
-    } else if (nComp.getClass().equals(Date.class)) {
-      nComp = new Long(((Date)nComp).getTime());
-    }
-    return new Double(((Number)nComp).doubleValue()*-1);
-  }
-}
-/**
- * <code>AbsoluteValueExpression</code> returns the negation of the delegate's value.
- */
-class AbsoluteValueExpression extends SingleDelegateExpression {
-  public AbsoluteValueExpression(Expression delegate) {
-    super(delegate);
-  }
-
-  @Override
-  public Comparable getValue() {
-    Comparable nComp = delegate.getValue();
-    if (nComp==null) {
-      return null;
-    }
-    double d = ((Number)nComp).doubleValue();
-    if (d<0) {
-      return new Double(d*-1);
-    } else {
-      return new Double(d);
-    }
-  }
-}
-/**
- * <code>StringExpression</code> returns the reverse of the delegate's string value.
- */
-class ReverseExpression extends SingleDelegateExpression {
-  public ReverseExpression(Expression delegate) {
-    super(delegate);
-  }
-
-  @Override
-  public Comparable getValue() {
-    Comparable rComp = delegate.getValue();
-    if (rComp==null) {
-      return null;
-    }
-    return new StringBuilder(rComp.toString()).reverse().toString();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/package-info.java
deleted file mode 100644
index 8c6f70e..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/expression/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-/** 
- * Expressions map either zero, one, two or many inputs to a single value. They can be defined recursively to compute complex math.
- */
-package org.apache.solr.analytics.expression;
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/AbstractSolrQueryFacet.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/AbstractSolrQueryFacet.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/AbstractSolrQueryFacet.java
new file mode 100644
index 0000000..d06cfa3
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/AbstractSolrQueryFacet.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SimpleCollector;
+import org.apache.solr.analytics.AnalyticsDriver;
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.search.Filter;
+import org.apache.solr.search.SolrIndexSearcher;
+
+/**
+ * Solr Query Facets are AnalyticsFacets that are calculated after the document streaming phase has occurred in the {@link AnalyticsDriver}
+ * (during which StreamingFacets and overall expressions are calculated). {@link AbstractSolrQueryFacet}s should not be confused with {@link QueryFacet}s, 
+ * which are a specific sub-type.
+ * 
+ * <p>
+ * The filtering for these facets is done through issuing additional Solr queries, and collecting on the resulting documents.
+ * Unlike streaming facets, which have an unspecified amount of facet values (facet buckets), the amount of facet values is determined by the user and
+ * a Solr query is issued for each requested facet value.
+ */
+public abstract class AbstractSolrQueryFacet extends AnalyticsFacet {
+  
+  protected AbstractSolrQueryFacet(String name) {
+    super(name);
+  }
+
+  /**
+   * Returns the set of {@link FacetValueQueryExecuter}s, one for each facet value, through the given consumer.
+   * 
+   * Each of these executors will be executed after the streaming phase in the {@link AnalyticsDriver}.
+   * 
+   * @param filter the overall filter representing the documents being used for the analytics request
+   * @param queryRequest the queryRequest 
+   * @param consumer the consumer of each facet value's executer
+   */
+  public abstract void createFacetValueExecuters(final Filter filter, SolrQueryRequest queryRequest, Consumer<FacetValueQueryExecuter> consumer);
+  
+  /**
+   * This executer is in charge of issuing the Solr query for a facet value and collecting results as the query is processed.
+   */
+  public class FacetValueQueryExecuter extends SimpleCollector {
+    private final ReductionDataCollection collection;
+    private final Query query;
+    
+    /**
+     * Create an executer to collect the given reduction data from the given Solr query.
+     * 
+     * @param collection The reduction data to collect while querying
+     * @param query The query used to filter for the facet value
+     */
+    public FacetValueQueryExecuter(ReductionDataCollection collection, Query query) {
+      this.collection = collection;
+      this.query = query;
+    }
+
+    @Override
+    public boolean needsScores() {
+      return false;
+    }
+
+    @Override
+    public void doSetNextReader(LeafReaderContext context) throws IOException {
+      collectionManager.doSetNextReader(context);
+    }
+
+    @Override
+    public void collect(int doc) throws IOException {
+      collectionManager.collect(doc);
+      collectionManager.apply();
+    }
+
+    /**
+     * Start the collection for this facet value.
+     * 
+     * @param searcher the solr searcher
+     * @throws IOException if an exception occurs during the querying
+     */
+    public void execute(SolrIndexSearcher searcher) throws IOException {
+      collectionManager.clearLastingCollectTargets();
+      collectionManager.addLastingCollectTarget(collection);
+      searcher.search(query, this);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/AnalyticsFacet.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/AnalyticsFacet.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/AnalyticsFacet.java
new file mode 100644
index 0000000..d9c0f8c
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/AnalyticsFacet.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import org.apache.solr.analytics.function.ExpressionCalculator;
+import org.apache.solr.analytics.function.ReductionCollectionManager;
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
+import org.apache.solr.common.util.NamedList;
+
+/**
+ * An abstract Facet to break up Analytics data over.
+ */
+public abstract class AnalyticsFacet {
+  protected final Map<String,ReductionDataCollection> reductionData;
+  protected ReductionCollectionManager collectionManager;
+  protected ExpressionCalculator expressionCalculator;
+  
+  protected final String name;
+  
+  public AnalyticsFacet(String name) {
+    this.reductionData = new LinkedHashMap<>();
+    this.name = name;
+  }
+  
+  /**
+   * Set the {@link ReductionCollectionManager} that manages the collection of the expressions
+   * calculated with this facet.
+   * 
+   * @param collectionManager The manager for relevant expressions
+   */
+  public void setReductionCollectionManager(ReductionCollectionManager collectionManager) {
+    this.collectionManager = collectionManager;
+  }
+  
+  /**
+   * Set the {@link ExpressionCalculator} that calculates the collection of the expressions
+   * requested for this facet.
+   * 
+   * @param expressionCalculator The calculator for relevant expressions
+   */
+  public void setExpressionCalculator(ExpressionCalculator expressionCalculator) {
+    this.expressionCalculator = expressionCalculator;
+  }
+
+  /**
+   * Import the shard data from a bit-stream, exported by the {@link #exportShardData} method 
+   * in the each of the collection's shards.
+   * 
+   * @param input The bit-stream to import the data from
+   * @throws IOException if an exception occurs while reading from the {@link DataInput}
+   */
+  public void importShardData(DataInput input) throws IOException {
+    int size = input.readInt();
+    for (int i = 0; i < size; ++i) {
+      importFacetValue(input, input.readUTF());
+    }
+  }
+  /**
+   * Import the next facet value's set of {@link ReductionData}.
+   * 
+   * @param input the bit-stream to import the reduction data from
+   * @param facetValue the next facet value
+   * @throws IOException if an exception occurs while reading from the input
+   */
+  protected void importFacetValue(DataInput input, String facetValue) throws IOException {
+    ReductionDataCollection dataCollection = reductionData.get(facetValue);
+    if (dataCollection == null) {
+      reductionData.put(facetValue, collectionManager.newDataCollectionIO());
+    } else {
+      collectionManager.prepareReductionDataIO(dataCollection);
+    }
+    
+    collectionManager.mergeData();
+  }
+
+  /**
+   * Export the shard data through a bit-stream, to be imported by the {@link #importShardData} method 
+   * in the originating shard.
+   * 
+   * @param output The bit-stream to output the data through
+   * @throws IOException if an exception occurs while writing to the {@link DataOutput}
+   */
+  public void exportShardData(DataOutput output) throws IOException {
+    output.writeInt(reductionData.size());
+    for (String facetValue : reductionData.keySet()) {
+      exportFacetValue(output, facetValue);
+    }
+  }
+  /**
+   * Export the next facet value's set of {@link ReductionData}.
+   * 
+   * @param output the bit-stream to output the reduction data to
+   * @param facetValue the next facet value
+   * @throws IOException if an exception occurs while reading from the input
+   */
+  protected void exportFacetValue(DataOutput output, String facetValue) throws IOException {
+    output.writeUTF(facetValue);
+    
+    collectionManager.prepareReductionDataIO(reductionData.get(facetValue));
+    collectionManager.exportData();
+  }
+  
+  /**
+   * Create the old olap-style response of the facet to be returned in the overall analytics response.
+   * 
+   * @return the response of the facet
+   */
+  public NamedList<Object> createOldResponse() {
+    NamedList<Object> nl = new NamedList<>();
+    reductionData.forEach((facetVal, dataCol) -> {
+      collectionManager.setData(dataCol);
+      nl.add(facetVal, new NamedList<>(expressionCalculator.getResults()));
+    });
+    return nl;
+  }
+  
+  /**
+   * Create the response of the facet to be returned in the overall analytics response.
+   * 
+   * @return the response of the facet
+   */
+  public Iterable<Map<String,Object>> createResponse() {
+    LinkedList<Map<String,Object>> list = new LinkedList<>();
+    reductionData.forEach((facetVal, dataCol) -> {
+      Map<String, Object> bucket = new HashMap<>();
+      bucket.put(AnalyticsResponseHeadings.FACET_VALUE, facetVal);
+      collectionManager.setData(dataCol);
+      expressionCalculator.addResults(bucket);
+      list.add(bucket);
+    });
+    return list;
+  }
+  
+  /**
+   * Get the name of the Facet. This is unique for the grouping.
+   * 
+   * @return The name of the Facet
+   */
+  public String getName() {
+    return name;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/PivotFacet.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/PivotFacet.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/PivotFacet.java
new file mode 100644
index 0000000..f9e35f7
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/PivotFacet.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.analytics.function.ExpressionCalculator;
+import org.apache.solr.analytics.function.ReductionCollectionManager;
+import org.apache.solr.common.util.NamedList;
+
+/**
+ * A facet that takes in multiple ValueFacet expressions and does analytics calculations over each dimension given. 
+ */
+public class PivotFacet extends AnalyticsFacet implements StreamingFacet {
+  private final PivotHead<?> pivotHead;
+
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  public PivotFacet(String name, PivotNode<?> topPivot) {
+    super(name);
+    this.pivotHead = new PivotHead(topPivot);
+  }
+  
+  @Override
+  public void setReductionCollectionManager(ReductionCollectionManager collectionManager) {
+    pivotHead.setReductionCollectionManager(collectionManager);
+  }
+
+  @Override
+  public void setExpressionCalculator(ExpressionCalculator expressionCalculator) {
+    pivotHead.setExpressionCalculator(expressionCalculator);
+  }
+
+  @Override
+  public void addFacetValueCollectionTargets() {
+    pivotHead.addFacetValueCollectionTargets();
+  }
+
+  @Override
+  public void importShardData(DataInput input) throws IOException {
+    pivotHead.importShardData(input);
+  }
+
+  @Override
+  public void exportShardData(DataOutput output) throws IOException {
+    pivotHead.exportShardData(output);
+  }
+  
+  @Override
+  public NamedList<Object> createOldResponse() {
+    return new NamedList<>();
+  }
+  
+  @Override
+  public Iterable<Map<String,Object>> createResponse() {
+    return pivotHead.createResponse();
+  }
+}
+/**
+ * Typed Pivot class that stores the overall Pivot data and head of the Pivot node chain.
+ * 
+ * This class exists so that the {@link PivotFacet} class doesn't have to be typed ( {@code <T>} ).
+ */
+class PivotHead<T> implements StreamingFacet {
+  private final PivotNode<T> topPivot;
+  private final Map<String, T> pivotValues;
+  
+  public PivotHead(PivotNode<T> topPivot) {
+    this.topPivot = topPivot;
+    this.pivotValues = new HashMap<>();
+  }
+  
+  public void setReductionCollectionManager(ReductionCollectionManager collectionManager) {
+    topPivot.setReductionCollectionManager(collectionManager);
+  }
+  
+  public void setExpressionCalculator(ExpressionCalculator expressionCalculator) {
+    topPivot.setExpressionCalculator(expressionCalculator);
+  }
+
+  @Override
+  public void addFacetValueCollectionTargets() {
+    topPivot.addFacetValueCollectionTargets(pivotValues);
+  }
+
+  public void importShardData(DataInput input) throws IOException {
+    topPivot.importPivot(input, pivotValues);
+  }
+
+  public void exportShardData(DataOutput output) throws IOException {
+    topPivot.exportPivot(output, pivotValues);
+  }
+  
+  public Iterable<Map<String,Object>> createResponse() {
+    return topPivot.getPivotedResponse(pivotValues);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/PivotNode.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/PivotNode.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/PivotNode.java
new file mode 100644
index 0000000..c6c0dc4
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/PivotNode.java
@@ -0,0 +1,263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.AnalyticsDriver;
+import org.apache.solr.analytics.function.ExpressionCalculator;
+import org.apache.solr.analytics.function.ReductionCollectionManager;
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
+import org.apache.solr.analytics.value.StringValueStream;
+
+/**
+ * Representation of one layer of a Pivot Facet. A PivotFacet node is individually sortable,
+ * and is collected during the streaming phase of the {@link AnalyticsDriver}.
+ */
+public abstract class PivotNode<T> extends SortableFacet implements Consumer<String> {
+  private StringValueStream expression;
+  protected Map<String,T> currentPivot;
+
+  public PivotNode(String name, StringValueStream expression) {
+    super(name);
+    this.expression = expression;
+  }
+
+  /**
+   * Determine which facet values match the current document. Add the {@link ReductionDataCollection}s of the relevant facet values
+   * to the targets of the streaming {@link ReductionCollectionManager} so that they are updated with the current document's data.
+   */
+  public void addFacetValueCollectionTargets(Map<String,T> pivot) {
+    currentPivot = pivot;
+    expression.streamStrings(this);
+  }
+  
+  /**
+   * Import the shard data from a bit-stream for the given pivot, exported by the {@link #exportPivot} method 
+   * in the each of the collection's shards.
+   * 
+   * @param input The bit-stream to import the data from
+   * @param pivot the values for this pivot node and the pivot children (if they exist)
+   * @throws IOException if an exception occurs while reading from the {@link DataInput}
+   */
+  public void importPivot(DataInput input, Map<String,T> pivot) throws IOException {
+    int size = input.readInt();
+    currentPivot = pivot;
+    for (int i = 0; i < size; ++i) {
+      importPivotValue(input, input.readUTF());
+    }
+  }
+  /**
+   * Import the next pivot value's set of {@link ReductionData} and children's {@link ReductionData} if they exist.
+   * 
+   * @param input the bit-stream to import the reduction data from
+   * @param pivotValue the next pivot value
+   * @throws IOException if an exception occurs while reading from the input
+   */
+  protected abstract void importPivotValue(DataInput input, String pivotValue) throws IOException;
+
+  /**
+   * Export the shard data through a bit-stream for the given pivot, 
+   * to be imported by the {@link #importPivot} method in the originating shard.
+   * 
+   * @param output The bit-stream to output the data through
+   * @param pivot the values for this pivot node and the pivot children (if they exist)
+   * @throws IOException if an exception occurs while writing to the {@link DataOutput}
+   */
+  public void exportPivot(DataOutput output, Map<String,T> pivot) throws IOException {
+    output.writeInt(pivot.size());
+    for (String pivotValue : pivot.keySet()) {
+      output.writeUTF(pivotValue);
+      exportPivotValue(output, pivot.get(pivotValue));
+    }
+  }
+  /**
+   * Export the given pivot data, containing {@link ReductionData} and pivot children if they exist.
+   * 
+   * @param output the bit-stream to output the reduction data to
+   * @param pivotData the next pivot value data
+   * @throws IOException if an exception occurs while reading from the input
+   */
+  protected abstract void exportPivotValue(DataOutput output, T pivotData) throws IOException;
+  
+  /**
+   * Create the response of the facet to be returned in the overall analytics response.
+   * 
+   * @param pivot the pivot to create a response for
+   * @return the response of the facet
+   */
+  public abstract Iterable<Map<String,Object>> getPivotedResponse(Map<String,T> pivot);
+  
+  /**
+   * A pivot node that has no pivot children.
+   */
+  public static class PivotLeaf extends PivotNode<ReductionDataCollection> {
+
+    public PivotLeaf(String name, StringValueStream expression) {
+      super(name, expression);
+    }
+    
+    @Override
+    public void accept(String pivotValue) {
+      ReductionDataCollection collection = currentPivot.get(pivotValue);
+      if (collection == null) {
+        collection = collectionManager.newDataCollectionTarget();
+        currentPivot.put(pivotValue, collection);
+      } else {
+        collectionManager.addCollectTarget(collection);
+      }
+    }
+
+    @Override
+    protected void importPivotValue(DataInput input, String pivotValue) throws IOException {
+      ReductionDataCollection dataCollection = currentPivot.get(pivotValue);
+      if (dataCollection == null) {
+        currentPivot.put(pivotValue, collectionManager.newDataCollectionIO());
+      } else {
+        collectionManager.prepareReductionDataIO(dataCollection);
+      }
+      collectionManager.mergeData();
+    }
+
+    @Override
+    protected void exportPivotValue(DataOutput output, ReductionDataCollection pivotData) throws IOException {
+      collectionManager.prepareReductionDataIO(pivotData);
+      collectionManager.exportData();
+    }
+
+    @Override
+    public Iterable<Map<String,Object>> getPivotedResponse(Map<String,ReductionDataCollection> pivot) {
+      final List<FacetBucket> facetResults = new ArrayList<>();
+      pivot.forEach((facetVal, dataCol) -> {
+        collectionManager.setData(dataCol);
+        facetResults.add(new FacetBucket(facetVal,expressionCalculator.getResults()));
+      });
+
+      Iterable<FacetBucket> facetResultsIter = applyOptions(facetResults);
+      final LinkedList<Map<String,Object>> results = new LinkedList<>();
+      // Export each expression in the bucket.
+      for (FacetBucket bucket : facetResultsIter) {
+        Map<String, Object> bucketMap = new HashMap<>();
+        bucketMap.put(AnalyticsResponseHeadings.PIVOT_NAME, name);
+        bucketMap.put(AnalyticsResponseHeadings.FACET_VALUE, bucket.getFacetValue());
+        bucketMap.put(AnalyticsResponseHeadings.RESULTS, bucket.getResults());
+        results.add(bucketMap);
+      }
+      return results;
+    }
+  }
+  
+  /**
+   * A pivot node that has pivot children.
+   */
+  public static class PivotBranch<T> extends PivotNode<PivotBranch.PivotDataPair<T>> {
+    private final PivotNode<T> childPivot;
+    public PivotBranch(String name, StringValueStream expression, PivotNode<T> childPivot) {
+      super(name, expression);
+      this.childPivot = childPivot;
+    }
+    
+    @Override
+    public void setReductionCollectionManager(ReductionCollectionManager collectionManager) {
+      super.setReductionCollectionManager(collectionManager);
+      childPivot.setReductionCollectionManager(collectionManager);
+    }
+
+    @Override
+    public void setExpressionCalculator(ExpressionCalculator expressionCalculator) {
+      super.setExpressionCalculator(expressionCalculator);
+      childPivot.setExpressionCalculator(expressionCalculator);
+    }
+    
+    @Override
+    public void accept(String pivotValue) {
+      PivotDataPair<T> pivotData = currentPivot.get(pivotValue);
+      if (pivotData == null) {
+        pivotData = new PivotDataPair<>();
+        pivotData.childPivots = new HashMap<>();
+        pivotData.pivotReduction = collectionManager.newDataCollectionTarget();
+        currentPivot.put(pivotValue, pivotData);
+      } else {
+        collectionManager.addCollectTarget(pivotData.pivotReduction);
+      }
+      childPivot.addFacetValueCollectionTargets(pivotData.childPivots);
+    }
+
+    @Override
+    protected void importPivotValue(DataInput input, String pivotValue) throws IOException {
+      PivotDataPair<T> pivotData = currentPivot.get(pivotValue);
+      if (pivotData == null) {
+        pivotData = new PivotDataPair<>();
+        pivotData.childPivots = new HashMap<>();
+        pivotData.pivotReduction = collectionManager.newDataCollectionIO();
+        currentPivot.put(pivotValue, pivotData);
+      } else {
+        collectionManager.prepareReductionDataIO(pivotData.pivotReduction);
+      }
+      collectionManager.mergeData();
+      childPivot.importPivot(input, pivotData.childPivots);
+    }
+
+    @Override
+    protected void exportPivotValue(DataOutput output, PivotDataPair<T> pivotData) throws IOException {
+      collectionManager.prepareReductionDataIO(pivotData.pivotReduction);
+      collectionManager.exportData();
+      
+      childPivot.exportPivot(output, pivotData.childPivots);
+    }
+
+    @Override
+    public Iterable<Map<String,Object>> getPivotedResponse(Map<String,PivotDataPair<T>> pivot) {
+      final List<FacetBucket> facetResults = new ArrayList<>();
+      pivot.forEach((facetVal, dataPair) -> {
+        collectionManager.setData(dataPair.pivotReduction);
+        facetResults.add(new FacetBucket(facetVal,expressionCalculator.getResults()));
+      });
+
+      Iterable<FacetBucket> facetResultsIter = applyOptions(facetResults);
+      final LinkedList<Map<String,Object>> results = new LinkedList<>();
+      // Export each expression in the bucket.
+      for (FacetBucket bucket : facetResultsIter) {
+        Map<String, Object> bucketMap = new HashMap<>();
+        bucketMap.put(AnalyticsResponseHeadings.PIVOT_NAME, name);
+        bucketMap.put(AnalyticsResponseHeadings.FACET_VALUE, bucket.getFacetValue());
+        bucketMap.put(AnalyticsResponseHeadings.RESULTS, bucket.getResults());
+        bucketMap.put(AnalyticsResponseHeadings.PIVOT_CHILDREN, childPivot.getPivotedResponse(pivot.get(bucket.getFacetValue()).childPivots));
+        results.add(bucketMap);
+      }
+      return results;
+    }
+    
+    /**
+     * Contains pivot data for {@link PivotNode.PivotBranch} classes.
+     */
+    protected static class PivotDataPair<T> {
+      ReductionDataCollection pivotReduction;
+      Map<String,T> childPivots;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/QueryFacet.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/QueryFacet.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/QueryFacet.java
new file mode 100644
index 0000000..f880809
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/QueryFacet.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.search.Filter;
+import org.apache.solr.search.QParser;
+
+/**
+ * A facet that breaks down the data by additional Solr Queries.
+ */
+public class QueryFacet extends AbstractSolrQueryFacet {
+  private final Map<String,String> queries;
+  
+  public QueryFacet(String name, Map<String, String> queries) {
+    super(name);
+    this.queries = queries;
+  }
+  
+  @Override
+  public void createFacetValueExecuters(final Filter filter, SolrQueryRequest queryRequest, Consumer<FacetValueQueryExecuter> consumer) {
+    queries.forEach( (queryName, query) -> {
+      final Query q;
+      try {
+        q = QParser.getParser(query, queryRequest).getQuery();
+      } catch( Exception e ){
+        throw new SolrException(ErrorCode.BAD_REQUEST,"Invalid query '"+query+"' in query facet '" + getName() + "'",e);
+      }
+      // The searcher sends docIds to the QueryFacetAccumulator which forwards
+      // them to <code>collectQuery()</code> in this class for collection.
+      Query queryQuery = new BooleanQuery.Builder()
+          .add(q, Occur.MUST)
+          .add(filter, Occur.FILTER)
+          .build();
+
+      ReductionDataCollection dataCol = collectionManager.newDataCollection();
+      reductionData.put(queryName, dataCol);
+      consumer.accept(new FacetValueQueryExecuter(dataCol, queryQuery));
+    });
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/RangeFacet.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/RangeFacet.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/RangeFacet.java
new file mode 100644
index 0000000..80e8d21
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/RangeFacet.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.function.Consumer;
+
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+import org.apache.solr.analytics.util.FacetRangeGenerator;
+import org.apache.solr.analytics.util.FacetRangeGenerator.FacetRange;
+import org.apache.solr.common.params.FacetParams.FacetRangeInclude;
+import org.apache.solr.common.params.FacetParams.FacetRangeOther;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.schema.SchemaField;
+import org.apache.solr.search.Filter;
+
+/**
+ * A facet that groups data by a discrete set of ranges.
+ */
+public class RangeFacet extends AbstractSolrQueryFacet {
+  protected final SchemaField field;
+  protected final String start;
+  protected final String end;
+  protected final List<String> gaps;
+  protected boolean hardEnd = false;
+  protected EnumSet<FacetRangeInclude> include;
+  protected EnumSet<FacetRangeOther> others;
+  
+  public RangeFacet(String name, SchemaField field, String start, String end, List<String> gaps) {
+    super(name);
+    this.field = field;
+    this.start = start;
+    this.end = end;
+    this.gaps = gaps;
+    include = EnumSet.of(FacetRangeInclude.LOWER);
+    others = EnumSet.of(FacetRangeOther.NONE);
+  }
+
+  @Override
+  public void createFacetValueExecuters(final Filter filter, SolrQueryRequest queryRequest, Consumer<FacetValueQueryExecuter> consumer) {
+    // Computes the end points of the ranges in the rangeFacet
+    final FacetRangeGenerator<? extends Comparable<?>> rec = FacetRangeGenerator.create(this);
+    final SchemaField sf = field;
+    
+    // Create a rangeFacetAccumulator for each range and 
+    // collect the documents for that range.
+    for (FacetRange range : rec.getRanges()) {
+      Query q = sf.getType().getRangeQuery(null, sf, range.lower, range.upper, range.includeLower,range.includeUpper);
+      // The searcher sends docIds to the RangeFacetAccumulator which forwards
+      // them to <code>collectRange()</code> in this class for collection.
+      Query rangeQuery = new BooleanQuery.Builder()
+          .add(q, Occur.MUST)
+          .add(filter, Occur.FILTER)
+          .build();
+      
+      ReductionDataCollection dataCol = collectionManager.newDataCollection();
+      reductionData.put(range.toString(), dataCol);
+      consumer.accept(new FacetValueQueryExecuter(dataCol, rangeQuery));
+    }
+  }
+
+  public String getStart() {
+    return start;
+  }
+
+  public String getEnd() {
+    return end;
+  }
+
+  public EnumSet<FacetRangeInclude> getInclude() {
+    return include;
+  }
+
+  public void setInclude(EnumSet<FacetRangeInclude> include) {
+    this.include = include;
+  }
+
+  public List<String> getGaps() {
+    return gaps;
+  }
+
+  public boolean isHardEnd() {
+    return hardEnd;
+  }
+
+  public void setHardEnd(boolean hardEnd) {
+    this.hardEnd = hardEnd;
+  }
+
+  public EnumSet<FacetRangeOther> getOthers() {
+    return others;
+  }
+
+  public void setOthers(EnumSet<FacetRangeOther> others) {
+    this.others = others;
+  }
+  
+  public SchemaField getField() {
+    return field;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/SortableFacet.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/SortableFacet.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/SortableFacet.java
new file mode 100644
index 0000000..ef1e04b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/SortableFacet.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.solr.analytics.facet.compare.FacetResultsComparator;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
+import org.apache.solr.common.util.NamedList;
+
+import com.google.common.collect.Iterables;
+
+/**
+ * A facet that can be sorted by either the facet value or an expression value.
+ */
+public abstract class SortableFacet extends AnalyticsFacet {
+  protected FacetSortSpecification sort = null;
+  
+  protected SortableFacet(String name) {
+    super(name);
+  }
+  
+  @Override
+  public NamedList<Object> createOldResponse() {
+    final NamedList<Object> results = new NamedList<>();
+    // Export each expression in the bucket.
+    for (FacetBucket bucket : getBuckets()) {
+      results.add(bucket.getFacetValue(), new NamedList<>(bucket.getResults()));
+    }
+    return results;
+  }
+  
+  @Override
+  public Iterable<Map<String,Object>> createResponse() {
+    final LinkedList<Map<String,Object>> results = new LinkedList<>();
+    // Export each expression in the bucket.
+    for (FacetBucket bucket : getBuckets()) {
+      Map<String, Object> bucketMap = new HashMap<>();
+      bucketMap.put(AnalyticsResponseHeadings.FACET_VALUE, bucket.getFacetValue());
+      bucketMap.put(AnalyticsResponseHeadings.RESULTS, bucket.getResults());
+      results.add(bucketMap);
+    }
+    return results;
+  }
+  
+  private Iterable<FacetBucket> getBuckets() {
+    final List<FacetBucket> facetResults = new ArrayList<>();
+    reductionData.forEach((facetVal, dataCol) -> {
+      collectionManager.setData(dataCol);
+      facetResults.add(new FacetBucket(facetVal,expressionCalculator.getResults()));
+    });
+    
+    return applyOptions(facetResults);
+  }
+
+  /**
+   * Apply the sorting options to the given facet results.
+   * 
+   * @param facetResults to apply sorting options to
+   * @return the sorted results
+   */
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  protected Iterable<FacetBucket> applyOptions(List<FacetBucket> facetResults) {
+    // Sorting the buckets if a sort specification is provided
+    if (sort == null || facetResults.isEmpty()) {
+      return facetResults;
+    }
+    Comparator comp = sort.getComparator();
+    Collections.sort(facetResults, comp);
+    
+    Iterable<FacetBucket> facetResultsIter = facetResults;
+    // apply the limit
+    if (sort.getLimit() > 0) {
+      if (sort.getOffset() > 0) {
+        facetResultsIter = Iterables.skip(facetResultsIter, sort.getOffset());
+      }
+      facetResultsIter = Iterables.limit(facetResultsIter, sort.getLimit());
+    } else if (sort.getLimit() == 0) {
+      return new LinkedList<FacetBucket>();
+    }
+    return facetResultsIter;
+  }
+  
+  /**
+   * Specifies how to sort the buckets of a sortable facet.
+   */
+  public static class FacetSortSpecification {
+    private FacetResultsComparator comparator;
+    protected int limit;
+    protected int offset;
+    
+    public FacetSortSpecification(FacetResultsComparator comparator, int limit, int offset) {
+      this.comparator = comparator;
+      this.limit = limit;
+      this.offset = offset;
+    }
+
+    public FacetResultsComparator getComparator() {
+      return comparator;
+    }
+
+    /**
+     * Get the maximum number of buckets to be returned.
+     * 
+     * @return the limit
+     */
+    public int getLimit() {
+      return limit;
+    }
+    /**
+     * Set the maximum number of buckets to be returned.
+     * 
+     * @param limit the maximum number of buckets
+     */
+    public void setLimit(int limit) {
+      this.limit = limit;
+    }
+    
+    /**
+     * Get the first bucket to return, has to be used with the {@code limit} option.
+     * 
+     * @return the bucket offset
+     */
+    public int getOffset() {
+      return offset;
+    }
+  }
+
+  public SortableFacet.FacetSortSpecification getSort() {
+    return sort;
+  }
+
+  public void setSort(SortableFacet.FacetSortSpecification sort) {
+    this.sort = sort;
+  }
+  
+  public static class FacetBucket {
+    private final String facetValue;
+    private final Map<String,Object> expressionResults;
+    
+    public FacetBucket(String facetValue, Map<String,Object> expressionResults) {
+      this.facetValue = facetValue;
+      this.expressionResults = expressionResults;
+    }
+    
+    public Object getResult(String expression) {
+      return expressionResults.get(expression);
+    }
+    
+    public Map<String,Object> getResults() {
+      return expressionResults;
+    }
+    
+    public String getFacetValue() {
+      return facetValue;
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/StreamingFacet.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/StreamingFacet.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/StreamingFacet.java
new file mode 100644
index 0000000..6cca041
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/StreamingFacet.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import org.apache.solr.analytics.AnalyticsDriver;
+import org.apache.solr.analytics.function.ReductionCollectionManager;
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+
+/**
+ * A facet that is collected during the streaming phase of the {@link AnalyticsDriver}.
+ */
+public interface StreamingFacet {
+  /**
+   * Determine which facet values match the current document. Add the {@link ReductionDataCollection}s of the relevant facet values
+   * to the targets of the streaming {@link ReductionCollectionManager} so that they are updated with the current document's data.
+   */
+  void addFacetValueCollectionTargets();
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/ValueFacet.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/ValueFacet.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/ValueFacet.java
new file mode 100644
index 0000000..b1d84ba
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/ValueFacet.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet;
+
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+import org.apache.solr.analytics.value.StringValueStream;
+
+/**
+ * A facet that breaks up data by the values of a mapping expression or field.
+ * The mapping expression must be castable to a {@link StringValueStream}.
+ */
+public class ValueFacet extends SortableFacet implements StreamingFacet, Consumer<String> {
+  private StringValueStream expression;
+
+  public ValueFacet(String name, StringValueStream expression) {
+    super(name);
+    this.expression = expression;
+  }
+
+  @Override
+  public void addFacetValueCollectionTargets() {
+    expression.streamStrings(this);
+  }
+    
+  @Override
+  public void accept(String t) {
+    ReductionDataCollection collection = reductionData.get(t);
+    if (collection == null) {
+      collection = collectionManager.newDataCollectionTarget();
+      reductionData.put(t, collection);
+    } else {
+      collectionManager.addCollectTarget(collection);
+    }
+  }
+  
+  /**
+   * Get the expression used to create the facet values.
+   * 
+   * @return a string mapping expression
+   */
+  public StringValueStream getExpression() {
+    return expression;
+  }
+}
\ No newline at end of file


[44/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-1095: Refactor code to standardize replica assignment

Posted by ab...@apache.org.
SOLR-1095: Refactor code to standardize replica assignment


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/196d84b9
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/196d84b9
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/196d84b9

Branch: refs/heads/jira/solr-10879
Commit: 196d84b9e08730e9af225450217032cf70d52b5a
Parents: 0159d49
Author: Noble Paul <no...@apache.org>
Authored: Fri Jun 30 15:49:40 2017 +0930
Committer: Noble Paul <no...@apache.org>
Committed: Fri Jun 30 15:49:40 2017 +0930

----------------------------------------------------------------------
 .../src/java/org/apache/solr/cloud/Assign.java  | 131 ++++++++++++++++---
 .../apache/solr/cloud/CreateCollectionCmd.java  |  31 ++---
 .../java/org/apache/solr/cloud/RestoreCmd.java  |  30 +++--
 .../org/apache/solr/cloud/SplitShardCmd.java    |  13 +-
 .../apache/solr/cloud/rule/ReplicaAssigner.java |  68 ++++------
 .../solr/common/cloud/ReplicaPosition.java      |  55 ++++++++
 .../apache/solr/cloud/rule/RuleEngineTest.java  |   8 +-
 7 files changed, 234 insertions(+), 102 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/196d84b9/solr/core/src/java/org/apache/solr/cloud/Assign.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/Assign.java b/solr/core/src/java/org/apache/solr/cloud/Assign.java
index 9f21245..7c9752d 100644
--- a/solr/core/src/java/org/apache/solr/cloud/Assign.java
+++ b/solr/core/src/java/org/apache/solr/cloud/Assign.java
@@ -25,10 +25,14 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Random;
 import java.util.Set;
+import java.util.function.Supplier;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
+import com.google.common.collect.ImmutableMap;
 import org.apache.solr.client.solrj.cloud.autoscaling.Policy;
 import org.apache.solr.client.solrj.cloud.autoscaling.PolicyHelper;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
@@ -40,7 +44,9 @@ import org.apache.solr.common.SolrException;
 import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.DocCollection;
 import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.ReplicaPosition;
 import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.common.cloud.ZkNodeProps;
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.common.util.Utils;
@@ -49,6 +55,11 @@ import org.apache.zookeeper.KeeperException;
 
 import static java.util.Collections.singletonMap;
 import static org.apache.solr.client.solrj.cloud.autoscaling.Policy.POLICY;
+import static org.apache.solr.cloud.OverseerCollectionMessageHandler.CREATE_NODE_SET;
+import static org.apache.solr.cloud.OverseerCollectionMessageHandler.CREATE_NODE_SET_EMPTY;
+import static org.apache.solr.cloud.OverseerCollectionMessageHandler.CREATE_NODE_SET_SHUFFLE;
+import static org.apache.solr.cloud.OverseerCollectionMessageHandler.CREATE_NODE_SET_SHUFFLE_DEFAULT;
+import static org.apache.solr.common.cloud.DocCollection.SNITCH;
 import static org.apache.solr.common.cloud.ZkStateReader.CORE_NAME_PROP;
 import static org.apache.solr.common.cloud.ZkStateReader.MAX_SHARDS_PER_NODE;
 import static org.apache.solr.common.cloud.ZkStateReader.SOLR_AUTOSCALING_CONF_PATH;
@@ -119,7 +130,7 @@ public class Assign {
     returnShardId = shardIdNames.get(0);
     return returnShardId;
   }
-  
+
   public static String buildCoreName(String collectionName, String shard, Replica.Type type, int replicaNum) {
     // TODO: Adding the suffix is great for debugging, but may be an issue if at some point we want to support a way to change replica type
     return String.format(Locale.ROOT, "%s_%s_replica_%s%s", collectionName, shard, type.name().substring(0,1).toLowerCase(Locale.ROOT), replicaNum);
@@ -141,6 +152,91 @@ public class Assign {
       else return replicaName;
     }
   }
+  public static List<String> getLiveOrLiveAndCreateNodeSetList(final Set<String> liveNodes, final ZkNodeProps message, final Random random) {
+    // TODO: add smarter options that look at the current number of cores per
+    // node?
+    // for now we just go random (except when createNodeSet and createNodeSet.shuffle=false are passed in)
+
+    List<String> nodeList;
+
+    final String createNodeSetStr = message.getStr(CREATE_NODE_SET);
+    final List<String> createNodeList = (createNodeSetStr == null) ? null : StrUtils.splitSmart((CREATE_NODE_SET_EMPTY.equals(createNodeSetStr) ? "" : createNodeSetStr), ",", true);
+
+    if (createNodeList != null) {
+      nodeList = new ArrayList<>(createNodeList);
+      nodeList.retainAll(liveNodes);
+      if (message.getBool(CREATE_NODE_SET_SHUFFLE, CREATE_NODE_SET_SHUFFLE_DEFAULT)) {
+        Collections.shuffle(nodeList, random);
+      }
+    } else {
+      nodeList = new ArrayList<>(liveNodes);
+      Collections.shuffle(nodeList, random);
+    }
+
+    return nodeList;
+  }
+
+  public static List<ReplicaPosition> identifyNodes(Supplier<CoreContainer> coreContainer,
+                                                    ZkStateReader zkStateReader,
+                                                    ClusterState clusterState,
+                                                    List<String> nodeList,
+                                                    String collectionName,
+                                                    ZkNodeProps message,
+                                                    List<String> shardNames,
+                                                    int numNrtReplicas,
+                                                    int numTlogReplicas,
+                                                    int numPullReplicas) throws KeeperException, InterruptedException {
+    List<Map> rulesMap = (List) message.get("rule");
+    String policyName = message.getStr(POLICY);
+    Map autoScalingJson = Utils.getJson(zkStateReader.getZkClient(), SOLR_AUTOSCALING_CONF_PATH, true);
+
+    if (rulesMap == null && policyName == null) {
+      int i = 0;
+      List<ReplicaPosition> result = new ArrayList<>();
+      for (String aShard : shardNames) {
+
+        for (Map.Entry<Replica.Type, Integer> e : ImmutableMap.of(Replica.Type.NRT, numNrtReplicas,
+            Replica.Type.TLOG, numTlogReplicas,
+            Replica.Type.PULL, numPullReplicas
+        ).entrySet()) {
+          for (int j = 0; j < e.getValue(); j++){
+            result.add(new ReplicaPosition(aShard, j, e.getKey(), nodeList.get(i % nodeList.size())));
+            i++;
+          }
+        }
+
+      }
+      return result;
+    } else {
+      if (numTlogReplicas + numPullReplicas != 0) {
+        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+            Replica.Type.TLOG + " or " + Replica.Type.PULL + " replica types not supported with placement rules or cluster policies");
+      }
+    }
+
+    if (policyName != null || autoScalingJson.get(Policy.CLUSTER_POLICY) != null) {
+      return getPositionsUsingPolicy(collectionName,
+          shardNames, numNrtReplicas, policyName, zkStateReader, nodeList);
+    } else {
+      List<Rule> rules = new ArrayList<>();
+      for (Object map : rulesMap) rules.add(new Rule((Map) map));
+      Map<String, Integer> sharVsReplicaCount = new HashMap<>();
+
+      for (String shard : shardNames) sharVsReplicaCount.put(shard, numNrtReplicas);
+      ReplicaAssigner replicaAssigner = new ReplicaAssigner(rules,
+          sharVsReplicaCount,
+          (List<Map>) message.get(SNITCH),
+          new HashMap<>(),//this is a new collection. So, there are no nodes in any shard
+          nodeList,
+          coreContainer.get(),
+          clusterState);
+
+      Map<ReplicaPosition, String> nodeMappings = replicaAssigner.getNodeMappings();
+      return nodeMappings.entrySet().stream()
+          .map(e -> new ReplicaPosition(e.getKey().shard, e.getKey().index, e.getKey().type, e.getValue()))
+          .collect(Collectors.toList());
+    }
+  }
 
   static class ReplicaCount {
     public final String nodeName;
@@ -191,21 +287,21 @@ public class Assign {
     }
 
     List l = (List) coll.get(DocCollection.RULE);
-    Map<ReplicaAssigner.Position, String> positions = null;
+    List<ReplicaPosition> replicaPositions = null;
     if (l != null) {
-      positions = getNodesViaRules(clusterState, shard, numberOfNodes, cc, coll, createNodeList, l);
+      replicaPositions = getNodesViaRules(clusterState, shard, numberOfNodes, cc, coll, createNodeList, l);
     }
     String policyName = coll.getStr(POLICY);
     Map autoScalingJson = Utils.getJson(cc.getZkController().getZkClient(), SOLR_AUTOSCALING_CONF_PATH, true);
     if (policyName != null || autoScalingJson.get(Policy.CLUSTER_POLICY) != null) {
-      positions= Assign.getPositionsUsingPolicy(collectionName, Collections.singletonList(shard), numberOfNodes,
+      replicaPositions = Assign.getPositionsUsingPolicy(collectionName, Collections.singletonList(shard), numberOfNodes,
           policyName, cc.getZkController().getZkStateReader(), createNodeList);
     }
 
-    if(positions != null){
+    if(replicaPositions != null){
       List<ReplicaCount> repCounts = new ArrayList<>();
-      for (String s : positions.values()) {
-        repCounts.add(new ReplicaCount(s));
+      for (ReplicaPosition p : replicaPositions) {
+        repCounts.add(new ReplicaCount(p.node));
       }
       return repCounts;
     }
@@ -215,9 +311,10 @@ public class Assign {
     return sortedNodeList;
 
   }
-  public static Map<ReplicaAssigner.Position, String> getPositionsUsingPolicy(String collName, List<String> shardNames, int numReplicas,
-                                                                              String policyName, ZkStateReader zkStateReader,
-                                                                              List<String> nodesList) throws KeeperException, InterruptedException {
+
+  public static List<ReplicaPosition> getPositionsUsingPolicy(String collName, List<String> shardNames, int numReplicas,
+                                                              String policyName, ZkStateReader zkStateReader,
+                                                              List<String> nodesList) throws KeeperException, InterruptedException {
     try (CloudSolrClient csc = new CloudSolrClient.Builder()
         .withClusterStateProvider(new ZkClientClusterStateProvider(zkStateReader))
         .build()) {
@@ -226,11 +323,11 @@ public class Assign {
       Map<String, List<String>> locations = PolicyHelper.getReplicaLocations(collName,
           autoScalingJson,
           clientDataProvider, singletonMap(collName, policyName), shardNames, numReplicas, nodesList);
-      Map<ReplicaAssigner.Position, String> result = new HashMap<>();
+      List<ReplicaPosition> result = new ArrayList<>();
       for (Map.Entry<String, List<String>> e : locations.entrySet()) {
         List<String> value = e.getValue();
         for (int i = 0; i < value.size(); i++) {
-          result.put(new ReplicaAssigner.Position(e.getKey(), i, Replica.Type.NRT), value.get(i));
+          result.add(new ReplicaPosition(e.getKey(), i, Replica.Type.NRT, value.get(i)));
         }
       }
       return result;
@@ -239,8 +336,8 @@ public class Assign {
     }
   }
 
-  private static Map<ReplicaAssigner.Position, String> getNodesViaRules(ClusterState clusterState, String shard, int numberOfNodes,
-                                                                        CoreContainer cc, DocCollection coll, List<String> createNodeList, List l) {
+  private static List<ReplicaPosition> getNodesViaRules(ClusterState clusterState, String shard, int numberOfNodes,
+                                                        CoreContainer cc, DocCollection coll, List<String> createNodeList, List l) {
     ArrayList<Rule> rules = new ArrayList<>();
     for (Object o : l) rules.add(new Rule((Map) o));
     Map<String, Map<String, Integer>> shardVsNodes = new LinkedHashMap<>();
@@ -253,18 +350,18 @@ public class Assign {
         n.put(replica.getNodeName(), ++count);
       }
     }
-    List snitches = (List) coll.get(DocCollection.SNITCH);
+    List snitches = (List) coll.get(SNITCH);
     List<String> nodesList = createNodeList == null ?
         new ArrayList<>(clusterState.getLiveNodes()) :
         createNodeList;
-    Map<ReplicaAssigner.Position, String> positions = new ReplicaAssigner(
+    Map<ReplicaPosition, String> positions = new ReplicaAssigner(
         rules,
         Collections.singletonMap(shard, numberOfNodes),
         snitches,
         shardVsNodes,
         nodesList, cc, clusterState).getNodeMappings();
 
-    return positions;// getReplicaCounts(positions);
+    return positions.entrySet().stream().map(e -> e.getKey().setNode(e.getValue())).collect(Collectors.toList());// getReplicaCounts(positions);
   }
 
   private static HashMap<String, ReplicaCount> getNodeNameVsShardCount(String collectionName,

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/196d84b9/solr/core/src/java/org/apache/solr/cloud/CreateCollectionCmd.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/CreateCollectionCmd.java b/solr/core/src/java/org/apache/solr/cloud/CreateCollectionCmd.java
index 0c87658..7d3df70 100644
--- a/solr/core/src/java/org/apache/solr/cloud/CreateCollectionCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/CreateCollectionCmd.java
@@ -31,7 +31,7 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.solr.cloud.OverseerCollectionMessageHandler.Cmd;
 import org.apache.solr.cloud.overseer.ClusterStateMutator;
-import org.apache.solr.cloud.rule.ReplicaAssigner;
+import org.apache.solr.common.cloud.ReplicaPosition;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.cloud.ClusterState;
@@ -131,12 +131,12 @@ public class CreateCollectionCmd implements Cmd {
       // add our new cores to existing nodes serving the least number of cores
       // but (for now) require that each core goes on a distinct node.
 
-      final List<String> nodeList = OverseerCollectionMessageHandler.getLiveOrLiveAndCreateNodeSetList(clusterState.getLiveNodes(), message, RANDOM);
-      Map<ReplicaAssigner.Position, String> positionVsNodes;
+      final List<String> nodeList = Assign.getLiveOrLiveAndCreateNodeSetList(clusterState.getLiveNodes(), message, RANDOM);
+      List<ReplicaPosition> replicaPositions;
       if (nodeList.isEmpty()) {
         log.warn("It is unusual to create a collection ("+collectionName+") without cores.");
 
-        positionVsNodes = new HashMap<>();
+        replicaPositions = new ArrayList<>();
       } else {
         int totalNumReplicas = numNrtReplicas + numTlogReplicas + numPullReplicas;
         if (totalNumReplicas > nodeList.size()) {
@@ -164,7 +164,9 @@ public class CreateCollectionCmd implements Cmd {
               + " shards to be created (higher than the allowed number)");
         }
 
-        positionVsNodes = ocmh.identifyNodes(clusterState, nodeList, collectionName, message, shardNames, numNrtReplicas, numTlogReplicas, numPullReplicas);
+        replicaPositions = Assign.identifyNodes(() -> ocmh.overseer.getZkController().getCoreContainer(),
+            ocmh.zkStateReader
+            , clusterState, nodeList, collectionName, message, shardNames, numNrtReplicas, numTlogReplicas, numPullReplicas);
       }
 
       ZkStateReader zkStateReader = ocmh.zkStateReader;
@@ -207,12 +209,11 @@ public class CreateCollectionCmd implements Cmd {
       log.debug(formatString("Creating SolrCores for new collection {0}, shardNames {1} , nrtReplicas : {2}, tlogReplicas: {3}, pullReplicas: {4}",
           collectionName, shardNames, numNrtReplicas, numTlogReplicas, numPullReplicas));
       Map<String,ShardRequest> coresToCreate = new LinkedHashMap<>();
-      for (Map.Entry<ReplicaAssigner.Position, String> e : positionVsNodes.entrySet()) {
-        ReplicaAssigner.Position position = e.getKey();
-        String nodeName = e.getValue();
-        String coreName = Assign.buildCoreName(collectionName, position.shard, position.type, position.index + 1);
+      for (ReplicaPosition replicaPosition : replicaPositions) {
+        String nodeName = replicaPosition.node;
+        String coreName = Assign.buildCoreName(collectionName, replicaPosition.shard, replicaPosition.type, replicaPosition.index + 1);
         log.debug(formatString("Creating core {0} as part of shard {1} of collection {2} on {3}"
-            , coreName, position.shard, collectionName, nodeName));
+            , coreName, replicaPosition.shard, collectionName, nodeName));
 
 
         String baseUrl = zkStateReader.getBaseUrlForNodeName(nodeName);
@@ -222,11 +223,11 @@ public class CreateCollectionCmd implements Cmd {
           ZkNodeProps props = new ZkNodeProps(
               Overseer.QUEUE_OPERATION, ADDREPLICA.toString(),
               ZkStateReader.COLLECTION_PROP, collectionName,
-              ZkStateReader.SHARD_ID_PROP, position.shard,
+              ZkStateReader.SHARD_ID_PROP, replicaPosition.shard,
               ZkStateReader.CORE_NAME_PROP, coreName,
               ZkStateReader.STATE_PROP, Replica.State.DOWN.toString(),
-              ZkStateReader.BASE_URL_PROP, baseUrl, 
-              ZkStateReader.REPLICA_TYPE, position.type.name());
+              ZkStateReader.BASE_URL_PROP, baseUrl,
+              ZkStateReader.REPLICA_TYPE, replicaPosition.type.name());
           Overseer.getStateUpdateQueue(zkStateReader.getZkClient()).offer(Utils.toJSON(props));
         }
 
@@ -237,10 +238,10 @@ public class CreateCollectionCmd implements Cmd {
         params.set(CoreAdminParams.NAME, coreName);
         params.set(COLL_CONF, configName);
         params.set(CoreAdminParams.COLLECTION, collectionName);
-        params.set(CoreAdminParams.SHARD, position.shard);
+        params.set(CoreAdminParams.SHARD, replicaPosition.shard);
         params.set(ZkStateReader.NUM_SHARDS_PROP, numSlices);
         params.set(CoreAdminParams.NEW_COLLECTION, "true");
-        params.set(CoreAdminParams.REPLICA_TYPE, position.type.name());
+        params.set(CoreAdminParams.REPLICA_TYPE, replicaPosition.type.name());
 
         if (async != null) {
           String coreAdminAsyncId = async + Math.abs(System.nanoTime());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/196d84b9/solr/core/src/java/org/apache/solr/cloud/RestoreCmd.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/RestoreCmd.java b/solr/core/src/java/org/apache/solr/cloud/RestoreCmd.java
index 6a18bff..fa493c7 100644
--- a/solr/core/src/java/org/apache/solr/cloud/RestoreCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/RestoreCmd.java
@@ -28,12 +28,13 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
 
 import org.apache.solr.cloud.overseer.OverseerAction;
-import org.apache.solr.cloud.rule.ReplicaAssigner;
+import org.apache.solr.common.cloud.ReplicaPosition;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.cloud.ClusterState;
@@ -108,7 +109,7 @@ public class RestoreCmd implements OverseerCollectionMessageHandler.Cmd {
     DocCollection backupCollectionState = backupMgr.readCollectionState(location, backupName, backupCollection);
 
     // Get the Solr nodes to restore a collection.
-    final List<String> nodeList = OverseerCollectionMessageHandler.getLiveOrLiveAndCreateNodeSetList(
+    final List<String> nodeList = Assign.getLiveOrLiveAndCreateNodeSetList(
         zkStateReader.getClusterState().getLiveNodes(), message, RANDOM);
 
     int numShards = backupCollectionState.getActiveSlices().size();
@@ -213,8 +214,11 @@ public class RestoreCmd implements OverseerCollectionMessageHandler.Cmd {
     List<String> sliceNames = new ArrayList<>();
     restoreCollection.getSlices().forEach(x -> sliceNames.add(x.getName()));
 
-    Map<ReplicaAssigner.Position, String> positionVsNodes = ocmh.identifyNodes(clusterState, nodeList,
-        restoreCollectionName, message, sliceNames, numNrtReplicas, numTlogReplicas, numPullReplicas);
+    List<ReplicaPosition> replicaPositions = Assign.identifyNodes(() -> ocmh.overseer.getZkController().getCoreContainer(),
+        ocmh.zkStateReader, clusterState,
+        nodeList, restoreCollectionName,
+        message, sliceNames,
+        numNrtReplicas, numTlogReplicas, numPullReplicas);
 
     //Create one replica per shard and copy backed up data to it
     for (Slice slice : restoreCollection.getSlices()) {
@@ -235,12 +239,11 @@ public class RestoreCmd implements OverseerCollectionMessageHandler.Cmd {
 
       // Get the first node matching the shard to restore in
       String node;
-      for (Map.Entry<ReplicaAssigner.Position, String> pvn : positionVsNodes.entrySet()) {
-        ReplicaAssigner.Position position = pvn.getKey();
-        if (position.shard == slice.getName()) {
-          node = pvn.getValue();
+      for (ReplicaPosition replicaPosition : replicaPositions) {
+        if (Objects.equals(replicaPosition.shard, slice.getName())) {
+          node = replicaPosition.node;
           propMap.put(CoreAdminParams.NODE, node);
-          positionVsNodes.remove(position);
+          replicaPositions.remove(replicaPosition);
           break;
         }
       }
@@ -319,12 +322,11 @@ public class RestoreCmd implements OverseerCollectionMessageHandler.Cmd {
 
           // Get the first node matching the shard to restore in
           String node;
-          for (Map.Entry<ReplicaAssigner.Position, String> pvn : positionVsNodes.entrySet()) {
-            ReplicaAssigner.Position position = pvn.getKey();
-            if (position.shard == slice.getName()) {
-              node = pvn.getValue();
+          for (ReplicaPosition replicaPosition : replicaPositions) {
+            if (Objects.equals(replicaPosition.shard, slice.getName())) {
+              node = replicaPosition.node;
               propMap.put(CoreAdminParams.NODE, node);
-              positionVsNodes.remove(position);
+              replicaPositions.remove(replicaPosition);
               break;
             }
           }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/196d84b9/solr/core/src/java/org/apache/solr/cloud/SplitShardCmd.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/SplitShardCmd.java b/solr/core/src/java/org/apache/solr/cloud/SplitShardCmd.java
index 2e2e335..099190c 100644
--- a/solr/core/src/java/org/apache/solr/cloud/SplitShardCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/SplitShardCmd.java
@@ -30,7 +30,7 @@ import java.util.Set;
 import org.apache.solr.client.solrj.request.CoreAdminRequest;
 import org.apache.solr.cloud.OverseerCollectionMessageHandler.Cmd;
 import org.apache.solr.cloud.overseer.OverseerAction;
-import org.apache.solr.cloud.rule.ReplicaAssigner;
+import org.apache.solr.common.cloud.ReplicaPosition;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.CompositeIdRouter;
@@ -381,7 +381,8 @@ public class SplitShardCmd implements Cmd {
 
       // TODO: change this to handle sharding a slice into > 2 sub-shards.
 
-      Map<ReplicaAssigner.Position, String> nodeMap = ocmh.identifyNodes(clusterState,
+      List<ReplicaPosition> replicaPositions = Assign.identifyNodes(() -> ocmh.overseer.getZkController().getCoreContainer(),
+          ocmh.zkStateReader, clusterState,
           new ArrayList<>(clusterState.getLiveNodes()),
           collectionName,
           new ZkNodeProps(collection.getProperties()),
@@ -389,10 +390,10 @@ public class SplitShardCmd implements Cmd {
 
       List<Map<String, Object>> replicas = new ArrayList<>((repFactor - 1) * 2);
 
-      for (Map.Entry<ReplicaAssigner.Position, String> entry : nodeMap.entrySet()) {
-        String sliceName = entry.getKey().shard;
-        String subShardNodeName = entry.getValue();
-        String shardName = collectionName + "_" + sliceName + "_replica" + (entry.getKey().index);
+      for (ReplicaPosition replicaPosition : replicaPositions) {
+        String sliceName = replicaPosition.shard;
+        String subShardNodeName = replicaPosition.node;
+        String shardName = collectionName + "_" + sliceName + "_replica" + (replicaPosition.index);
 
         log.info("Creating replica shard " + shardName + " as part of slice " + sliceName + " of collection "
             + collectionName + " on " + subShardNodeName);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/196d84b9/solr/core/src/java/org/apache/solr/cloud/rule/ReplicaAssigner.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/rule/ReplicaAssigner.java b/solr/core/src/java/org/apache/solr/cloud/rule/ReplicaAssigner.java
index 669e82b..8887e53 100644
--- a/solr/core/src/java/org/apache/solr/cloud/rule/ReplicaAssigner.java
+++ b/solr/core/src/java/org/apache/solr/cloud/rule/ReplicaAssigner.java
@@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicReference;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.DocCollection;
+import org.apache.solr.common.cloud.ReplicaPosition;
 import org.apache.solr.common.cloud.Replica;
 import org.apache.solr.common.cloud.Slice;
 import org.apache.solr.common.cloud.rule.ImplicitSnitch;
@@ -59,31 +60,6 @@ public class ReplicaAssigner {
   private Map<String, AtomicInteger> nodeVsCores = new HashMap<>();
 
 
-  public static class Position implements Comparable<Position> {
-    public final String shard;
-    public final int index;
-    public final Replica.Type type;
-
-    public Position(String shard, int replicaIdx, Replica.Type type) {
-      this.shard = shard;
-      this.index = replicaIdx;
-      this.type = type;
-    }
-
-    @Override
-    public int compareTo(Position that) {
-      //this is to ensure that we try one replica from each shard first instead of
-      // all replicas from same shard
-      return that.index > index ? -1 : that.index == index ? 0 : 1;
-    }
-
-    @Override
-    public String toString() {
-      return shard + ":" + index;
-    }
-  }
-
-
   /**
    * @param shardVsReplicaCount shard names vs no:of replicas required for each of those shards
    * @param snitches            snitches details
@@ -128,8 +104,8 @@ public class ReplicaAssigner {
    * For each shard return a new set of nodes where the replicas need to be created satisfying
    * the specified rule
    */
-  public Map<Position, String> getNodeMappings() {
-    Map<Position, String> result = getNodeMappings0();
+  public Map<ReplicaPosition, String> getNodeMappings() {
+    Map<ReplicaPosition, String> result = getNodeMappings0();
     if (result == null) {
       String msg = "Could not identify nodes matching the rules " + rules;
       if (!failedNodes.isEmpty()) {
@@ -149,7 +125,7 @@ public class ReplicaAssigner {
 
   }
 
-  Map<Position, String> getNodeMappings0() {
+  Map<ReplicaPosition, String> getNodeMappings0() {
     List<String> shardNames = new ArrayList<>(shardVsReplicaCount.keySet());
     int[] shardOrder = new int[shardNames.size()];
     for (int i = 0; i < shardNames.size(); i++) shardOrder[i] = i;
@@ -168,17 +144,17 @@ public class ReplicaAssigner {
       }
     }
 
-    Map<Position, String> result = tryAllPermutations(shardNames, shardOrder, nonWildCardShardRules, false);
+    Map<ReplicaPosition, String> result = tryAllPermutations(shardNames, shardOrder, nonWildCardShardRules, false);
     if (result == null && hasFuzzyRules) {
       result = tryAllPermutations(shardNames, shardOrder, nonWildCardShardRules, true);
     }
     return result;
   }
 
-  private Map<Position, String> tryAllPermutations(List<String> shardNames,
-                                                   int[] shardOrder,
-                                                   int nonWildCardShardRules,
-                                                   boolean fuzzyPhase) {
+  private Map<ReplicaPosition, String> tryAllPermutations(List<String> shardNames,
+                                                          int[] shardOrder,
+                                                          int nonWildCardShardRules,
+                                                          boolean fuzzyPhase) {
 
 
     Iterator<int[]> shardPermutations = nonWildCardShardRules > 0 ?
@@ -187,16 +163,16 @@ public class ReplicaAssigner {
 
     for (; shardPermutations.hasNext(); ) {
       int[] p = shardPermutations.next();
-      List<Position> positions = new ArrayList<>();
+      List<ReplicaPosition> replicaPositions = new ArrayList<>();
       for (int pos : p) {
         for (int j = 0; j < shardVsReplicaCount.get(shardNames.get(pos)); j++) {
-          positions.add(new Position(shardNames.get(pos), j, Replica.Type.NRT));
+          replicaPositions.add(new ReplicaPosition(shardNames.get(pos), j, Replica.Type.NRT));
         }
       }
-      Collections.sort(positions);
+      Collections.sort(replicaPositions);
       for (Iterator<int[]> it = permutations(rules.size()); it.hasNext(); ) {
         int[] permutation = it.next();
-        Map<Position, String> result = tryAPermutationOfRules(permutation, positions, fuzzyPhase);
+        Map<ReplicaPosition, String> result = tryAPermutationOfRules(permutation, replicaPositions, fuzzyPhase);
         if (result != null) return result;
       }
     }
@@ -205,9 +181,9 @@ public class ReplicaAssigner {
   }
 
 
-  private Map<Position, String> tryAPermutationOfRules(int[] rulePermutation, List<Position> positions, boolean fuzzyPhase) {
+  private Map<ReplicaPosition, String> tryAPermutationOfRules(int[] rulePermutation, List<ReplicaPosition> replicaPositions, boolean fuzzyPhase) {
     Map<String, Map<String, Object>> nodeVsTagsCopy = getDeepCopy(nodeVsTags, 2);
-    Map<Position, String> result = new LinkedHashMap<>();
+    Map<ReplicaPosition, String> result = new LinkedHashMap<>();
     int startPosition = 0;
     Map<String, Map<String, Integer>> copyOfCurrentState = getDeepCopy(shardVsNodes, 2);
     List<String> sortedLiveNodes = new ArrayList<>(this.participatingLiveNodes);
@@ -232,7 +208,7 @@ public class ReplicaAssigner {
       return result1;
     });
     forEachPosition:
-    for (Position position : positions) {
+    for (ReplicaPosition replicaPosition : replicaPositions) {
       //trying to assign a node by verifying each rule in this rulePermutation
       forEachNode:
       for (int j = 0; j < sortedLiveNodes.size(); j++) {
@@ -242,16 +218,16 @@ public class ReplicaAssigner {
           Rule rule = rules.get(rulePermutation[i]);
           //trying to assign a replica into this node in this shard
           Rule.MatchStatus status = rule.tryAssignNodeToShard(liveNode,
-              copyOfCurrentState, nodeVsTagsCopy, position.shard, fuzzyPhase ? FUZZY_ASSIGN : ASSIGN);
+              copyOfCurrentState, nodeVsTagsCopy, replicaPosition.shard, fuzzyPhase ? FUZZY_ASSIGN : ASSIGN);
           if (status == Rule.MatchStatus.CANNOT_ASSIGN_FAIL) {
             continue forEachNode;//try another node for this position
           }
         }
         //We have reached this far means this node can be applied to this position
         //and all rules are fine. So let us change the currentState
-        result.put(position, liveNode);
-        Map<String, Integer> nodeNames = copyOfCurrentState.get(position.shard);
-        if (nodeNames == null) copyOfCurrentState.put(position.shard, nodeNames = new HashMap<>());
+        result.put(replicaPosition, liveNode);
+        Map<String, Integer> nodeNames = copyOfCurrentState.get(replicaPosition.shard);
+        if (nodeNames == null) copyOfCurrentState.put(replicaPosition.shard, nodeNames = new HashMap<>());
         Integer n = nodeNames.get(liveNode);
         n = n == null ? 1 : n + 1;
         nodeNames.put(liveNode, n);
@@ -267,11 +243,11 @@ public class ReplicaAssigner {
       return null;
     }
 
-    if (positions.size() > result.size()) {
+    if (replicaPositions.size() > result.size()) {
       return null;
     }
 
-    for (Map.Entry<Position, String> e : result.entrySet()) {
+    for (Map.Entry<ReplicaPosition, String> e : result.entrySet()) {
       for (int i = 0; i < rulePermutation.length; i++) {
         Rule rule = rules.get(rulePermutation[i]);
         Rule.MatchStatus matchStatus = rule.tryAssignNodeToShard(e.getValue(),

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/196d84b9/solr/core/src/java/org/apache/solr/common/cloud/ReplicaPosition.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/common/cloud/ReplicaPosition.java b/solr/core/src/java/org/apache/solr/common/cloud/ReplicaPosition.java
new file mode 100644
index 0000000..d64d1d1
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/common/cloud/ReplicaPosition.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.common.cloud;
+
+
+public class ReplicaPosition implements Comparable<ReplicaPosition> {
+  public final String shard;
+  public final int index;
+  public final Replica.Type type;
+  public String node;
+
+  public ReplicaPosition(String shard, int replicaIdx, Replica.Type type) {
+    this.shard = shard;
+    this.index = replicaIdx;
+    this.type = type;
+  }
+  public ReplicaPosition(String shard, int replicaIdx, Replica.Type type, String node) {
+    this.shard = shard;
+    this.index = replicaIdx;
+    this.type = type;
+    this.node = node;
+  }
+
+  @Override
+  public int compareTo(ReplicaPosition that) {
+    //this is to ensure that we try one replica from each shard first instead of
+    // all replicas from same shard
+    return that.index > index ? -1 : that.index == index ? 0 : 1;
+  }
+
+  @Override
+  public String toString() {
+    return shard + ":" + index;
+  }
+
+  public ReplicaPosition setNode(String node) {
+    this.node = node;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/196d84b9/solr/core/src/test/org/apache/solr/cloud/rule/RuleEngineTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/rule/RuleEngineTest.java b/solr/core/src/test/org/apache/solr/cloud/rule/RuleEngineTest.java
index 8b0a788..6d460ed 100644
--- a/solr/core/src/test/org/apache/solr/cloud/rule/RuleEngineTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/rule/RuleEngineTest.java
@@ -28,7 +28,7 @@ import java.util.Set;
 
 import com.google.common.collect.ImmutableList;
 import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.cloud.rule.ReplicaAssigner.Position;
+import org.apache.solr.common.cloud.ReplicaPosition;
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.cloud.rule.Snitch;
 import org.apache.solr.common.cloud.rule.SnitchContext;
@@ -73,7 +73,7 @@ public class RuleEngineTest extends SolrTestCaseJ4{
             "'replica':'1',shard:'*','node':'*'}," +
             " {'freedisk':'>1'}]");
 
-    Map<Position, String> mapping = new ReplicaAssigner(
+    Map<ReplicaPosition, String> mapping = new ReplicaAssigner(
         rules,
         shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null ).getNodeMappings();
@@ -147,7 +147,7 @@ public class RuleEngineTest extends SolrTestCaseJ4{
             "{node:'!127.0.0.1:49947_'}," +
             "{freedisk:'>1'}]");
     Map shardVsReplicaCount = makeMap("shard1", 2, "shard2", 2);
-    Map<Position, String> mapping = new ReplicaAssigner(
+    Map<ReplicaPosition, String> mapping = new ReplicaAssigner(
         rules,
         shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null).getNodeMappings();
@@ -236,7 +236,7 @@ public class RuleEngineTest extends SolrTestCaseJ4{
         "node5:80", makeMap("rack", "182")
     );
     MockSnitch.nodeVsTags = nodeVsTags;
-    Map<Position, String> mapping = new ReplicaAssigner(
+    Map<ReplicaPosition, String> mapping = new ReplicaAssigner(
         rules,
         shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null).getNodeMappings0();


[41/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10272: Fix for test failure, while comparing directory contents of _default configsets

Posted by ab...@apache.org.
SOLR-10272: Fix for test failure, while comparing directory contents of _default configsets


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/46bfd9cf
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/46bfd9cf
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/46bfd9cf

Branch: refs/heads/jira/solr-10879
Commit: 46bfd9cf7e9da99e936fe986af88f4ab47d7fe33
Parents: 9f09620
Author: Ishan Chattopadhyaya <is...@apache.org>
Authored: Thu Jun 29 21:52:19 2017 +0530
Committer: Ishan Chattopadhyaya <is...@apache.org>
Committed: Thu Jun 29 21:52:19 2017 +0530

----------------------------------------------------------------------
 .../core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/46bfd9cf/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
index a9e5837..364108c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
@@ -744,7 +744,11 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 {
         FileVisitResult result = super.preVisitDirectory(dir, attrs);
         Path relativePath = userDefault.toPath().relativize(dir);
         File testDefaultFile = testDefault.toPath().resolve(relativePath).toFile();
-        assertEquals("Mismatch in files", Arrays.toString(dir.toFile().list()), Arrays.toString(testDefaultFile.list()));
+        String[] listOne = dir.toFile().list();
+        String[] listTwo = testDefaultFile.list();
+        Arrays.sort(listOne);
+        Arrays.sort(listTwo);
+        assertEquals("Mismatch in files", Arrays.toString(listOne), Arrays.toString(listTwo));
         return result;
       }
       @Override


[37/58] [abbrv] lucene-solr:jira/solr-10879: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/lucene-solr

Posted by ab...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/lucene-solr


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

Branch: refs/heads/jira/solr-10879
Commit: b4fa0e785b70e39a3a1420bc020ad1183308b7af
Parents: 224f349 92e4603
Author: Karl Wright <Da...@gmail.com>
Authored: Thu Jun 29 05:00:17 2017 -0400
Committer: Karl Wright <Da...@gmail.com>
Committed: Thu Jun 29 05:00:17 2017 -0400

----------------------------------------------------------------------
 .gitignore                                      |   41 +-
 build.xml                                       |   37 +-
 dev-tools/doap/lucene.rdf                       |    7 +
 dev-tools/doap/solr.rdf                         |    7 +
 .../lucene/classification/classification.iml    |    1 -
 .../lucene/spatial-extras/spatial-extras.iml    |    5 +-
 dev-tools/idea/solr/solrj/src/java/solrj.iml    |    3 +
 dev-tools/scripts/checkJavadocLinks.py          |    5 +-
 lucene/CHANGES.txt                              |   86 +
 lucene/MIGRATE.txt                              |   64 +
 lucene/NOTICE.txt                               |    2 +-
 .../lucene/analysis/custom/CustomAnalyzer.java  |   16 +-
 .../miscellaneous/ConcatenatingTokenStream.java |  121 +
 .../DelimitedTermFrequencyTokenFilter.java      |   75 +
 ...elimitedTermFrequencyTokenFilterFactory.java |   53 +
 .../PrefixAndSuffixAwareTokenFilter.java        |   84 -
 .../miscellaneous/PrefixAwareTokenFilter.java   |  202 --
 .../payloads/NumericPayloadTokenFilter.java     |    7 +-
 .../payloads/TypeAsPayloadTokenFilter.java      |    6 +-
 .../lucene/analysis/util/AnalysisSPILoader.java |    2 +-
 .../analysis/util/ClasspathResourceLoader.java  |   12 +-
 .../analysis/util/FilesystemResourceLoader.java |   16 +
 .../wikipedia/WikipediaTokenizerFactory.java    |   21 +-
 ...ache.lucene.analysis.util.TokenFilterFactory |    1 +
 .../lucene/analysis/core/TestFactories.java     |   46 +-
 .../lucene/analysis/core/TestRandomChains.java  |    3 +
 .../DelimitedTermFrequencyTokenFilterTest.java  |   77 +
 .../TestConcatenatingTokenStream.java           |   82 +
 .../TestPrefixAndSuffixAwareTokenFilter.java    |   49 -
 .../TestPrefixAwareTokenFilter.java             |   60 -
 .../TestWikipediaTokenizerFactory.java          |   84 +-
 .../lucene/analysis/ja/TestFactories.java       |   46 +-
 .../index/TestBackwardsCompatibility.java       |    6 +-
 .../org/apache/lucene/index/index.6.6.0-cfs.zip |  Bin 0 -> 15875 bytes
 .../apache/lucene/index/index.6.6.0-nocfs.zip   |  Bin 0 -> 15883 bytes
 .../byTask/feeds/SpatialFileQueryMaker.java     |   15 +-
 lucene/classification/build.xml                 |    6 +-
 .../classification/KNearestFuzzyClassifier.java |   29 +-
 .../classification/utils/DatasetSplitter.java   |    2 +-
 .../classification/utils/NearestFuzzyQuery.java |  333 ++
 .../KNearestFuzzyClassifierTest.java            |    2 +-
 lucene/common-build.xml                         |    2 +-
 .../org/apache/lucene/analysis/Analyzer.java    |    4 +-
 .../java/org/apache/lucene/analysis/Token.java  |  210 --
 .../org/apache/lucene/analysis/TokenStream.java |    7 +-
 .../tokenattributes/CharTermAttributeImpl.java  |    5 -
 .../PackedTokenAttributeImpl.java               |   29 +-
 .../tokenattributes/TermFrequencyAttribute.java |   33 +
 .../TermFrequencyAttributeImpl.java             |   82 +
 .../codecs/blocktree/BlockTreeTermsReader.java  |   37 +-
 .../apache/lucene/document/RangeFieldQuery.java |  377 +-
 .../index/BinaryDocValuesFieldUpdates.java      |  101 +-
 .../apache/lucene/index/BufferedUpdates.java    |   53 +-
 .../lucene/index/BufferedUpdatesStream.java     |  700 +---
 .../apache/lucene/index/CoalescedUpdates.java   |  109 -
 .../org/apache/lucene/index/CodecReader.java    |   11 +-
 .../lucene/index/DefaultIndexingChain.java      |    8 +-
 .../lucene/index/DocValuesFieldUpdates.java     |  190 +-
 .../apache/lucene/index/DocValuesUpdate.java    |    3 -
 .../apache/lucene/index/DocumentsWriter.java    |   66 +-
 .../index/DocumentsWriterDeleteQueue.java       |   29 +-
 .../index/DocumentsWriterFlushControl.java      |   21 +-
 .../lucene/index/DocumentsWriterFlushQueue.java |   33 +-
 .../lucene/index/DocumentsWriterPerThread.java  |   35 +-
 .../index/DocumentsWriterPerThreadPool.java     |   11 +-
 .../lucene/index/ExitableDirectoryReader.java   |   40 +-
 .../apache/lucene/index/FieldInvertState.java   |    3 +
 .../java/org/apache/lucene/index/Fields.java    |   10 +-
 .../apache/lucene/index/FilterLeafReader.java   |    6 +-
 .../lucene/index/FlushByRamOrCountsPolicy.java  |   29 +-
 .../org/apache/lucene/index/FlushPolicy.java    |    3 -
 .../lucene/index/FreqProxTermsWriter.java       |    5 +-
 .../index/FreqProxTermsWriterPerField.java      |   27 +-
 .../lucene/index/FrozenBufferedUpdates.java     |  841 ++++-
 .../apache/lucene/index/IndexFileDeleter.java   |    7 +-
 .../org/apache/lucene/index/IndexWriter.java    |  776 +++--
 .../apache/lucene/index/IndexWriterConfig.java  |   19 +-
 .../org/apache/lucene/index/LeafReader.java     |   15 +-
 .../lucene/index/LiveIndexWriterConfig.java     |   48 +-
 .../apache/lucene/index/MergeReaderWrapper.java |    7 +-
 .../index/MergedPrefixCodedTermsIterator.java   |  132 -
 .../org/apache/lucene/index/MultiFields.java    |   69 +-
 .../index/NumericDocValuesFieldUpdates.java     |   97 +-
 .../apache/lucene/index/ParallelLeafReader.java |   33 +-
 .../apache/lucene/index/PrefixCodedTerms.java   |    2 +-
 .../apache/lucene/index/ReadersAndUpdates.java  |  413 ++-
 .../apache/lucene/index/SegmentCommitInfo.java  |   16 +-
 .../apache/lucene/index/SegmentCoreReaders.java |    2 -
 .../org/apache/lucene/index/SegmentInfo.java    |    2 +-
 .../org/apache/lucene/index/SegmentReader.java  |   19 +-
 .../lucene/index/SerialMergeScheduler.java      |    4 +-
 .../lucene/index/SlowCodecReaderWrapper.java    |   16 +-
 .../apache/lucene/index/SortingLeafReader.java  |    6 +-
 .../index/TermVectorsConsumerPerField.java      |   19 +-
 .../apache/lucene/index/TermsHashPerField.java  |    5 +-
 .../apache/lucene/index/TieredMergePolicy.java  |   73 +-
 .../apache/lucene/search/AutomatonQuery.java    |    7 +
 .../lucene/search/DisjunctionMaxQuery.java      |    8 +
 .../org/apache/lucene/search/DoubleValues.java  |   21 +
 .../lucene/search/DoubleValuesSource.java       |  216 +-
 .../apache/lucene/search/LongValuesSource.java  |   82 +-
 .../apache/lucene/search/TermInSetQuery.java    |    4 +-
 .../java/org/apache/lucene/search/TopDocs.java  |    8 +-
 .../org/apache/lucene/search/TopFieldDocs.java  |    2 +-
 .../org/apache/lucene/util/NamedSPILoader.java  |    2 +-
 .../org/apache/lucene/util/QueryBuilder.java    |    6 +-
 .../apache/lucene/util/SPIClassIterator.java    |   10 +-
 .../util/packed/AbstractPagedMutable.java       |    2 +-
 .../org/apache/lucene/analysis/TestToken.java   |    2 +
 .../TestPackedTokenAttributeImpl.java           |    2 +
 .../lucene50/TestBlockPostingsFormat.java       |    2 +-
 .../org/apache/lucene/index/Test2BDocs.java     |    2 +-
 .../org/apache/lucene/index/Test2BTerms.java    |    2 +-
 .../index/TestBinaryDocValuesUpdates.java       |  146 +-
 .../apache/lucene/index/TestCustomTermFreq.java |  468 +++
 .../test/org/apache/lucene/index/TestDoc.java   |   10 +-
 .../index/TestDocumentsWriterDeleteQueue.java   |   39 +-
 .../index/TestExitableDirectoryReader.java      |   16 +-
 .../lucene/index/TestFieldInvertState.java      |  139 +
 .../lucene/index/TestFilterLeafReader.java      |   17 +-
 .../test/org/apache/lucene/index/TestFlex.java  |   13 +-
 .../index/TestFlushByRamOrCountsPolicy.java     |   12 +-
 .../lucene/index/TestForceMergeForever.java     |    7 +-
 .../lucene/index/TestIndexReaderClose.java      |    8 +-
 .../apache/lucene/index/TestIndexWriter.java    |   65 +-
 .../lucene/index/TestIndexWriterConfig.java     |    7 +-
 .../lucene/index/TestIndexWriterDelete.java     |  163 +-
 .../lucene/index/TestIndexWriterExceptions.java |  253 --
 .../lucene/index/TestIndexWriterReader.java     |    7 +-
 .../lucene/index/TestIndexWriterUnicode.java    |    2 +-
 .../org/apache/lucene/index/TestManyFields.java |    2 +-
 .../lucene/index/TestNRTReaderWithThreads.java  |    8 +-
 .../index/TestNumericDocValuesUpdates.java      |  314 +-
 .../lucene/index/TestParallelTermEnum.java      |   20 +-
 .../org/apache/lucene/index/TestPayloads.java   |    4 +-
 .../lucene/index/TestPerSegmentDeletes.java     |   11 +-
 .../lucene/index/TestPostingsOffsets.java       |    2 +-
 .../lucene/index/TestPrefixCodedTerms.java      |   76 -
 .../lucene/index/TestSegmentTermDocs.java       |    2 +-
 .../lucene/index/TestSegmentTermEnum.java       |   10 +-
 .../apache/lucene/index/TestStressAdvance.java  |   11 +-
 .../org/apache/lucene/index/TestTermsEnum.java  |   23 +-
 .../lucene/search/TermInSetQueryTest.java       |   24 +-
 .../lucene/search/TestAutomatonQuery.java       |    2 +-
 .../search/TestAutomatonQueryUnicode.java       |    2 +-
 .../org/apache/lucene/search/TestBooleanOr.java |    2 +-
 .../TestControlledRealTimeReopenThread.java     |    4 +-
 .../lucene/search/TestDisjunctionMaxQuery.java  |   15 +
 .../lucene/search/TestDoubleValuesSource.java   |   16 +-
 .../apache/lucene/search/TestLRUQueryCache.java |    2 +-
 .../lucene/search/TestMultiPhraseQuery.java     |    2 +-
 .../lucene/search/TestPhrasePrefixQuery.java    |    2 +-
 .../apache/lucene/search/TestRegexpQuery.java   |    2 +-
 .../search/TestSameScoresWithThreads.java       |    2 +-
 .../org/apache/lucene/search/TestTermQuery.java |   43 +-
 .../lucene/search/TestTermRangeQuery.java       |    4 +-
 .../apache/lucene/search/spans/TestSpans.java   |    2 +-
 .../apache/lucene/util/TestQueryBuilder.java    |   28 +-
 .../org/apache/lucene/demo/SearchFiles.java     |    2 +-
 .../facet/range/TestRangeFacetCounts.java       |   75 +-
 .../lucene/search/grouping/GroupDocs.java       |    4 +-
 .../search/highlight/TermVectorLeafReader.java  |    8 +-
 .../lucene/search/highlight/TokenGroup.java     |   15 +-
 .../highlight/WeightedSpanTermExtractor.java    |   25 +-
 .../uhighlight/MemoryIndexOffsetStrategy.java   |    3 +-
 .../uhighlight/MultiTermHighlighting.java       |  124 +-
 .../lucene/search/uhighlight/PhraseHelper.java  |   29 +-
 .../TermVectorFilteredLeafReader.java           |   22 +-
 .../uhighlight/TestSplittingBreakIterator.java  |    1 -
 .../uhighlight/TestUnifiedHighlighter.java      |    3 -
 .../uhighlight/TestUnifiedHighlighterMTQ.java   |   69 +-
 .../TestUnifiedHighlighterRanking.java          |    3 -
 .../TestUnifiedHighlighterReanalysis.java       |    2 -
 .../TestUnifiedHighlighterStrictPhrases.java    |    2 -
 .../TestUnifiedHighlighterTermVec.java          |    2 -
 .../TestUnifiedHighlighterExtensibility.java    |   26 +-
 lucene/ivy-versions.properties                  |    2 +-
 .../apache/lucene/search/join/TestJoinUtil.java |   21 +-
 .../apache/lucene/index/memory/MemoryIndex.java |   43 +-
 .../lucene/index/memory/TestMemoryIndex.java    |   26 +-
 .../memory/TestMemoryIndexAgainstRAMDir.java    |    5 +-
 .../org/apache/lucene/misc/IndexMergeTool.java  |   11 +-
 .../apache/lucene/queries/CommonTermsQuery.java |    4 +-
 .../queries/function/FunctionScoreQuery.java    |    9 -
 .../lucene/queries/function/ValueSource.java    |  260 +-
 .../function/valuesource/TFValueSource.java     |    6 +-
 .../valuesource/TermFreqValueSource.java        |    6 +-
 .../function/TestFunctionScoreExplanations.java |    8 +-
 .../function/TestFunctionScoreQuery.java        |   91 +-
 .../queryparser/classic/FastCharStream.java     |    2 +-
 .../standard/parser/FastCharStream.java         |    2 +-
 .../surround/parser/FastCharStream.java         |    2 +-
 .../classic/TestMultiFieldQueryParser.java      |    2 +-
 .../queryparser/classic/TestQueryParser.java    |   91 +-
 .../lucene/queryparser/xml/TestCoreParser.java  |    2 +-
 .../xml/TestQueryTemplateManager.java           |    2 +-
 .../replicator/nrt/SimpleReplicaNode.java       |    4 +-
 .../idversion/IDVersionPostingsWriter.java      |    4 +-
 .../idversion/VersionBlockTreeTermsWriter.java  |    4 +-
 .../idversion/TestIDVersionPostingsFormat.java  |    4 +-
 lucene/spatial-extras/build.xml                 |    8 +-
 .../org/apache/lucene/spatial/ShapeValues.java  |   41 +
 .../lucene/spatial/ShapeValuesSource.java       |   34 +
 .../apache/lucene/spatial/SpatialStrategy.java  |   19 +-
 .../bbox/BBoxOverlapRatioValueSource.java       |    7 +-
 .../spatial/bbox/BBoxSimilarityValueSource.java |   79 +-
 .../lucene/spatial/bbox/BBoxStrategy.java       |   13 +-
 .../lucene/spatial/bbox/BBoxValueSource.java    |   74 +-
 .../composite/CompositeSpatialStrategy.java     |   14 +-
 .../spatial/composite/CompositeVerifyQuery.java |   32 +-
 .../composite/IntersectsRPTVerifyQuery.java     |   21 +-
 .../prefix/NumberRangePrefixTreeStrategy.java   |    4 +-
 .../spatial/prefix/PrefixTreeStrategy.java      |   21 +-
 .../prefix/RecursivePrefixTreeStrategy.java     |    1 +
 .../prefix/tree/PackedQuadPrefixTree.java       |   30 +-
 .../serialized/SerializedDVStrategy.java        |  110 +-
 .../spatial/util/CachingDoubleValueSource.java  |   61 +-
 .../util/DistanceToShapeValueSource.java        |   68 +-
 .../util/ReciprocalDoubleValuesSource.java      |   96 +
 .../spatial/util/ShapeAreaValueSource.java      |   67 +-
 .../ShapeFieldCacheDistanceValueSource.java     |   59 +-
 .../spatial/util/ShapePredicateValueSource.java |  113 -
 .../spatial/util/ShapeValuesPredicate.java      |   99 +
 .../spatial/vector/DistanceValueSource.java     |   72 +-
 .../spatial/vector/PointVectorStrategy.java     |   95 +-
 .../lucene/spatial/DistanceStrategyTest.java    |    6 -
 .../apache/lucene/spatial/SpatialExample.java   |   14 +-
 .../apache/lucene/spatial/SpatialTestCase.java  |    4 +-
 .../apache/lucene/spatial/StrategyTestCase.java |   39 +-
 .../RandomSpatialOpFuzzyPrefixTreeTest.java     |   41 +-
 .../lucene/spatial/spatial4j/Geo3dRptTest.java  |    2 +-
 .../Geo3dShapeRectRelationTestCase.java         |    2 +-
 .../DocumentValueSourceDictionaryTest.java      |   15 +
 .../suggest/document/TestSuggestField.java      |    6 +-
 .../java/org/apache/lucene/analysis/Token.java  |  195 ++
 .../lucene/index/AssertingLeafReader.java       |    7 +-
 .../index/BaseDocValuesFormatTestCase.java      |   24 +
 .../index/BaseIndexFileFormatTestCase.java      |    4 +-
 .../index/BasePostingsFormatTestCase.java       |   15 +-
 .../lucene/index/FieldFilterLeafReader.java     |    9 +-
 .../ThreadedIndexingAndSearchingTestCase.java   |   21 +-
 .../org/apache/lucene/search/QueryUtils.java    |   26 +-
 .../org/apache/lucene/util/LuceneTestCase.java  |   15 +-
 lucene/tools/forbiddenApis/base.txt             |    4 +
 solr/.gitignore                                 |   30 +
 solr/CHANGES.txt                                |  293 +-
 solr/NOTICE.txt                                 |    4 +-
 solr/bin/solr                                   |   76 +-
 solr/bin/solr.cmd                               |   74 +-
 solr/bin/solr.in.cmd                            |    4 +
 solr/bin/solr.in.sh                             |    4 +
 .../collection1/conf/schema-icucollate-dv.xml   |    4 +-
 .../solr/collection1/conf/schema-icucollate.xml |    4 +-
 .../conf/schema-icucollateoptions.xml           |    4 +-
 .../collection1/conf/solrconfig-icucollate.xml  |    2 +-
 .../solr/schema/TestICUCollationField.java      |   28 +-
 .../schema/TestICUCollationFieldDocValues.java  |   28 +-
 .../schema/TestICUCollationFieldOptions.java    |   26 +-
 .../apache/solr/analytics/AnalyticsDriver.java  |   82 +
 .../solr/analytics/AnalyticsExpression.java     |   64 +
 .../analytics/AnalyticsGroupingManager.java     |  239 ++
 .../solr/analytics/AnalyticsRequestManager.java |  279 ++
 .../solr/analytics/AnalyticsRequestParser.java  |  549 +++
 .../solr/analytics/ExpressionFactory.java       |  821 +++++
 .../analytics/accumulator/BasicAccumulator.java |  173 -
 .../accumulator/FacetingAccumulator.java        |  730 ----
 .../analytics/accumulator/ValueAccumulator.java |   40 -
 .../facet/FacetValueAccumulator.java            |   35 -
 .../facet/FieldFacetAccumulator.java            |  153 -
 .../facet/QueryFacetAccumulator.java            |   72 -
 .../facet/RangeFacetAccumulator.java            |   49 -
 .../accumulator/facet/package-info.java         |   24 -
 .../analytics/accumulator/package-info.java     |   23 -
 .../analytics/expression/BaseExpression.java    |   88 -
 .../expression/DualDelegateExpression.java      |   99 -
 .../solr/analytics/expression/Expression.java   |   39 -
 .../analytics/expression/ExpressionFactory.java |  175 -
 .../expression/MultiDelegateExpression.java     |  131 -
 .../expression/SingleDelegateExpression.java    |   88 -
 .../solr/analytics/expression/package-info.java |   23 -
 .../analytics/facet/AbstractSolrQueryFacet.java |  104 +
 .../solr/analytics/facet/AnalyticsFacet.java    |  166 +
 .../apache/solr/analytics/facet/PivotFacet.java |  114 +
 .../apache/solr/analytics/facet/PivotNode.java  |  263 ++
 .../apache/solr/analytics/facet/QueryFacet.java |   64 +
 .../apache/solr/analytics/facet/RangeFacet.java |  119 +
 .../solr/analytics/facet/SortableFacet.java     |  178 +
 .../solr/analytics/facet/StreamingFacet.java    |   32 +
 .../apache/solr/analytics/facet/ValueFacet.java |   60 +
 .../facet/compare/ConstantComparator.java       |   30 +
 .../facet/compare/DelegatingComparator.java     |   62 +
 .../facet/compare/ExpressionComparator.java     |   46 +
 .../facet/compare/FacetResultsComparator.java   |   52 +
 .../facet/compare/FacetValueComparator.java     |   37 +
 .../analytics/facet/compare/package-info.java   |   23 +
 .../solr/analytics/facet/package-info.java      |   23 +
 .../function/ExpressionCalculator.java          |   71 +
 .../MergingReductionCollectionManager.java      |   46 +
 .../function/ReductionCollectionManager.java    |  320 ++
 .../analytics/function/ReductionFunction.java   |   37 +
 .../function/field/AnalyticsField.java          |   69 +
 .../analytics/function/field/BooleanField.java  |  111 +
 .../function/field/BooleanMultiField.java       |  101 +
 .../analytics/function/field/DateField.java     |  108 +
 .../function/field/DateMultiField.java          |   47 +
 .../function/field/DateMultiPointField.java     |   47 +
 .../analytics/function/field/DoubleField.java   |   97 +
 .../function/field/DoubleMultiField.java        |   85 +
 .../function/field/DoubleMultiPointField.java   |   81 +
 .../analytics/function/field/FloatField.java    |  108 +
 .../function/field/FloatMultiField.java         |   91 +
 .../function/field/FloatMultiPointField.java    |   87 +
 .../solr/analytics/function/field/IntField.java |  129 +
 .../analytics/function/field/IntMultiField.java |  100 +
 .../function/field/IntMultiPointField.java      |   96 +
 .../analytics/function/field/LongField.java     |  107 +
 .../function/field/LongMultiField.java          |   89 +
 .../function/field/LongMultiPointField.java     |   86 +
 .../analytics/function/field/StringField.java   |   85 +
 .../function/field/StringMultiField.java        |   66 +
 .../analytics/function/field/package-info.java  |   23 +
 .../function/mapping/AbsoluteValueFunction.java |   54 +
 .../analytics/function/mapping/AddFunction.java |   68 +
 .../function/mapping/BottomFunction.java        |  163 +
 .../function/mapping/CompareFunction.java       |  614 ++++
 .../function/mapping/ConcatFunction.java        |   78 +
 .../function/mapping/DateMathFunction.java      |  156 +
 .../function/mapping/DateParseFunction.java     |  210 ++
 .../function/mapping/DivideFunction.java        |   51 +
 .../function/mapping/FillMissingFunction.java   |  842 +++++
 .../function/mapping/FilterFunction.java        |  722 ++++
 .../analytics/function/mapping/IfFunction.java  |  892 +++++
 .../function/mapping/JoinFunction.java          |   57 +
 .../function/mapping/LambdaFunction.java        | 3220 ++++++++++++++++++
 .../analytics/function/mapping/LogFunction.java |   51 +
 .../function/mapping/LogicFunction.java         |   90 +
 .../function/mapping/MultFunction.java          |   68 +
 .../function/mapping/NegateFunction.java        |   58 +
 .../mapping/NumericConvertFunction.java         |  256 ++
 .../function/mapping/PowerFunction.java         |   51 +
 .../function/mapping/RemoveFunction.java        |  796 +++++
 .../function/mapping/ReplaceFunction.java       |  914 +++++
 .../function/mapping/StringCastFunction.java    |   42 +
 .../function/mapping/SubtractFunction.java      |   51 +
 .../analytics/function/mapping/TopFunction.java |  163 +
 .../function/mapping/package-info.java          |   23 +
 .../solr/analytics/function/package-info.java   |   23 +
 .../function/reduction/CountFunction.java       |   87 +
 .../function/reduction/DocCountFunction.java    |   87 +
 .../function/reduction/MaxFunction.java         |  298 ++
 .../function/reduction/MedianFunction.java      |  200 ++
 .../function/reduction/MinFunction.java         |  298 ++
 .../function/reduction/MissingFunction.java     |   76 +
 .../function/reduction/OrdinalFunction.java     |  386 +++
 .../function/reduction/PercentileFunction.java  |  337 ++
 .../function/reduction/SumFunction.java         |   92 +
 .../function/reduction/UniqueFunction.java      |  101 +
 .../function/reduction/data/CountCollector.java |  188 +
 .../function/reduction/data/MaxCollector.java   |  476 +++
 .../function/reduction/data/MinCollector.java   |  476 +++
 .../function/reduction/data/ReductionData.java  |   24 +
 .../reduction/data/ReductionDataCollector.java  |  183 +
 .../reduction/data/SortedListCollector.java     |  363 ++
 .../function/reduction/data/SumCollector.java   |  124 +
 .../reduction/data/UniqueCollector.java         |  241 ++
 .../function/reduction/data/package-info.java   |   24 +
 .../function/reduction/package-info.java        |   23 +
 .../org/apache/solr/analytics/package-info.java |   23 +
 .../request/AbstractFieldFacetRequest.java      |   42 -
 .../request/AnalyticsContentHandler.java        |  314 --
 .../analytics/request/AnalyticsRequest.java     |  114 -
 .../request/AnalyticsRequestFactory.java        |  308 --
 .../solr/analytics/request/AnalyticsStats.java  |  138 -
 .../analytics/request/ExpressionRequest.java    |   72 -
 .../solr/analytics/request/FacetRequest.java    |   26 -
 .../analytics/request/FieldFacetRequest.java    |  172 -
 .../analytics/request/QueryFacetRequest.java    |   74 -
 .../analytics/request/RangeFacetRequest.java    |  129 -
 .../solr/analytics/request/package-info.java    |   24 -
 .../AbstractDelegatingStatsCollector.java       |   74 -
 .../statistics/MedianStatsCollector.java        |   76 -
 .../statistics/MinMaxStatsCollector.java        |  114 -
 .../statistics/NumericStatsCollector.java       |   68 -
 .../statistics/PercentileStatsCollector.java    |   80 -
 .../analytics/statistics/StatsCollector.java    |   69 -
 .../StatsCollectorSupplierFactory.java          |  646 ----
 .../statistics/UniqueStatsCollector.java        |   53 -
 .../solr/analytics/statistics/package-info.java |   24 -
 .../stream/AnalyticsShardRequestManager.java    |  245 ++
 .../stream/AnalyticsShardResponseParser.java    |   89 +
 .../solr/analytics/stream/package-info.java     |   23 +
 .../reservation/BooleanArrayReservation.java    |   44 +
 .../reservation/BooleanCheckedReservation.java  |   42 +
 .../stream/reservation/BooleanReservation.java  |   42 +
 .../reservation/DoubleArrayReservation.java     |   44 +
 .../reservation/DoubleCheckedReservation.java   |   43 +
 .../stream/reservation/DoubleReservation.java   |   42 +
 .../reservation/FloatArrayReservation.java      |   44 +
 .../reservation/FloatCheckedReservation.java    |   43 +
 .../stream/reservation/FloatReservation.java    |   42 +
 .../stream/reservation/IntArrayReservation.java |   42 +
 .../reservation/IntCheckedReservation.java      |   43 +
 .../stream/reservation/IntReservation.java      |   42 +
 .../reservation/LongArrayReservation.java       |   45 +
 .../reservation/LongCheckedReservation.java     |   43 +
 .../stream/reservation/LongReservation.java     |   42 +
 .../ReductionCheckedDataReservation.java        |   35 +
 .../ReductionDataArrayReservation.java          |   36 +
 .../reservation/ReductionDataReservation.java   |   53 +
 .../reservation/StringArrayReservation.java     |   45 +
 .../reservation/StringCheckedReservation.java   |   44 +
 .../stream/reservation/StringReservation.java   |   43 +
 .../stream/reservation/package-info.java        |   24 +
 .../read/BooleanCheckedDataReader.java          |   33 +
 .../read/BooleanDataArrayReader.java            |   36 +
 .../reservation/read/BooleanDataReader.java     |   33 +
 .../read/DoubleCheckedDataReader.java           |   32 +
 .../reservation/read/DoubleDataArrayReader.java |   35 +
 .../reservation/read/DoubleDataReader.java      |   32 +
 .../read/FloatCheckedDataReader.java            |   33 +
 .../reservation/read/FloatDataArrayReader.java  |   36 +
 .../reservation/read/FloatDataReader.java       |   33 +
 .../reservation/read/IntCheckedDataReader.java  |   32 +
 .../reservation/read/IntDataArrayReader.java    |   34 +
 .../stream/reservation/read/IntDataReader.java  |   32 +
 .../reservation/read/LongCheckedDataReader.java |   32 +
 .../reservation/read/LongDataArrayReader.java   |   35 +
 .../stream/reservation/read/LongDataReader.java |   32 +
 .../read/ReductionCheckedDataReader.java        |   54 +
 .../read/ReductionDataArrayReader.java          |   54 +
 .../reservation/read/ReductionDataReader.java   |   40 +
 .../read/StringCheckedDataReader.java           |   32 +
 .../reservation/read/StringDataArrayReader.java |   35 +
 .../reservation/read/StringDataReader.java      |   34 +
 .../stream/reservation/read/package-info.java   |   24 +
 .../write/BooleanCheckedDataWriter.java         |   33 +
 .../write/BooleanDataArrayWriter.java           |   36 +
 .../reservation/write/BooleanDataWriter.java    |   33 +
 .../write/DoubleCheckedDataWriter.java          |   34 +
 .../write/DoubleDataArrayWriter.java            |   36 +
 .../reservation/write/DoubleDataWriter.java     |   33 +
 .../write/FloatCheckedDataWriter.java           |   35 +
 .../reservation/write/FloatDataArrayWriter.java |   37 +
 .../reservation/write/FloatDataWriter.java      |   34 +
 .../reservation/write/IntCheckedDataWriter.java |   34 +
 .../reservation/write/IntDataArrayWriter.java   |   35 +
 .../stream/reservation/write/IntDataWriter.java |   33 +
 .../write/LongCheckedDataWriter.java            |   34 +
 .../reservation/write/LongDataArrayWriter.java  |   36 +
 .../reservation/write/LongDataWriter.java       |   33 +
 .../write/ReductionCheckedDataWriter.java       |   60 +
 .../write/ReductionDataArrayWriter.java         |   53 +
 .../reservation/write/ReductionDataWriter.java  |   40 +
 .../write/StringCheckedDataWriter.java          |   34 +
 .../write/StringDataArrayWriter.java            |   36 +
 .../reservation/write/StringDataWriter.java     |   37 +
 .../stream/reservation/write/package-info.java  |   24 +
 .../solr/analytics/util/AnalyticsParams.java    |  113 -
 .../solr/analytics/util/AnalyticsParsers.java   |  171 -
 .../util/AnalyticsResponseHeadings.java         |   36 +
 .../analytics/util/FacetRangeGenerator.java     |  356 ++
 .../solr/analytics/util/MedianCalculator.java   |    4 +
 .../solr/analytics/util/OldAnalyticsParams.java |  177 +
 .../util/OldAnalyticsRequestConverter.java      |  177 +
 .../solr/analytics/util/OrdinalCalculator.java  |  173 +
 .../analytics/util/PercentileCalculator.java    |  176 -
 .../analytics/util/RangeEndpointCalculator.java |  354 --
 .../util/function/BooleanConsumer.java          |   59 +
 .../analytics/util/function/FloatConsumer.java  |   59 +
 .../analytics/util/function/FloatSupplier.java  |   41 +
 .../analytics/util/function/package-info.java   |   23 +
 .../solr/analytics/util/package-info.java       |    3 +-
 .../AbsoluteValueDoubleFunction.java            |   60 -
 .../util/valuesource/AddDoubleFunction.java     |   49 -
 .../util/valuesource/ConcatStringFunction.java  |   54 -
 .../util/valuesource/ConstDateSource.java       |  112 -
 .../util/valuesource/ConstDoubleSource.java     |  104 -
 .../util/valuesource/ConstStringSource.java     |   50 -
 .../util/valuesource/DateFieldSource.java       |  131 -
 .../util/valuesource/DateMathFunction.java      |   71 -
 .../util/valuesource/DivDoubleFunction.java     |   48 -
 .../util/valuesource/DualDoubleFunction.java    |   94 -
 .../util/valuesource/FilterFieldSource.java     |  154 -
 .../util/valuesource/LogDoubleFunction.java     |   43 -
 .../util/valuesource/MultiDateFunction.java     |  133 -
 .../util/valuesource/MultiDoubleFunction.java   |  119 -
 .../util/valuesource/MultiStringFunction.java   |  146 -
 .../valuesource/MultiplyDoubleFunction.java     |   49 -
 .../util/valuesource/NegateDoubleFunction.java  |   55 -
 .../util/valuesource/PowDoubleFunction.java     |   48 -
 .../util/valuesource/ReverseStringFunction.java |   45 -
 .../util/valuesource/SingleDoubleFunction.java  |   79 -
 .../util/valuesource/SingleStringFunction.java  |  117 -
 .../util/valuesource/package-info.java          |   24 -
 .../solr/analytics/value/AnalyticsValue.java    |   55 +
 .../analytics/value/AnalyticsValueStream.java   |  133 +
 .../solr/analytics/value/BooleanValue.java      |   85 +
 .../analytics/value/BooleanValueStream.java     |   55 +
 .../solr/analytics/value/ComparableValue.java   |   32 +
 .../apache/solr/analytics/value/DateValue.java  |  102 +
 .../solr/analytics/value/DateValueStream.java   |   62 +
 .../solr/analytics/value/DoubleValue.java       |   86 +
 .../solr/analytics/value/DoubleValueStream.java |   54 +
 .../apache/solr/analytics/value/FloatValue.java |   97 +
 .../solr/analytics/value/FloatValueStream.java  |   60 +
 .../apache/solr/analytics/value/IntValue.java   |  121 +
 .../solr/analytics/value/IntValueStream.java    |   71 +
 .../apache/solr/analytics/value/LongValue.java  |   97 +
 .../solr/analytics/value/LongValueStream.java   |   60 +
 .../solr/analytics/value/StringValue.java       |   71 +
 .../solr/analytics/value/StringValueStream.java |   49 +
 .../value/constant/ConstantBooleanValue.java    |   91 +
 .../value/constant/ConstantDateValue.java       |  103 +
 .../value/constant/ConstantDoubleValue.java     |   90 +
 .../value/constant/ConstantFloatValue.java      |   99 +
 .../value/constant/ConstantIntValue.java        |  118 +
 .../value/constant/ConstantLongValue.java       |  100 +
 .../value/constant/ConstantStringValue.java     |   79 +
 .../analytics/value/constant/ConstantValue.java |  128 +
 .../analytics/value/constant/package-info.java  |   23 +
 .../solr/analytics/value/package-info.java      |   23 +
 .../apache/solr/handler/AnalyticsHandler.java   |  147 +
 .../handler/component/AnalyticsComponent.java   |  119 +-
 .../java/org/apache/solr/handler/package.html   |   28 +
 .../response/AnalyticsShardResponseWriter.java  |   91 +
 .../java/org/apache/solr/response/package.html  |   28 +
 .../analytics/requestFiles/expressions.txt      |   70 -
 .../analytics/requestFiles/fieldFacetExtras.txt |   66 -
 .../analytics/requestFiles/fieldFacets.txt      |  132 -
 .../analytics/requestFiles/functions.txt        |   62 -
 .../analytics/requestFiles/noFacets.txt         |   74 -
 .../analytics/requestFiles/queryFacets.txt      |   45 -
 .../analytics/requestFiles/rangeFacets.txt      |  170 -
 .../analytics/requestXMLFiles/expressions.xml   |  285 --
 .../requestXMLFiles/fieldFacetExtras.xml        |  101 -
 .../analytics/requestXMLFiles/fieldFacets.xml   |  496 ---
 .../analytics/requestXMLFiles/functions.xml     |  246 --
 .../analytics/requestXMLFiles/noFacets.xml      |  310 --
 .../analytics/requestXMLFiles/queryFacets.xml   |   94 -
 .../analytics/requestXMLFiles/rangeFacets.xml   |  319 --
 .../test-files/solr/analytics/expressions.txt   |   65 +
 .../test-files/solr/analytics/facetSorting.txt  |    4 +
 .../solr/analytics/fieldFacetExtras.txt         |   66 +
 .../test-files/solr/analytics/fieldFacets.txt   |  132 +
 .../src/test-files/solr/analytics/functions.txt |   57 +
 .../src/test-files/solr/analytics/noFacets.txt  |   74 +
 .../test-files/solr/analytics/queryFacets.txt   |   27 +
 .../test-files/solr/analytics/rangeFacets.txt   |  161 +
 .../solr/collection1/conf/schema-analytics.xml  |   17 +-
 .../collection1/conf/solrconfig-analytics.xml   |   42 +
 .../solr/collection1/conf/solrconfig-basic.xml  |   40 -
 .../configsets/cloud-analytics/conf/schema.xml  |   63 +
 .../cloud-analytics/conf/solrconfig.xml         |   59 +
 .../AbstractAnalyticsStatsCloudTest.java        |  187 +
 .../analytics/AbstractAnalyticsStatsTest.java   |   15 +-
 .../apache/solr/analytics/NoFacetCloudTest.java |  557 +++
 .../org/apache/solr/analytics/NoFacetTest.java  |   47 +-
 .../analytics/expression/ExpressionTest.java    |   70 +-
 .../solr/analytics/expression/FunctionTest.java |  221 ++
 .../facet/AbstractAnalyticsFacetCloudTest.java  |  284 ++
 .../facet/AbstractAnalyticsFacetTest.java       |   38 +-
 .../solr/analytics/facet/FacetSortingTest.java  |   53 +
 .../analytics/facet/FieldFacetCloudTest.java    | 1214 +++++++
 .../facet/FieldFacetExtrasCloudTest.java        |  253 ++
 .../analytics/facet/FieldFacetExtrasTest.java   |    6 +-
 .../solr/analytics/facet/FieldFacetTest.java    |   63 +-
 .../analytics/facet/QueryFacetCloudTest.java    |  159 +
 .../solr/analytics/facet/QueryFacetTest.java    |   10 +-
 .../analytics/facet/RangeFacetCloudTest.java    |  588 ++++
 .../solr/analytics/facet/RangeFacetTest.java    |   43 +-
 .../util/valuesource/FunctionTest.java          |  233 --
 .../carrot2/CarrotClusteringEngine.java         |   62 +-
 .../clustering/solr/collection1/conf/schema.xml |   18 +-
 .../solr/collection1/conf/solrconfig.xml        |   25 +-
 .../clustering/ClusteringComponentTest.java     |    2 +-
 .../handler/dataimport/MailEntityProcessor.java |   31 +-
 .../conf/dataimport-schema-no-unique-key.xml    |   18 +-
 .../collection1/conf/dataimport-solrconfig.xml  |   43 +-
 .../solr/handler/dataimport/DebugInfo.java      |   32 +-
 .../handler/dataimport/VariableResolver.java    |    4 +-
 .../conf/contentstream-solrconfig.xml           |   47 +-
 .../conf/dataimport-nodatasource-solrconfig.xml |   45 +-
 .../solr/collection1/conf/dataimport-schema.xml |   10 +-
 .../conf/dataimport-solr_id-schema.xml          |   18 +-
 .../collection1/conf/dataimport-solrconfig.xml  |   45 +-
 .../AbstractDataImportHandlerTestCase.java      |    4 +-
 .../dataimport/TestHierarchicalDocBuilder.java  |   31 +-
 .../handler/extraction/SolrContentHandler.java  |    4 +-
 .../extraction/solr/collection1/conf/schema.xml |   18 +-
 .../solr/collection1/conf/solrconfig.xml        |   40 +-
 .../extraction/TestXLSXResponseWriter.java      |    2 +-
 .../conf/solrconfig-languageidentifier.xml      |    7 +-
 .../java/org/apache/solr/ltr/LTRRescorer.java   |    2 +-
 .../ltr/model/MultipleAdditiveTreesModel.java   |   16 +-
 .../test-files/solr/collection1/conf/schema.xml |   10 +-
 .../org/apache/solr/ltr/TestLTROnSolrCloud.java |   14 +-
 .../apache/solr/ltr/TestLTRScoringQuery.java    |   20 +-
 .../solr/ltr/TestSelectiveWeightCreation.java   |   14 +-
 .../apache/solr/ltr/model/TestLinearModel.java  |   10 +
 .../model/TestMultipleAdditiveTreesModel.java   |   17 +-
 .../uima/solr/collection1/conf/schema.xml       |   20 +-
 .../uima/solr/collection1/conf/solrconfig.xml   |   29 +-
 .../test-files/uima/uima-tokenizers-schema.xml  |   20 +-
 .../uima/uima-tokenizers-solrconfig.xml         |   19 +-
 .../java/org/apache/solr/response/PageTool.java |    5 +-
 solr/core/src/java/org/apache/solr/api/Api.java |    3 +-
 .../src/java/org/apache/solr/api/ApiBag.java    |   32 +-
 .../java/org/apache/solr/api/SpecProvider.java  |   25 -
 .../java/org/apache/solr/api/V2HttpCall.java    |   60 +-
 .../org/apache/solr/cloud/AddReplicaCmd.java    |    3 +-
 .../src/java/org/apache/solr/cloud/Assign.java  |   66 +-
 .../apache/solr/cloud/CreateCollectionCmd.java  |   67 +-
 .../org/apache/solr/cloud/CreateShardCmd.java   |   74 +-
 .../java/org/apache/solr/cloud/Overseer.java    |    4 +-
 .../cloud/OverseerCollectionMessageHandler.java |  108 +-
 .../org/apache/solr/cloud/RecoveryStrategy.java |    4 +-
 .../org/apache/solr/cloud/ReplaceNodeCmd.java   |   96 +-
 .../apache/solr/cloud/ReplicateFromLeader.java  |    6 +-
 .../java/org/apache/solr/cloud/RestoreCmd.java  |    2 +-
 .../org/apache/solr/cloud/SplitShardCmd.java    |    2 +-
 .../org/apache/solr/cloud/ZkController.java     |   57 +-
 .../cloud/autoscaling/AutoScalingHandler.java   |  324 ++
 .../solr/cloud/autoscaling/package-info.java    |   21 +
 .../apache/solr/cloud/rule/ReplicaAssigner.java |    2 +-
 .../solr/cloud/rule/ServerSnitchContext.java    |   25 +-
 .../solr/core/CachingDirectoryFactory.java      |   10 +
 .../org/apache/solr/core/CoreContainer.java     |   91 +-
 .../org/apache/solr/core/DirectoryFactory.java  |   24 +-
 .../java/org/apache/solr/core/PluginBag.java    |   32 +-
 .../java/org/apache/solr/core/SolrConfig.java   |   20 +-
 .../src/java/org/apache/solr/core/SolrCore.java |   18 +-
 .../java/org/apache/solr/core/SolrCores.java    |   91 +-
 .../apache/solr/core/SolrResourceLoader.java    |   13 +-
 .../apache/solr/handler/AnalyzeEvaluator.java   |   14 +-
 .../org/apache/solr/handler/BlobHandler.java    |   19 +-
 .../apache/solr/handler/CdcrRequestHandler.java |    6 +-
 .../org/apache/solr/handler/ClassifyStream.java |    3 +-
 .../org/apache/solr/handler/ExportWriter.java   |  105 +-
 .../org/apache/solr/handler/IndexFetcher.java   |    2 +-
 .../solr/handler/MoreLikeThisHandler.java       |    9 +-
 .../apache/solr/handler/ReplicationHandler.java |    2 +-
 .../apache/solr/handler/RequestHandlerBase.java |    1 -
 .../solr/handler/RequestHandlerUtils.java       |   13 +
 .../org/apache/solr/handler/SchemaHandler.java  |    2 +-
 .../apache/solr/handler/SolrConfigHandler.java  |   11 +-
 .../solr/handler/StandardRequestHandler.java    |   19 +-
 .../org/apache/solr/handler/StreamHandler.java  |  477 ++-
 .../solr/handler/UpdateRequestHandlerApi.java   |    4 +-
 .../handler/admin/BaseHandlerApiSupport.java    |    3 +-
 .../solr/handler/admin/CollectionsHandler.java  |    8 +-
 .../solr/handler/admin/ConfigSetsHandler.java   |    4 +
 .../handler/admin/ConfigSetsHandlerApi.java     |    2 +
 .../apache/solr/handler/admin/InfoHandler.java  |    2 +-
 .../solr/handler/admin/LukeRequestHandler.java  |   10 +-
 .../solr/handler/admin/SecurityConfHandler.java |   16 +-
 .../solr/handler/component/ExpandComponent.java |    2 +
 .../handler/component/HttpShardHandler.java     |   76 +-
 .../component/QueryElevationComponent.java      |    5 +-
 .../solr/handler/component/ResponseBuilder.java |    3 +
 .../handler/component/SpellCheckComponent.java  |   12 +-
 .../solr/handler/component/TermsComponent.java  |   38 +-
 .../solr/highlight/DefaultSolrHighlighter.java  |    2 +-
 .../solr/highlight/UnifiedSolrHighlighter.java  |    7 +
 .../solr/index/SlowCompositeReaderWrapper.java  |    4 +-
 .../org/apache/solr/legacy/BBoxStrategy.java    |   13 +-
 .../org/apache/solr/legacy/BBoxValueSource.java |   82 +-
 .../apache/solr/legacy/DistanceValueSource.java |   81 +-
 .../apache/solr/legacy/PointVectorStrategy.java |   17 +-
 .../apache/solr/metrics/SolrMetricReporter.java |   37 +-
 .../metrics/reporters/SolrGangliaReporter.java  |   23 +-
 .../metrics/reporters/SolrGraphiteReporter.java |   37 +-
 .../solr/metrics/reporters/SolrJmxReporter.java |   21 +-
 .../metrics/reporters/SolrSlf4jReporter.java    |   24 +-
 .../reporters/solr/SolrClusterReporter.java     |   17 +-
 .../reporters/solr/SolrShardReporter.java       |   19 +-
 .../org/apache/solr/parser/FastCharStream.java  |    2 +-
 .../apache/solr/parser/SolrQueryParserBase.java |    5 +-
 .../org/apache/solr/request/SimpleFacets.java   |    4 +-
 .../solr/request/SolrQueryRequestBase.java      |   21 +-
 .../solr/response/BinaryResponseWriter.java     |   12 +-
 .../solr/response/TextResponseWriter.java       |   13 +-
 .../transform/GeoTransformerFactory.java        |   33 +-
 .../solr/schema/AbstractSpatialFieldType.java   |   10 +-
 .../java/org/apache/solr/schema/BBoxField.java  |   15 +-
 .../org/apache/solr/schema/CurrencyField.java   |  999 +-----
 .../apache/solr/schema/CurrencyFieldType.java   |  829 +++++
 .../apache/solr/schema/DoublePointField.java    |   10 +-
 .../apache/solr/schema/ExternalFileField.java   |   14 -
 .../java/org/apache/solr/schema/FieldType.java  |    4 +-
 .../solr/schema/FileExchangeRateProvider.java   |  252 ++
 .../org/apache/solr/schema/FloatPointField.java |   10 +-
 .../org/apache/solr/schema/IndexSchema.java     |   37 +-
 .../org/apache/solr/schema/IntPointField.java   |   10 +-
 .../solr/schema/LatLonPointSpatialField.java    |   46 +-
 .../org/apache/solr/schema/LongPointField.java  |   10 +-
 .../apache/solr/schema/NumericFieldType.java    |   88 +-
 .../schema/OpenExchangeRatesOrgProvider.java    |    2 +-
 .../java/org/apache/solr/schema/PointField.java |   35 +-
 .../schema/RptWithGeometrySpatialField.java     |   60 +-
 .../java/org/apache/solr/schema/TrieField.java  |   60 +-
 .../apache/solr/schema/ZkIndexSchemaReader.java |  105 +-
 .../java/org/apache/solr/search/CursorMark.java |   21 +-
 .../org/apache/solr/search/DisMaxQParser.java   |    4 +-
 .../java/org/apache/solr/search/DocList.java    |    2 +-
 .../java/org/apache/solr/search/DocSetUtil.java |    4 +-
 .../java/org/apache/solr/search/DocSlice.java   |    6 +-
 .../solr/search/ExtendedDismaxQParser.java      |   17 +-
 .../src/java/org/apache/solr/search/Filter.java |    2 +-
 .../solr/search/FloatPayloadValueSource.java    |    4 +-
 .../solr/search/GraphTermsQParserPlugin.java    |   16 +-
 .../java/org/apache/solr/search/Grouping.java   |    2 +-
 .../solr/search/IGainTermsQParserPlugin.java    |    5 +-
 .../apache/solr/search/JoinQParserPlugin.java   |   12 +-
 .../apache/solr/search/LuceneQParserPlugin.java |    8 +-
 .../solr/search/OldLuceneQParserPlugin.java     |    3 +
 .../java/org/apache/solr/search/QParser.java    |   10 -
 .../org/apache/solr/search/QParserPlugin.java   |    1 -
 .../org/apache/solr/search/QueryParsing.java    |   26 -
 .../java/org/apache/solr/search/QueryUtils.java |   11 +
 .../search/SignificantTermsQParserPlugin.java   |    9 +-
 .../TextLogisticRegressionQParserPlugin.java    |    5 +-
 .../apache/solr/search/ValueSourceParser.java   |   17 +-
 .../apache/solr/search/facet/FacetField.java    |   13 +-
 .../solr/search/facet/FacetFieldProcessor.java  |    1 +
 .../FacetFieldProcessorByEnumTermsStream.java   |    4 +-
 .../facet/FacetFieldProcessorByHashDV.java      |   33 +-
 .../apache/solr/search/facet/FacetModule.java   |    6 +-
 .../apache/solr/search/facet/FacetRange.java    |  149 +-
 .../org/apache/solr/search/facet/FieldUtil.java |    6 +
 .../org/apache/solr/search/facet/HLLAgg.java    |   83 +-
 .../org/apache/solr/search/facet/UniqueAgg.java |   76 +-
 .../search/function/ConcatStringFunction.java   |   53 +
 .../search/function/MultiStringFunction.java    |  146 +
 .../distance/GeoDistValueSourceParser.java      |    8 +-
 .../TopGroupsResultTransformer.java             |   10 +-
 .../apache/solr/search/mlt/CloudMLTQParser.java |    3 +-
 .../solr/search/mlt/SimpleMLTQParser.java       |    3 +-
 .../search/stats/ExactSharedStatsCache.java     |   12 +-
 .../solr/search/stats/ExactStatsCache.java      |   19 +-
 .../apache/solr/security/BasicAuthPlugin.java   |    2 +-
 .../solr/security/PermissionNameProvider.java   |    2 +
 .../security/RuleBasedAuthorizationPlugin.java  |    6 +-
 .../security/Sha256AuthenticationProvider.java  |    4 +-
 .../org/apache/solr/servlet/BaseSolrFilter.java |    3 +
 .../apache/solr/servlet/BaseSolrServlet.java    |    3 +
 .../org/apache/solr/servlet/HttpSolrCall.java   |   26 +-
 .../apache/solr/servlet/SolrDispatchFilter.java |    8 +-
 .../apache/solr/servlet/SolrRequestParsers.java |   13 +-
 .../spelling/AbstractLuceneSpellChecker.java    |   12 +-
 .../spelling/ConjunctionSolrSpellChecker.java   |    1 -
 .../solr/spelling/DirectSolrSpellChecker.java   |    1 -
 .../solr/spelling/PossibilityIterator.java      |    2 -
 .../apache/solr/spelling/QueryConverter.java    |    7 +-
 .../org/apache/solr/spelling/ResultEntry.java   |    2 -
 .../apache/solr/spelling/SolrSpellChecker.java  |   13 +-
 .../solr/spelling/SpellCheckCollation.java      |    6 +-
 .../solr/spelling/SpellCheckCollator.java       |   11 +-
 .../solr/spelling/SpellCheckCorrection.java     |    1 -
 .../apache/solr/spelling/SpellingOptions.java   |    5 +-
 .../solr/spelling/SpellingQueryConverter.java   |    1 -
 .../apache/solr/spelling/SpellingResult.java    |    5 +-
 .../solr/spelling/SuggestQueryConverter.java    |    2 -
 .../java/org/apache/solr/spelling/Token.java    |  175 +
 .../spelling/WordBreakSolrSpellChecker.java     |    1 -
 .../apache/solr/spelling/suggest/Suggester.java |    2 +-
 .../apache/solr/uninverting/DocTermOrds.java    |    4 +-
 .../apache/solr/update/AddUpdateCommand.java    |    8 +-
 .../solr/update/DirectUpdateHandler2.java       |    3 +-
 .../org/apache/solr/update/DocumentBuilder.java |    8 +-
 .../org/apache/solr/update/SolrIndexConfig.java |  146 +-
 .../apache/solr/update/SolrIndexSplitter.java   |    4 +-
 .../solr/update/StreamingSolrClients.java       |   65 +-
 .../java/org/apache/solr/update/UpdateLog.java  |   22 +-
 .../org/apache/solr/update/VersionInfo.java     |   76 +-
 .../AddSchemaFieldsUpdateProcessorFactory.java  |   12 +-
 .../processor/AtomicUpdateProcessorFactory.java |    3 +-
 .../processor/SimpleUpdateProcessorFactory.java |   18 +-
 .../TemplateUpdateProcessorFactory.java         |   23 +-
 .../processor/UpdateRequestProcessorChain.java  |   19 +-
 .../org/apache/solr/util/Java9InitHack.java     |   78 +
 .../apache/solr/util/JsonSchemaValidator.java   |  277 --
 .../src/java/org/apache/solr/util/PathTrie.java |  195 --
 .../src/java/org/apache/solr/util/SolrCLI.java  |   34 +-
 .../org/apache/solr/util/SolrPluginUtils.java   |   75 +-
 .../resources/SystemCollectionSolrConfig.xml    |    2 +-
 .../src/resources/apispec/cluster.Commands.json |   74 -
 .../src/resources/apispec/cluster.aliases.json  |   12 -
 .../apispec/cluster.commandstatus.delete.json   |   10 -
 .../apispec/cluster.commandstatus.json          |   20 -
 .../apispec/cluster.configs.Commands.json       |   34 -
 .../apispec/cluster.configs.delete.json         |   12 -
 .../src/resources/apispec/cluster.configs.json  |   12 -
 solr/core/src/resources/apispec/cluster.json    |   14 -
 .../src/resources/apispec/cluster.nodes.json    |   12 -
 .../cluster.security.BasicAuth.Commands.json    |   23 -
 ...cluster.security.RuleBasedAuthorization.json |  129 -
 ...luster.security.authentication.Commands.json |   12 -
 .../cluster.security.authentication.json        |   12 -
 ...cluster.security.authorization.Commands.json |   13 -
 .../apispec/cluster.security.authorization.json |   13 -
 .../resources/apispec/collections.Commands.json |  206 --
 .../collections.collection.Commands.json        |  137 -
 .../collections.collection.Commands.modify.json |   36 -
 .../collections.collection.Commands.reload.json |   11 -
 .../apispec/collections.collection.delete.json  |   13 -
 .../apispec/collections.collection.json         |   19 -
 .../collections.collection.shards.Commands.json |  109 -
 ...ctions.collection.shards.shard.Commands.json |   24 -
 ...lections.collection.shards.shard.delete.json |   27 -
 ....collection.shards.shard.replica.delete.json |   39 -
 .../core/src/resources/apispec/collections.json |   13 -
 .../src/resources/apispec/core.RealtimeGet.json |   26 -
 .../apispec/core.SchemaEdit.addCopyField.json   |   27 -
 .../apispec/core.SchemaEdit.addField.json       |   98 -
 .../core.SchemaEdit.addFieldType.analyzers.json |   51 -
 .../apispec/core.SchemaEdit.addFieldType.json   |   53 -
 .../core.SchemaEdit.deleteCopyField.json        |   19 -
 .../core.SchemaEdit.deleteDynamicField.json     |   12 -
 .../apispec/core.SchemaEdit.deleteField.json    |   12 -
 .../core.SchemaEdit.deleteFieldType.json        |   14 -
 .../src/resources/apispec/core.SchemaEdit.json  |   47 -
 .../apispec/core.SchemaRead.copyFields.json     |   26 -
 ...ore.SchemaRead.dynamicFields_fieldTypes.json |   20 -
 .../apispec/core.SchemaRead.fields.json         |   34 -
 .../src/resources/apispec/core.SchemaRead.json  |   17 -
 .../core/src/resources/apispec/core.Update.json |   17 -
 ...g.Commands.addRequestHandler.properties.json |   25 -
 .../apispec/core.config.Commands.generic.json   |   19 -
 .../resources/apispec/core.config.Commands.json |  215 --
 .../core.config.Commands.runtimeLib.json        |   23 -
 .../apispec/core.config.Params.Commands.json    |   31 -
 .../resources/apispec/core.config.Params.json   |   13 -
 .../core/src/resources/apispec/core.config.json |   18 -
 .../src/resources/apispec/core.system.blob.json |   20 -
 .../apispec/core.system.blob.upload.json        |   12 -
 .../src/resources/apispec/cores.Commands.json   |   85 -
 .../src/resources/apispec/cores.Status.json     |   20 -
 .../resources/apispec/cores.core.Commands.json  |  136 -
 .../apispec/cores.core.Commands.split.json      |   34 -
 solr/core/src/resources/apispec/emptySpec.json  |   11 -
 .../src/resources/apispec/node.Commands.json    |   24 -
 solr/core/src/resources/apispec/node.Info.json  |   11 -
 .../core/src/resources/apispec/node.invoke.json |   16 -
 .../solr/analysisconfs/analysis-err-schema.xml  |    4 +-
 .../collection1/conf/bad-error-solrconfig.xml   |    2 +-
 .../solr/collection1/conf/bad-mp-solrconfig.xml |   36 -
 .../collection1/conf/bad-mpf-solrconfig.xml     |    2 +-
 .../bad-schema-currency-ft-amount-suffix.xml    |   34 +
 .../conf/bad-schema-currency-ft-code-suffix.xml |   33 +
 .../conf/bad-schema-currency-ft-oer-norates.xml |    2 +-
 ...ma-currencyfieldtype-bogus-amount-suffix.xml |   34 +
 ...hema-currencyfieldtype-bogus-code-suffix.xml |   35 +
 ...ma-currencyfieldtype-dynamic-multivalued.xml |   36 +
 ...a-currencyfieldtype-ft-bogus-code-in-xml.xml |   41 +
 ...-currencyfieldtype-ft-bogus-default-code.xml |   41 +
 ...-schema-currencyfieldtype-ft-multivalued.xml |   36 +
 ...-schema-currencyfieldtype-ft-oer-norates.xml |   40 +
 ...-currencyfieldtype-missing-amount-suffix.xml |   34 +
 ...ma-currencyfieldtype-missing-code-suffix.xml |   35 +
 ...bad-schema-currencyfieldtype-multivalued.xml |   36 +
 ...schema-currencyfieldtype-wrong-amount-ft.xml |   36 +
 ...d-schema-currencyfieldtype-wrong-code-ft.xml |   35 +
 .../conf/bad-schema-external-filefield.xml      |   25 -
 ...-schema-uniquekey-diff-type-dynamic-root.xml |   36 +
 .../bad-schema-uniquekey-diff-type-root.xml     |   35 +
 .../conf/bad-schema-uniquekey-uses-points.xml   |   28 +
 ...chema-add-schema-fields-update-processor.xml |   22 +
 .../collection1/conf/schema-binaryfield.xml     |    2 +-
 .../conf/schema-blockjoinfacetcomponent.xml     |    4 +-
 .../solr/collection1/conf/schema-bm25.xml       |    4 +-
 .../collection1/conf/schema-charfilters.xml     |    4 +-
 .../solr/collection1/conf/schema-collate-dv.xml |    4 +-
 .../solr/collection1/conf/schema-collate.xml    |    4 +-
 .../collection1/conf/schema-copyfield-test.xml  |    2 +-
 .../collection1/conf/schema-custom-field.xml    |    6 +-
 .../collection1/conf/schema-customfield.xml     |    3 +-
 .../solr/collection1/conf/schema-dfi.xml        |    4 +-
 .../solr/collection1/conf/schema-dfr.xml        |    4 +-
 .../conf/schema-distrib-interval-faceting.xml   |   32 +-
 .../conf/schema-distributed-missing-sort.xml    |   34 +-
 .../solr/collection1/conf/schema-docValues.xml  |    5 +-
 .../conf/schema-docValuesFaceting.xml           |   35 +-
 .../conf/schema-field-sort-values.xml           |    6 +-
 .../solr/collection1/conf/schema-hash.xml       |    2 +-
 .../solr/collection1/conf/schema-ib.xml         |    4 +-
 .../collection1/conf/schema-inplace-updates.xml |    6 +-
 .../collection1/conf/schema-lmdirichlet.xml     |    4 +-
 .../collection1/conf/schema-lmjelinekmercer.xml |    4 +-
 .../conf/schema-not-required-unique-key.xml     |    2 +-
 .../collection1/conf/schema-phrasesuggest.xml   |    4 +-
 .../solr/collection1/conf/schema-point.xml      |   64 +-
 .../conf/schema-postingshighlight.xml           |    4 +-
 .../collection1/conf/schema-replication1.xml    |    2 +-
 .../collection1/conf/schema-replication2.xml    |    2 +-
 .../collection1/conf/schema-required-fields.xml |    2 +-
 .../solr/collection1/conf/schema-rest.xml       |   33 +-
 .../solr/collection1/conf/schema-reversed.xml   |    2 +-
 .../conf/schema-sim-default-override.xml        |    4 +-
 .../solr/collection1/conf/schema-sim.xml        |    4 +-
 .../collection1/conf/schema-simpleqpplugin.xml  |    4 +-
 .../collection1/conf/schema-sortingresponse.xml |   61 +-
 .../solr/collection1/conf/schema-sorts.xml      |  117 +-
 .../solr/collection1/conf/schema-spatial.xml    |   10 +
 .../solr/collection1/conf/schema-sql.xml        |    2 +-
 .../solr/collection1/conf/schema-sweetspot.xml  |    4 +-
 .../conf/schema-synonym-tokenizer.xml           |    6 +-
 .../solr/collection1/conf/schema-tfidf.xml      |    4 +-
 .../collection1/conf/schema-tokenizer-test.xml  |   25 +-
 .../solr/collection1/conf/schema-trie.xml       |    6 +-
 .../conf/schema-unifiedhighlight.xml            |    4 +-
 .../solr/collection1/conf/schema-version-dv.xml |    3 +-
 .../collection1/conf/schema-version-indexed.xml |    3 +-
 .../test-files/solr/collection1/conf/schema.xml |  135 +-
 .../solr/collection1/conf/schema11.xml          |   86 +-
 .../solr/collection1/conf/schema12.xml          |   63 +-
 .../solr/collection1/conf/schema_latest.xml     |   96 +-
 ...dd-schema-fields-update-processor-chains.xml |   32 +-
 .../conf/solrconfig-altdirectory.xml            |    2 +-
 .../conf/solrconfig-analytics-query.xml         |  230 +-
 .../solr/collection1/conf/solrconfig-basic.xml  |    2 +-
 .../conf/solrconfig-blockjoinfacetcomponent.xml |   11 +-
 .../conf/solrconfig-cache-enable-disable.xml    |    4 +-
 .../solr/collection1/conf/solrconfig-cdcr.xml   |    2 +-
 .../conf/solrconfig-cdcrupdatelog.xml           |    2 +-
 .../conf/solrconfig-classification.xml          |    2 +-
 .../conf/solrconfig-collapseqparser.xml         |  128 +-
 .../conf/solrconfig-components-name.xml         |    7 +-
 .../solrconfig-configurerecoverystrategy.xml    |    2 +-
 .../conf/solrconfig-customrecoverystrategy.xml  |    2 +-
 .../conf/solrconfig-delaying-component.xml      |    4 +-
 .../collection1/conf/solrconfig-delpolicy1.xml  |    5 +-
 .../collection1/conf/solrconfig-delpolicy2.xml  |    5 +-
 ...lrconfig-distrib-update-processor-chains.xml |    3 +-
 .../conf/solrconfig-doctransformers.xml         |    6 +-
 .../collection1/conf/solrconfig-elevate.xml     |    5 +-
 .../solrconfig-externalversionconstraint.xml    |    2 +-
 .../conf/solrconfig-functionquery.xml           |    4 +-
 .../solr/collection1/conf/solrconfig-hash.xml   |    6 +-
 .../collection1/conf/solrconfig-headers.xml     |    2 +-
 .../collection1/conf/solrconfig-highlight.xml   |    2 +-
 .../conf/solrconfig-implicitproperties.xml      |    2 +-
 .../collection1/conf/solrconfig-indexconfig.xml |   31 -
 .../conf/solrconfig-indexmetrics.xml            |    8 +-
 .../conf/solrconfig-infixsuggesters.xml         |    2 +-
 .../conf/solrconfig-logmergepolicy.xml          |   36 -
 .../conf/solrconfig-logmergepolicyfactory.xml   |    2 +-
 .../conf/solrconfig-managed-schema-test.xml     |    2 +-
 .../conf/solrconfig-managed-schema.xml          |    4 +-
 .../conf/solrconfig-master-throttled.xml        |   11 +-
 .../solr/collection1/conf/solrconfig-master.xml |   11 +-
 .../conf/solrconfig-master1-keepOneBackup.xml   |    7 +-
 .../collection1/conf/solrconfig-master1.xml     |   11 +-
 .../collection1/conf/solrconfig-master2.xml     |   11 +-
 .../collection1/conf/solrconfig-master3.xml     |   11 +-
 .../conf/solrconfig-mergepolicy-defaults.xml    |    2 +-
 .../conf/solrconfig-mergepolicy-legacy.xml      |    3 +-
 .../conf/solrconfig-mergepolicy-nocfs.xml       |   34 -
 .../solrconfig-mergepolicyfactory-nocfs.xml     |    2 +-
 .../collection1/conf/solrconfig-nocache.xml     |   10 +-
 .../conf/solrconfig-nomergepolicyfactory.xml    |    2 +-
 .../collection1/conf/solrconfig-noopregen.xml   |    2 +-
 .../collection1/conf/solrconfig-paramset.xml    |    2 +-
 ...lrconfig-parsing-update-processor-chains.xml |    2 +-
 .../conf/solrconfig-phrasesuggest.xml           |    2 +-
 .../conf/solrconfig-plugcollector.xml           |   31 +-
 .../conf/solrconfig-postingshighlight.xml       |    2 +-
 .../conf/solrconfig-query-parser-init.xml       |    2 +-
 .../conf/solrconfig-querysender-noquery.xml     |    2 +-
 .../collection1/conf/solrconfig-querysender.xml |    8 +-
 .../collection1/conf/solrconfig-repeater.xml    |   11 +-
 .../collection1/conf/solrconfig-reqHandler.incl |    2 +-
 .../conf/solrconfig-response-log-component.xml  |   16 +-
 .../collection1/conf/solrconfig-schemaless.xml  |    8 +-
 .../conf/solrconfig-script-updateprocessor.xml  |    2 +-
 .../conf/solrconfig-searcher-listeners1.xml     |    2 +-
 .../solr/collection1/conf/solrconfig-slave.xml  |   11 +-
 .../solr/collection1/conf/solrconfig-slave1.xml |   11 +-
 .../conf/solrconfig-solcoreproperties.xml       |    2 +-
 .../solrconfig-sortingmergepolicyfactory.xml    |    4 +-
 .../conf/solrconfig-sortingresponse.xml         |    2 +-
 .../collection1/conf/solrconfig-spatial.xml     |    2 +-
 .../conf/solrconfig-spellcheckcomponent.xml     |   15 +-
 .../conf/solrconfig-spellchecker.xml            |    2 +-
 .../solr/collection1/conf/solrconfig-sql.xml    |    6 +-
 ...-suggestercomponent-context-filter-query.xml |    2 +-
 .../conf/solrconfig-suggestercomponent.xml      |    2 +-
 .../collection1/conf/solrconfig-test-misc.xml   |    4 +-
 .../conf/solrconfig-testxmlparser.xml           |    2 +-
 .../conf/solrconfig-tieredmergepolicy.xml       |   48 -
 .../solrconfig-tieredmergepolicyfactory.xml     |    2 +-
 .../solr/collection1/conf/solrconfig-tlog.xml   |    5 +-
 ...nfig-uninvertdocvaluesmergepolicyfactory.xml |    2 +-
 .../conf/solrconfig-update-processor-chains.xml |    2 +-
 ...lrconfig-warmer-randommergepolicyfactory.xml |    2 +-
 .../solr/collection1/conf/solrconfig-warmer.xml |   46 -
 .../solrconfig.snippet.randomindexconfig.xml    |    3 +-
 .../solr/collection1/conf/solrconfig.xml        |   43 +-
 .../conf/solrconfig_SimpleTextCodec.xml         |    2 +-
 .../solr/collection1/conf/solrconfig_codec.xml  |    2 +-
 .../solr/collection1/conf/solrconfig_codec2.xml |    2 +-
 .../solr/collection1/conf/solrconfig_perf.xml   |    7 +-
 .../solr/configsets/_default/conf/currency.xml  |   67 +
 .../solr/configsets/_default/conf/elevate.xml   |   42 +
 .../_default/conf/lang/contractions_ca.txt      |    8 +
 .../_default/conf/lang/contractions_fr.txt      |   15 +
 .../_default/conf/lang/contractions_ga.txt      |    5 +
 .../_default/conf/lang/contractions_it.txt      |   23 +
 .../_default/conf/lang/hyphenations_ga.txt      |    5 +
 .../_default/conf/lang/stemdict_nl.txt          |    6 +
 .../_default/conf/lang/stoptags_ja.txt          |  420 +++
 .../_default/conf/lang/stopwords_ar.txt         |  125 +
 .../_default/conf/lang/stopwords_bg.txt         |  193 ++
 .../_default/conf/lang/stopwords_ca.txt         |  220 ++
 .../_default/conf/lang/stopwords_cz.txt         |  172 +
 .../_default/conf/lang/stopwords_da.txt         |  110 +
 .../_default/conf/lang/stopwords_de.txt         |  294 ++
 .../_default/conf/lang/stopwords_el.txt         |   78 +
 .../_default/conf/lang/stopwords_en.txt         |   54 +
 .../_default/conf/lang/stopwords_es.txt         |  356 ++
 .../_default/conf/lang/stopwords_eu.txt         |   99 +
 .../_default/conf/lang/stopwords_fa.txt         |  313 ++
 .../_default/conf/lang/stopwords_fi.txt         |   97 +
 .../_default/conf/lang/stopwords_fr.txt         |  186 +
 .../_default/conf/lang/stopwords_ga.txt         |  110 +
 .../_default/conf/lang/stopwords_gl.txt         |  161 +
 .../_default/conf/lang/stopwords_hi.txt         |  235 ++
 .../_default/conf/lang/stopwords_hu.txt         |  211 ++
 .../_default/conf/lang/stopwords_hy.txt         |   46 +
 .../_default/conf/lang/stopwords_id.txt         |  359 ++
 .../_default/conf/lang/stopwords_it.txt         |  303 ++
 .../_default/conf/lang/stopwords_ja.txt         |  127 +
 .../_default/conf/lang/stopwords_lv.txt         |  172 +
 .../_default/conf/lang/stopwords_nl.txt         |  119 +
 .../_default/conf/lang/stopwords_no.txt         |  194 ++
 .../_default/conf/lang/stopwords_pt.txt         |  253 ++
 .../_default/conf/lang/stopwords_ro.txt         |  233 ++
 .../_default/conf/lang/stopwords_ru.txt         |  243 ++
 .../_default/conf/lang/stopwords_sv.txt         |  133 +
 .../_default/conf/lang/stopwords_th.txt         |  119 +
 .../_default/conf/lang/stopwords_tr.txt         |  212 ++
 .../_default/conf/lang/userdict_ja.txt          |   29 +
 .../configsets/_default/conf/managed-schema     | 1076 ++++++
 .../solr/configsets/_default/conf/params.json   |   20 +
 .../solr/configsets/_default/conf/protwords.txt |   21 +
 .../configsets/_default/conf/solrconfig.xml     | 1373 ++++++++
 .../solr/configsets/_default/conf/stopwords.txt |   14 +
 .../solr/configsets/_default/conf/synonyms.txt  |   29 +
 .../bad-mergepolicy/conf/solrconfig.xml         |    2 +-
 .../cdcr-source-disabled/conf/schema.xml        |    2 +-
 .../solr/configsets/cdcr-source/conf/schema.xml |    2 +-
 .../configsets/cdcr-source/conf/solrconfig.xml  |    3 +-
 .../solr/configsets/cdcr-target/conf/schema.xml |    2 +-
 .../configsets/cdcr-target/conf/solrconfig.xml  |    3 +-
 .../solr/configsets/cloud-hdfs/conf/schema.xml  |    2 +-
 .../conf/managed-schema                         |    2 +-
 .../cloud-managed-upgrade/conf/schema.xml       |    2 +-
 .../cloud-managed/conf/managed-schema           |    2 +-
 .../cloud-minimal-jmx/conf/schema.xml           |    2 +-
 .../configsets/cloud-minimal/conf/schema.xml    |    3 +-
 .../configsets/cloud-subdirs/conf/schema.xml    |    2 +-
 .../solr/configsets/configset-2/conf/schema.xml |    4 +-
 .../exitable-directory/conf/schema.xml          |    2 +-
 .../exitable-directory/conf/solrconfig.xml      |    2 +-
 .../test-files/solr/crazy-path-to-config.xml    |   10 +-
 .../test-files/solr/crazy-path-to-schema.xml    |    4 +-
 .../org/apache/solr/BasicFunctionalityTest.java |  119 +-
 .../org/apache/solr/ConvertedLegacyTest.java    |   46 +-
 .../test/org/apache/solr/CursorPagingTest.java  |   60 +-
 .../apache/solr/DisMaxRequestHandlerTest.java   |   30 +-
 .../test/org/apache/solr/EchoParamsTest.java    |    4 +-
 .../src/test/org/apache/solr/SampleTest.java    |    6 +-
 .../test/org/apache/solr/SolrInfoBeanTest.java  |    4 +-
 .../apache/solr/TestDistributedGrouping.java    |   25 +-
 .../apache/solr/TestDistributedMissingSort.java |   60 +-
 .../org/apache/solr/TestDistributedSearch.java  |   31 +-
 .../org/apache/solr/TestGroupingSearch.java     |    6 +-
 .../core/src/test/org/apache/solr/TestJoin.java |    2 +-
 .../org/apache/solr/TestRandomDVFaceting.java   |    5 +
 .../org/apache/solr/TestRandomFaceting.java     |    3 +
 .../org/apache/solr/TestTolerantSearch.java     |    4 +-
 .../PathHierarchyTokenizerFactoryTest.java      |   32 +-
 .../apache/solr/analysis/TestCharFilters.java   |    8 +-
 .../test/org/apache/solr/api/TestPathTrie.java  |   61 -
 .../solr/cloud/BaseCdcrDistributedZkTest.java   |   26 +-
 .../solr/cloud/BasicDistributedZk2Test.java     |   37 +-
 .../solr/cloud/BasicDistributedZkTest.java      |  147 +-
 .../test/org/apache/solr/cloud/BasicZkTest.java |    6 +-
 ...MonkeyNothingIsSafeWithPullReplicasTest.java |    2 +
 ...aosMonkeySafeLeaderWithPullReplicasTest.java |    2 +
 .../solr/cloud/ClusterStateUpdateTest.java      |  175 +-
 .../cloud/CollectionsAPIDistributedZkTest.java  |  125 +-
 .../solr/cloud/CollectionsAPISolrJTest.java     |   40 +-
 .../solr/cloud/DistribCursorPagingTest.java     |   10 +-
 .../cloud/DistribJoinFromCollectionTest.java    |    8 +-
 .../org/apache/solr/cloud/ForceLeaderTest.java  |    4 +-
 .../FullThrottleStoppableIndexingThread.java    |   33 +-
 .../apache/solr/cloud/HttpPartitionTest.java    |   12 +-
 .../cloud/LeaderElectionIntegrationTest.java    |  294 +-
 .../cloud/LeaderFailoverAfterPartitionTest.java |    2 +-
 .../cloud/LeaderFailureAfterFreshStartTest.java |    4 +-
 .../LeaderInitiatedRecoveryOnCommitTest.java    |    4 +-
 ...aderInitiatedRecoveryOnShardRestartTest.java |    2 +-
 ...verseerCollectionConfigSetProcessorTest.java |   41 +-
 .../org/apache/solr/cloud/OverseerTest.java     |  339 +-
 .../org/apache/solr/cloud/ReplaceNodeTest.java  |   11 +-
 .../solr/cloud/ReplicationFactorTest.java       |    6 +-
 .../cloud/SegmentTerminateEarlyTestState.java   |   30 +-
 .../solr/cloud/ShardRoutingCustomTest.java      |   12 +
 .../org/apache/solr/cloud/ShardSplitTest.java   |    2 +-
 .../apache/solr/cloud/SolrCloudExampleTest.java |   11 +-
 .../solr/cloud/TestAuthenticationFramework.java |   13 +-
 .../cloud/TestCloudJSONFacetJoinDomain.java     |    6 +-
 .../apache/solr/cloud/TestCloudPivotFacet.java  |    7 +-
 .../apache/solr/cloud/TestCollectionAPI.java    |   29 +-
 .../apache/solr/cloud/TestConfigSetsAPI.java    |   51 +-
 .../solr/cloud/TestMiniSolrCloudCluster.java    |   22 +-
 .../cloud/TestOnReconnectListenerSupport.java   |    2 +-
 .../org/apache/solr/cloud/TestPullReplica.java  |   89 +-
 .../cloud/TestRandomRequestDistribution.java    |   10 +-
 .../cloud/TestSolrCloudWithKerberosAlt.java     |   15 +-
 .../solr/cloud/TestStressInPlaceUpdates.java    |   14 -
 .../org/apache/solr/cloud/TestTlogReplica.java  |   86 +-
 .../solr/cloud/UnloadDistributedZkTest.java     |  195 +-
 .../org/apache/solr/cloud/ZkControllerTest.java |   19 +-
 .../autoscaling/AutoScalingHandlerTest.java     |  327 ++
 .../solr/cloud/autoscaling/TestPolicyCloud.java |  199 ++
 .../solr/cloud/hdfs/HdfsNNFailoverTest.java     |    2 +-
 .../HdfsWriteToMultipleCollectionsTest.java     |    2 +-
 .../apache/solr/cloud/hdfs/StressHdfsTest.java  |    4 +-
 .../solr/cloud/rule/ImplicitSnitchTest.java     |   50 +-
 .../solr/core/AlternateDirectoryTest.java       |    2 +-
 .../apache/solr/core/DirectoryFactoryTest.java  |   61 +
 .../test/org/apache/solr/core/HelloStream.java  |    2 +-
 .../test/org/apache/solr/core/MockInfoBean.java |    2 +-
 .../apache/solr/core/RequestHandlersTest.java   |    8 +-
 .../test/org/apache/solr/core/SOLR749Test.java  |   12 +-
 .../test/org/apache/solr/core/SolrCoreTest.java |    2 +-
 .../org/apache/solr/core/TestBadConfig.java     |    2 -
 .../test/org/apache/solr/core/TestConfig.java   |   13 +-
 .../org/apache/solr/core/TestCoreContainer.java |    4 +-
 .../org/apache/solr/core/TestCoreDiscovery.java |    3 +-
 .../apache/solr/core/TestJmxIntegration.java    |    2 +-
 .../org/apache/solr/core/TestLazyCores.java     |   44 +-
 .../apache/solr/core/TestMergePolicyConfig.java |   18 +-
 .../test/org/apache/solr/core/TestNRTOpen.java  |    3 -
 .../solr/core/TestQuerySenderListener.java      |    2 +-
 .../solr/core/TestQuerySenderNoQuery.java       |    2 +-
 .../apache/solr/core/TestSolrIndexConfig.java   |    2 +-
 .../apache/solr/core/TestXIncludeConfig.java    |    2 +-
 .../core/snapshots/TestSolrCloudSnapshots.java  |    2 +-
 .../core/snapshots/TestSolrCoreSnapshots.java   |    2 +-
 .../solr/handler/MoreLikeThisHandlerTest.java   |   21 +-
 .../apache/solr/handler/SearchHandlerTest.java  |   80 +
 .../handler/StandardRequestHandlerTest.java     |   88 -
 .../apache/solr/handler/TestConfigReload.java   |    2 +-
 .../apache/solr/handler/TestReqParamsAPI.java   |    2 +-
 .../org/apache/solr/handler/TestSQLHandler.java |   32 +-
 .../handler/ThrowErrorOnInitRequestHandler.java |    4 +
 .../solr/handler/V2ApiIntegrationTest.java      |   63 +-
 .../apache/solr/handler/V2StandaloneTest.java   |   53 +
 .../handler/XsltUpdateRequestHandlerTest.java   |    2 +-
 .../handler/admin/CoreAdminHandlerTest.java     |   50 +
 .../solr/handler/admin/MBeansHandlerTest.java   |    2 +-
 .../admin/PropertiesRequestHandlerTest.java     |    2 +-
 .../admin/SegmentsInfoRequestHandlerTest.java   |    2 -
 .../solr/handler/admin/TestApiFramework.java    |    2 +-
 .../solr/handler/admin/TestCollectionAPIs.java  |   48 +-
 .../solr/handler/admin/TestConfigsApi.java      |    2 +-
 .../DistributedExpandComponentTest.java         |   40 +-
 .../DistributedFacetPivotLargeTest.java         |    5 +
 .../DistributedFacetPivotLongTailTest.java      |    5 +
 .../DistributedFacetPivotSmallAdvancedTest.java |    5 +
 .../DistributedFacetPivotSmallTest.java         |    5 +
 .../DistributedFacetPivotWhiteBoxTest.java      |    5 +
 .../component/DistributedMLTComponentTest.java  |   12 +-
 ...DistributedQueryComponentCustomSortTest.java |   38 +-
 .../DistributedQueryElevationComponentTest.java |    4 +-
 .../DistributedSpellCheckComponentTest.java     |   10 +-
 .../DistributedTermsComponentTest.java          |    3 +
 .../component/DummyCustomParamSpellChecker.java |   14 +-
 .../handler/component/FacetPivotSmallTest.java  |    3 +-
 .../component/QueryElevationComponentTest.java  |   90 +-
 .../component/ResponseLogComponentTest.java     |   12 +-
 .../component/SpellCheckComponentTest.java      |   10 +-
 .../handler/component/StatsComponentTest.java   |   23 +-
 .../handler/component/SuggestComponentTest.java |    2 +-
 .../component/TermVectorComponentTest.java      |    2 +-
 .../handler/component/TermsComponentTest.java   |    2 +-
 ...estDistributedStatsComponentCardinality.java |   26 +-
 .../handler/component/TestExpandComponent.java  |  100 +-
 .../TestTrackingShardHandlerFactory.java        |    2 +-
 .../highlight/FastVectorHighlighterTest.java    |    2 +-
 .../solr/highlight/HighlighterConfigTest.java   |    2 +-
 .../apache/solr/highlight/HighlighterTest.java  |   84 +-
 .../solr/metrics/SolrMetricManagerTest.java     |    5 +
 .../metrics/SolrMetricsIntegrationTest.java     |    2 +-
 .../metrics/reporters/MockMetricReporter.java   |    7 +-
 .../apache/solr/request/SimpleFacetsTest.java   |  156 +-
 .../org/apache/solr/request/TestFaceting.java   |   27 +-
 .../solr/request/TestIntervalFaceting.java      |    4 +-
 .../org/apache/solr/request/TestWriterPerf.java |    2 +
 .../solr/response/TestBinaryResponseWriter.java |    5 +-
 .../apache/solr/response/TestExportWriter.java  |  187 +-
 .../response/TestJavabinTupleStreamParser.java  |   20 +-
 .../apache/solr/response/TestPushWriter.java    |    8 +-
 .../transform/TestChildDocTransformer.java      |  120 +-
 .../transform/TestSubQueryTransformer.java      |   28 +-
 .../org/apache/solr/rest/TestRestManager.java   |    2 +-
 .../schema/TestFieldCollectionResource.java     |   10 +-
 .../solr/schema/AbstractCurrencyFieldTest.java  |  426 ---
 .../apache/solr/schema/BadIndexSchemaTest.java  |   63 +-
 .../org/apache/solr/schema/CopyFieldTest.java   |   12 +-
 .../schema/CurrencyFieldOpenExchangeTest.java   |   27 -
 .../solr/schema/CurrencyFieldTypeTest.java      |  494 +++
 .../solr/schema/CurrencyFieldXmlFileTest.java   |   42 -
 .../apache/solr/schema/DateRangeFieldTest.java  |    2 +-
 .../org/apache/solr/schema/DocValuesTest.java   |  256 +-
 .../schema/IndexSchemaRuntimeFieldTest.java     |    4 +-
 .../org/apache/solr/schema/IndexSchemaTest.java |   28 +-
 .../OpenExchangeRatesOrgProviderTest.java       |    2 +-
 .../org/apache/solr/schema/PolyFieldTest.java   |    8 -
 .../apache/solr/schema/SchemaWatcherTest.java   |   56 +
 .../org/apache/solr/schema/TestBinaryField.java |    6 +-
 .../solr/schema/TestCloudManagedSchema.java     |    2 +-
 .../apache/solr/schema/TestCollationField.java  |   32 +-
 .../schema/TestCollationFieldDocValues.java     |   32 +-
 .../solr/schema/TestHalfAndHalfDocValues.java   |   10 +-
 .../apache/solr/schema/TestOmitPositions.java   |    4 +-
 .../org/apache/solr/schema/TestPointFields.java |  578 ++--
 .../apache/solr/search/QueryEqualityTest.java   |   16 +
 .../apache/solr/search/SpatialFilterTest.java   |    2 +-
 .../solr/search/TestCollapseQParserPlugin.java  |  282 +-
 .../TestComplexPhraseLeadingWildcard.java       |    2 +-
 .../search/TestComplexPhraseQParserPlugin.java  |    8 +-
 .../org/apache/solr/search/TestCustomSort.java  |   20 +-
 .../test/org/apache/solr/search/TestDocSet.java |    5 +-
 .../solr/search/TestExtendedDismaxParser.java   |   22 +-
 .../apache/solr/search/TestFieldSortValues.java |   10 +-
 .../solr/search/TestFoldingMultitermQuery.java  |    2 +-
 .../search/TestGraphTermsQParserPlugin.java     |   36 +-
 .../solr/search/TestHashQParserPlugin.java      |   14 +-
 .../apache/solr/search/TestIndexSearcher.java   |    3 -
 .../solr/search/TestMaxScoreQueryParser.java    |   10 +-
 .../org/apache/solr/search/TestQueryTypes.java  |   68 +-
 .../org/apache/solr/search/TestRangeQuery.java  |    8 +-
 .../solr/search/TestReRankQParserPlugin.java    |  208 +-
 .../test/org/apache/solr/search/TestReload.java |    2 +-
 .../org/apache/solr/search/TestSearchPerf.java  |    2 +-
 .../apache/solr/search/TestSolr4Spatial.java    |   26 +-
 .../apache/solr/search/TestSolrQueryParser.java |   76 +-
 .../org/apache/solr/search/TestTrieFacet.java   |   26 +-
 .../org/apache/solr/search/facet/DebugAgg.java  |    5 +-
 .../search/facet/TestJsonFacetRefinement.java   |  265 +-
 .../solr/search/facet/TestJsonFacets.java       |   14 +-
 .../search/function/SortByFunctionTest.java     |   68 +-
 .../solr/search/function/TestFunctionQuery.java |   65 +-
 .../function/TestMinMaxOnMultiValuedField.java  |  156 +-
 .../search/join/BlockJoinFacetDistribTest.java  |    2 +-
 .../search/join/BlockJoinFacetRandomTest.java   |    2 +-
 .../search/join/BlockJoinFacetSimpleTest.java   |    2 +-
 .../solr/search/mlt/SimpleMLTQParserTest.java   |   86 +-
 .../search/stats/TestDefaultStatsCache.java     |   17 +-
 .../solr/search/stats/TestDistribIDF.java       |   14 +-
 .../solr/security/MockAuthorizationPlugin.java  |    2 +-
 .../apache/solr/servlet/NoCacheHeaderTest.java  |    2 +-
 .../spelling/DirectSolrSpellCheckerTest.java    |    3 +-
 .../spelling/FileBasedSpellCheckerTest.java     |    1 -
 .../spelling/IndexBasedSpellCheckerTest.java    |    1 -
 .../solr/spelling/SimpleQueryConverter.java     |    8 +-
 .../solr/spelling/SpellCheckCollatorTest.java   |   58 +-
 .../SpellCheckCollatorWithCollapseTest.java     |    2 +-
 .../spelling/SpellPossibilityIteratorTest.java  |    2 -
 .../spelling/SpellingQueryConverterTest.java    |    9 +-
 .../spelling/TestSuggestSpellingConverter.java  |   10 +-
 .../spelling/WordBreakSolrSpellCheckerTest.java |   17 +-
 .../solr/spelling/suggest/SuggesterTest.java    |   19 +-
 .../suggest/TestAnalyzeInfixSuggestions.java    |    2 +-
 .../suggest/TestFreeTextSuggestions.java        |    2 +-
 .../apache/solr/update/AddBlockUpdateTest.java  |   10 +-
 .../solr/update/DirectUpdateHandlerTest.java    |    3 -
 .../apache/solr/update/DocumentBuilderTest.java |    4 +-
 .../solr/update/SolrCmdDistributorTest.java     |    3 -
 .../apache/solr/update/SolrIndexConfigTest.java |   36 +-
 .../solr/update/TestInPlaceUpdatesDistrib.java  |   18 -
 .../update/TestInPlaceUpdatesStandalone.java    |   18 -
 .../org/apache/solr/update/UpdateLogTest.java   |    9 -
 .../org/apache/solr/update/VersionInfoTest.java |  126 +-
 ...dSchemaFieldsUpdateProcessorFactoryTest.java |   16 +-
 .../AtomicUpdateProcessorFactoryTest.java       |   36 +-
 .../update/processor/AtomicUpdatesTest.java     |   36 +-
 .../ClassificationUpdateProcessorTest.java      |    2 +-
 .../processor/TemplateUpdateProcessorTest.java  |   67 +-
 .../UpdateRequestProcessorFactoryTest.java      |    8 +-
 .../org/apache/solr/util/JsonValidatorTest.java |  196 --
 .../org/apache/solr/util/PrimUtilsTest.java     |    2 +-
 .../apache/solr/util/TestSolrCLIRunExample.java |    2 +-
 .../test/org/apache/solr/util/TestUtils.java    |   74 +-
 .../org/apache/solr/util/UtilsToolTest.java     |    2 +-
 .../org/apache/solr/util/hll/BitVectorTest.java |    2 +-
 .../apache/solr/util/hll/ExplicitHLLTest.java   |    2 +-
 .../org/apache/solr/util/hll/FullHLLTest.java   |    2 +-
 .../example-DIH/solr/db/conf/managed-schema     |   27 +-
 .../example-DIH/solr/db/conf/solrconfig.xml     |   42 +-
 .../example-DIH/solr/mail/conf/managed-schema   |   27 +-
 .../example-DIH/solr/mail/conf/solrconfig.xml   |   42 +-
 .../example-DIH/solr/solr/conf/currency.xml     |    2 +-
 .../example-DIH/solr/solr/conf/managed-schema   |   27 +-
 .../example-DIH/solr/solr/conf/solrconfig.xml   |   42 +-
 solr/example/files/conf/managed-schema          |   24 +-
 solr/example/files/conf/solrconfig.xml          |   46 +-
 solr/licenses/noggit-0.6.jar.sha1               |    1 -
 solr/licenses/noggit-0.8.jar.sha1               |    1 +
 solr/server/README.txt                          |   11 +-
 .../server/etc/test/create-solrtest.keystore.sh |   37 -
 solr/server/etc/test/solrtest.keystore          |  Bin 2208 -> 0 bytes
 .../solr/configsets/_default/conf/currency.xml  |   67 +
 .../solr/configsets/_default/conf/elevate.xml   |   42 +
 .../_default/conf/lang/contractions_ca.txt      |    8 +
 .../_default/conf/lang/contractions_fr.txt      |   15 +
 .../_default/conf/lang/contractions_ga.txt      |    5 +
 .../_default/conf/lang/contractions_it.txt      |   23 +
 .../_default/conf/lang/hyphenations_ga.txt      |    5 +
 .../_default/conf/lang/stemdict_nl.txt          |    6 +
 .../_default/conf/lang/stoptags_ja.txt          |  420 +++
 .../_default/conf/lang/stopwords_ar.txt         |  125 +
 .../_default/conf/lang/stopwords_bg.txt         |  193 ++
 .../_default/conf/lang/stopwords_ca.txt         |  220 ++
 .../_default/conf/lang/stopwords_cz.txt         |  172 +
 .../_default/conf/lang/stopwords_da.txt         |  110 +
 .../_default/conf/lang/stopwords_de.txt         |  294 ++
 .../_default/conf/lang/stopwords_el.txt         |   78 +
 .../_default/conf/lang/stopwords_en.txt         |   54 +
 .../_default/conf/lang/stopwords_es.txt         |  356 ++
 .../_default/conf/lang/stopwords_eu.txt         |   99 +
 .../_default/conf/lang/stopwords_fa.txt         |  313 ++
 .../_default/conf/lang/stopwords_fi.txt         |   97 +
 .../_default/conf/lang/stopwords_fr.txt         |  186 +
 .../_default/conf/lang/stopwords_ga.txt         |  110 +
 .../_default/conf/lang/stopwords_gl.txt         |  161 +
 .../_default/conf/lang/stopwords_hi.txt         |  235 ++
 .../_default/conf/lang/stopwords_hu.txt         |  211 ++
 .../_default/conf/lang/stopwords_hy.txt         |   46 +
 .../_default/conf/lang/stopwords_id.txt         |  359 ++
 .../_default/conf/lang/stopwords_it.txt         |  303 ++
 .../_default/conf/lang/stopwords_ja.txt         |  127 +
 .../_default/conf/lang/stopwords_lv.txt         |  172 +
 .../_default/conf/lang/stopwords_nl.txt         |  119 +
 .../_default/conf/lang/stopwords_no.txt         |  194 ++
 .../_default/conf/lang/stopwords_pt.txt         |  253 ++
 .../_default/conf/lang/stopwords_ro.txt         |  233 ++
 .../_default/conf/lang/stopwords_ru.txt         |  243 ++
 .../_default/conf/lang/stopwords_sv.txt         |  133 +
 .../_default/conf/lang/stopwords_th.txt         |  119 +
 .../_default/conf/lang/stopwords_tr.txt         |  212 ++
 .../_default/conf/lang/userdict_ja.txt          |   29 +
 .../configsets/_default/conf/managed-schema     | 1076 ++++++
 .../solr/configsets/_default/conf/params.json   |   20 +
 .../solr/configsets/_default/conf/protwords.txt |   21 +
 .../configsets/_default/conf/solrconfig.xml     | 1373 ++++++++
 .../solr/configsets/_default/conf/stopwords.txt |   14 +
 .../solr/configsets/_default/conf/synonyms.txt  |   29 +
 .../configsets/basic_configs/conf/currency.xml  |   67 -
 .../configsets/basic_configs/conf/elevate.xml   |   42 -
 .../basic_configs/conf/lang/contractions_ca.txt |    8 -
 .../basic_configs/conf/lang/contractions_fr.txt |   15 -
 .../basic_configs/conf/lang/contractions_ga.txt |    5 -
 .../basic_configs/conf/lang/contractions_it.txt |   23 -
 .../basic_configs/conf/lang/hyphenations_ga.txt |    5 -
 .../basic_configs/conf/lang/stemdict_nl.txt     |    6 -
 .../basic_configs/conf/lang/stoptags_ja.txt     |  420 ---
 .../basic_configs/conf/lang/stopwords_ar.txt    |  125 -
 .../basic_configs/conf/lang/stopwords_bg.txt    |  193 --
 .../basic_configs/conf/lang/stopwords_ca.txt    |  220 --
 .../basic_configs/conf/lang/stopwords_cz.txt    |  172 -
 .../basic_configs/conf/lang/stopwords_da.txt    |  110 -
 .../basic_configs/conf/lang/stopwords_de.txt    |  294 --
 .../basic_configs/conf/lang/stopwords_el.txt    |   78 -
 .../basic_configs/conf/lang/stopwords_en.txt    |   54 -
 .../basic_configs/conf/lang/stopwords_es.txt    |  356 --
 .../basic_configs/conf/lang/stopwords_eu.txt    |   99 -
 .../basic_configs/conf/lang/stopwords_fa.txt    |  313 --
 .../basic_configs/conf/lang/stopwords_fi.txt    |   97 -
 .../basic_configs/conf/lang/stopwords_fr.txt    |  186 -
 .../basic_configs/conf/lang/stopwords_ga.txt    |  110 -
 .../basic_configs/conf/lang/stopwords_gl.txt    |  161 -
 .../basic_configs/conf/lang/stopwords_hi.txt    |  235 --
 .../basic_configs/conf/lang/stopwords_hu.txt    |  211 --
 .../basic_configs/conf/lang/stopwords_hy.txt    |   46 -
 .../basic_configs/conf/lang/stopwords_id.txt    |  359 --
 .../basic_configs/conf/lang/stopwords_it.txt    |  303 --
 .../basic_configs/conf/lang/stopwords_ja.txt    |  127 -
 .../basic_configs/conf/lang/stopwords_lv.txt    |  172 -
 .../basic_configs/conf/lang/stopwords_nl.txt    |  119 -
 .../basic_configs/conf/lang/stopwords_no.txt    |  194 --
 .../basic_configs/conf/lang/stopwords_pt.txt    |  253 --
 .../basic_configs/conf/lang/stopwords_ro.txt    |  233 --
 .../basic_configs/conf/lang/stopwords_ru.txt    |  243 --
 .../basic_configs/conf/lang/stopwords_sv.txt    |  133 -
 .../basic_configs/conf/lang/stopwords_th.txt    |  119 -
 .../basic_configs/conf/lang/stopwords_tr.txt    |  212 --
 .../basic_configs/conf/lang/userdict_ja.txt     |   29 -
 .../basic_configs/conf/managed-schema           | 1045 ------
 .../configsets/basic_configs/conf/params.json   |   20 -
 .../configsets/basic_configs/conf/protwords.txt |   21 -
 .../basic_configs/conf/solrconfig.xml           | 1410 --------
 .../configsets/basic_configs/conf/stopwords.txt |   14 -
 .../configsets/basic_configs/conf/synonyms.txt  |   29 -
 .../conf/currency.xml                           |   67 -
 .../data_driven_schema_configs/conf/elevate.xml |   42 -
 .../conf/lang/contractions_ca.txt               |    8 -
 .../conf/lang/contractions_fr.txt               |   15 -
 .../conf/lang/contractions_ga.txt               |    5 -
 .../conf/lang/contractions_it.txt               |   23 -
 .../conf/lang/hyphenations_ga.txt               |    5 -
 .../conf/lang/stemdict_nl.txt                   |    6 -
 .../conf/lang/stoptags_ja.txt                   |  420 ---
 .../conf/lang/stopwords_ar.txt                  |  125 -
 .../conf/lang/stopwords_bg.txt                  |  193 --
 .../conf/lang/stopwords_ca.txt                  |  220 --
 .../conf/lang/stopwords_cz.txt                  |  172 -
 .../conf/lang/stopwords_da.txt                  |  110 -
 .../conf/lang/stopwords_de.txt                  |  294 --
 .../conf/lang/stopwords_el.txt                  |   78 -
 .../conf/lang/stopwords_en.txt                  |   54 -
 .../conf/lang/stopwords_es.txt                  |  356 --
 .../conf/lang/stopwords_eu.txt                  |   99 -
 .../conf/lang/stopwords_fa.txt                  |  313 --
 .../conf/lang/stopwords_fi.txt                  |   97 -
 .../conf/lang/stopwords_fr.txt                  |  186 -
 .../conf/lang/stopwords_ga.txt                  |  110 -
 .../conf/lang/stopwords_gl.txt                  |  161 -
 .../conf/lang/stopwords_hi.txt                  |  235 --
 .../conf/lang/stopwords_hu.txt                  |  211 --
 .../conf/lang/stopwords_hy.txt                  |   46 -
 .../conf/lang/stopwords_id.txt                  |  359 --
 .../conf/lang/stopwords_it.txt                  |  303 --
 .../conf/lang/stopwords_ja.txt                  |  127 -
 .../conf/lang/stopwords_lv.txt                  |  172 -
 .../conf/lang/stopwords_nl.txt                  |  119 -
 .../conf/lang/stopwords_no.txt                  |  194 --
 .../conf/lang/stopwords_pt.txt                  |  253 --
 .../conf/lang/stopwords_ro.txt                  |  233 --
 .../conf/lang/stopwords_ru.txt                  |  243 --
 .../conf/lang/stopwords_sv.txt                  |  133 -
 .../conf/lang/stopwords_th.txt                  |  119 -
 .../conf/lang/stopwords_tr.txt                  |  212 --
 .../conf/lang/userdict_ja.txt                   |   29 -
 .../conf/managed-schema                         | 1069 ------
 .../data_driven_schema_configs/conf/params.json |   20 -
 .../conf/protwords.txt                          |   21 -
 .../conf/solrconfig.xml                         | 1408 --------
 .../conf/stopwords.txt                          |   14 -
 .../conf/synonyms.txt                           |   29 -
 .../conf/managed-schema                         |   27 +-
 .../conf/solrconfig.xml                         |   56 +-
 solr/solr-ref-guide/build.xml                   |   31 +-
 solr/solr-ref-guide/meta-docs/publish.adoc      |    1 -
 solr/solr-ref-guide/src/_config.yml.template    |    9 +-
 solr/solr-ref-guide/src/_includes/head.html     |    2 -
 ...adding-custom-plugins-in-solrcloud-mode.adoc |    2 +-
 .../src/basic-authentication-plugin.adoc        |   22 +-
 solr/solr-ref-guide/src/blockjoin-faceting.adoc |   19 +-
 .../solr-ref-guide/src/charfilterfactories.adoc |   26 +-
 solr/solr-ref-guide/src/cloud-screens.adoc      |    2 +-
 solr/solr-ref-guide/src/codec-factory.adoc      |   12 +-
 .../src/collapse-and-expand-results.adoc        |   84 +-
 solr/solr-ref-guide/src/collections-api.adoc    | 1009 +++---
 .../src/command-line-utilities.adoc             |    2 +-
 .../src/common-query-parameters.adoc            |   30 +-
 solr/solr-ref-guide/src/config-api.adoc         |    2 +-
 solr/solr-ref-guide/src/configsets-api.adoc     |   61 +-
 .../src/configuring-solrconfig-xml.adoc         |    3 +-
 solr/solr-ref-guide/src/content-streams.adoc    |   28 +-
 solr/solr-ref-guide/src/coreadmin-api.adoc      |  284 +-
 .../src/cross-data-center-replication-cdcr.adoc |   55 +-
 solr/solr-ref-guide/src/css/ref-guide.css       |    5 +-
 solr/solr-ref-guide/src/css/theme-solr.css      |    2 +-
 ...adir-and-directoryfactory-in-solrconfig.adoc |    4 +-
 solr/solr-ref-guide/src/de-duplication.adoc     |   45 +-
 .../src/defining-core-properties.adoc           |   52 +-
 solr/solr-ref-guide/src/defining-fields.adoc    |   18 +-
 .../detecting-languages-during-indexing.adoc    |   99 +-
 .../src/distributed-requests.adoc               |   45 +-
 .../distributed-search-with-index-sharding.adoc |    2 +-
 solr/solr-ref-guide/src/enabling-ssl.adoc       |   12 +-
 .../src/exporting-result-sets.adoc              |    2 +-
 solr/solr-ref-guide/src/faceting.adoc           |   64 +-
 solr/solr-ref-guide/src/feed.xml                |   28 -
 .../field-type-definitions-and-properties.adoc  |   40 +-
 .../src/field-types-included-with-solr.adoc     |    3 +-
 .../solr-ref-guide/src/filter-descriptions.adoc |   36 +-
 solr/solr-ref-guide/src/format-of-solr-xml.adoc |  203 +-
 solr/solr-ref-guide/src/function-queries.adoc   |  451 ++-
 solr/solr-ref-guide/src/graph-traversal.adoc    |  296 +-
 .../src/hadoop-authentication-plugin.adoc       |   44 +-
 solr/solr-ref-guide/src/highlighting.adoc       |  301 +-
 .../src/images/Solr_Logo_on_white.png           |  Bin 0 -> 47661 bytes
 .../src/implicit-requesthandlers.adoc           |    2 +-
 solr/solr-ref-guide/src/index-replication.adoc  |  194 +-
 .../src/indexconfig-in-solrconfig.adoc          |   29 +-
 .../src/initparams-in-solrconfig.adoc           |   16 +-
 .../src/introduction-to-solr-indexing.adoc      |    2 +-
 solr/solr-ref-guide/src/jvm-settings.adoc       |    2 +-
 .../src/kerberos-authentication-plugin.adoc     |   72 +-
 solr/solr-ref-guide/src/language-analysis.adoc  |   10 +-
 solr/solr-ref-guide/src/learning-to-rank.adoc   |    2 +-
 .../src/local-parameters-in-queries.adoc        |    2 +-
 .../major-changes-from-solr-5-to-solr-6.adoc    |    6 +-
 .../src/making-and-restoring-backups.adoc       |  102 +-
 .../src/mbean-request-handler.adoc              |   21 +-
 solr/solr-ref-guide/src/merging-indexes.adoc    |    2 +-
 solr/solr-ref-guide/src/metrics-reporting.adoc  |  147 +-
 solr/solr-ref-guide/src/morelikethis.adoc       |   76 +-
 .../src/near-real-time-searching.adoc           |   44 +-
 solr/solr-ref-guide/src/other-parsers.adoc      |  203 +-
 .../src/parallel-sql-interface.adoc             |   18 +-
 .../solr-ref-guide/src/parameter-reference.adoc |   45 +-
 .../src/pdf/SolrRefGuide-all.adoc               |    6 +-
 .../src/pdf/themes/refguide-theme.yml           |   17 +-
 .../src/performance-statistics-reference.adoc   |    2 +-
 solr/solr-ref-guide/src/query-re-ranking.adoc   |   15 +-
 solr/solr-ref-guide/src/query-screen.adoc       |   68 +-
 .../src/query-settings-in-solrconfig.adoc       |   22 +-
 .../read-and-write-side-fault-tolerance.adoc    |    4 +-
 solr/solr-ref-guide/src/replication-screen.adoc |    4 +-
 .../src/request-parameters-api.adoc             |    2 +-
 .../src/requestdispatcher-in-solrconfig.adoc    |   35 +-
 ...lers-and-searchcomponents-in-solrconfig.adoc |   14 +-
 solr/solr-ref-guide/src/response-writers.adoc   |  103 +-
 solr/solr-ref-guide/src/result-clustering.adoc  |   82 +-
 solr/solr-ref-guide/src/result-grouping.adoc    |   77 +-
 .../src/rule-based-authorization-plugin.adoc    |   65 +-
 .../src/running-solr-on-hdfs.adoc               |   95 +-
 solr/solr-ref-guide/src/schema-api.adoc         |  361 +-
 ...schema-factory-definition-in-solrconfig.adoc |    6 +-
 solr/solr-ref-guide/src/schemaless-mode.adoc    |    8 +-
 ...tting-up-an-external-zookeeper-ensemble.adoc |    8 +-
 .../shards-and-indexing-data-in-solrcloud.adoc  |    2 +-
 solr/solr-ref-guide/src/sitemap.xml             |    2 +-
 .../src/solr-control-script-reference.adoc      |  520 +--
 .../src/solr-cores-and-solr-xml.adoc            |    2 +-
 .../src/solr-jdbc-apache-zeppelin.adoc          |    2 +-
 solr/solr-ref-guide/src/spatial-search.adoc     |  150 +-
 solr/solr-ref-guide/src/spell-checking.adoc     |   40 +-
 solr/solr-ref-guide/src/stream-decorators.adoc  |  392 ++-
 solr/solr-ref-guide/src/stream-evaluators.adoc  |  137 +-
 solr/solr-ref-guide/src/stream-sources.adoc     |  131 +-
 .../src/taking-solr-to-production.adoc          |   20 +-
 .../src/the-dismax-query-parser.adoc            |   38 +-
 .../src/the-extended-dismax-query-parser.adoc   |   30 +-
 .../src/the-query-elevation-component.adoc      |   31 +-
 .../src/the-standard-query-parser.adoc          |   14 +-
 .../solr-ref-guide/src/the-stats-component.adoc |   75 +-
 .../src/the-term-vector-component.adoc          |   55 +-
 .../solr-ref-guide/src/the-terms-component.adoc |  117 +-
 .../src/transforming-result-documents.adoc      |   31 +-
 ...anding-analyzers-tokenizers-and-filters.adoc |    8 +-
 .../src/update-request-processors.adoc          |   24 +-
 .../src/updatehandlers-in-solrconfig.adoc       |   62 +-
 .../src/updating-parts-of-documents.adoc        |   56 +-
 solr/solr-ref-guide/src/upgrading-solr.adoc     |    2 +-
 .../src/uploading-data-with-index-handlers.adoc |  130 +-
 ...g-data-with-solr-cell-using-apache-tika.adoc |  125 +-
 ...store-data-with-the-data-import-handler.adoc |    4 +-
 solr/solr-ref-guide/src/using-solrj.adoc        |   14 +-
 ...zookeeper-to-manage-configuration-files.adoc |    4 +-
 solr/solr-ref-guide/src/v2-api.adoc             |   24 +-
 .../src/velocity-response-writer.adoc           |   99 +-
 ...king-with-currencies-and-exchange-rates.adoc |   34 +-
 solr/solr-ref-guide/src/working-with-dates.adoc |   11 +-
 .../src/working-with-enum-fields.adoc           |    6 +-
 ...rking-with-external-files-and-processes.adoc |   30 +-
 .../src/zookeeper-access-control.adoc           |   21 +-
 .../apache/solr/client/solrj/SolrRequest.java   |   18 +
 .../solr/client/solrj/V2RequestSupport.java     |   30 +
 .../cloud/autoscaling/AddReplicaSuggester.java  |   69 +
 .../client/solrj/cloud/autoscaling/Cell.java    |   69 +
 .../client/solrj/cloud/autoscaling/Clause.java  |  472 +++
 .../cloud/autoscaling/ClusterDataProvider.java  |   52 +
 .../cloud/autoscaling/MoveReplicaSuggester.java |   83 +
 .../client/solrj/cloud/autoscaling/Operand.java |  123 +
 .../client/solrj/cloud/autoscaling/Policy.java  |  521 +++
 .../solrj/cloud/autoscaling/PolicyHelper.java   |   96 +
 .../solrj/cloud/autoscaling/Preference.java     |   89 +
 .../client/solrj/cloud/autoscaling/Row.java     |  120 +
 .../solrj/cloud/autoscaling/package-info.java   |   23 +
 .../solr/client/solrj/impl/CloudSolrClient.java |  120 +-
 .../solrj/impl/ConcurrentUpdateSolrClient.java  |   81 +-
 .../impl/DelegationTokenHttpSolrClient.java     |   13 +
 .../solr/client/solrj/impl/HttpSolrClient.java  |  217 +-
 .../client/solrj/impl/LBHttpSolrClient.java     |  101 +-
 .../solrj/impl/SolrClientDataProvider.java      |  256 ++
 .../impl/StreamingBinaryResponseParser.java     |    5 +-
 .../impl/ZkClientClusterStateProvider.java      |   11 +-
 .../client/solrj/io/eval/AnovaEvaluator.java    |    6 +
 .../client/solrj/io/eval/ArrayEvaluator.java    |   53 +-
 .../client/solrj/io/eval/ComplexEvaluator.java  |   18 +-
 .../solrj/io/eval/ConvolutionEvaluator.java     |    6 +
 .../solrj/io/eval/CorrelationEvaluator.java     |    6 +
 .../solrj/io/eval/CovarianceEvaluator.java      |    6 +
 .../io/eval/CumulativeProbabilityEvaluator.java |   67 +
 .../client/solrj/io/eval/DescribeEvaluator.java |   10 +-
 .../client/solrj/io/eval/DistanceEvaluator.java |    7 +
 .../io/eval/EmpiricalDistributionEvaluator.java |    9 +-
 .../solrj/io/eval/FindDelayEvaluator.java       |    6 +
 .../solrj/io/eval/HistogramEvaluator.java       |    7 +-
 .../client/solrj/io/eval/LengthEvaluator.java   |   23 +-
 .../solrj/io/eval/MovingAverageEvaluator.java   |    6 +
 .../solrj/io/eval/PercentileEvaluator.java      |   25 +-
 .../client/solrj/io/eval/PredictEvaluator.java  |   10 +-
 .../client/solrj/io/eval/RankEvaluator.java     |    7 +
 .../solrj/io/eval/RegressionEvaluator.java      |   10 +-
 .../client/solrj/io/eval/ReverseEvaluator.java  |    7 +
 .../client/solrj/io/eval/ScaleEvaluator.java    |    7 +
 .../client/solrj/io/eval/SequenceEvaluator.java |    7 +
 .../solrj/io/stream/CartesianProductStream.java |   12 +-
 .../client/solrj/io/stream/FacetStream.java     |    3 +
 .../solr/client/solrj/io/stream/LetStream.java  |    4 +-
 .../solr/client/solrj/io/stream/TupStream.java  |    3 +-
 .../solrj/request/CollectionAdminRequest.java   |   29 +-
 .../solrj/request/CollectionApiMapping.java     |   14 +
 .../request/JavaBinUpdateRequestCodec.java      |   12 +-
 .../client/solrj/request/V1toV2ApiMapper.java   |  144 +
 .../solr/client/solrj/request/V2Request.java    |   59 +-
 .../solrj/response/SpellCheckResponse.java      |    2 +-
 .../solr/client/solrj/response/V2Response.java  |   22 +
 .../org/apache/solr/common/IteratorWriter.java  |   21 +-
 .../java/org/apache/solr/common/MapWriter.java  |   10 +
 .../org/apache/solr/common/SpecProvider.java    |   25 +
 .../apache/solr/common/cloud/DocCollection.java |   14 +
 .../solr/common/cloud/ZkConfigManager.java      |    2 +-
 .../apache/solr/common/cloud/ZkStateReader.java |    1 +
 .../solr/common/cloud/rule/ImplicitSnitch.java  |   53 +-
 .../apache/solr/common/cloud/rule/Snitch.java   |    6 +-
 .../solr/common/cloud/rule/SnitchContext.java   |    7 +-
 .../apache/solr/common/params/CommonParams.java |   11 +-
 .../common/params/ModifiableSolrParams.java     |    4 +
 .../solr/common/params/MoreLikeThisParams.java  |    4 +-
 .../solr/common/util/CommandOperation.java      |  100 +-
 .../solr/common/util/ContentStreamBase.java     |    7 +-
 .../apache/solr/common/util/JavaBinCodec.java   |   44 +-
 .../solr/common/util/JsonSchemaValidator.java   |  298 ++
 .../org/apache/solr/common/util/PathTrie.java   |  195 ++
 .../org/apache/solr/common/util/Template.java   |   66 +
 .../java/org/apache/solr/common/util/Utils.java |  224 +-
 .../solr/common/util/ValidatingJsonMap.java     |    2 +-
 .../resources/apispec/autoscaling.Commands.json |   47 +
 .../src/resources/apispec/cluster.Commands.json |   74 +
 .../src/resources/apispec/cluster.aliases.json  |   12 +
 .../apispec/cluster.commandstatus.delete.json   |   10 +
 .../apispec/cluster.commandstatus.json          |   20 +
 .../apispec/cluster.configs.Commands.json       |   34 +
 .../apispec/cluster.configs.delete.json         |   12 +
 .../src/resources/apispec/cluster.configs.json  |   12 +
 solr/solrj/src/resources/apispec/cluster.json   |   14 +
 .../src/resources/apispec/cluster.nodes.json    |   12 +
 .../cluster.security.BasicAuth.Commands.json    |   23 +
 ...cluster.security.RuleBasedAuthorization.json |  129 +
 ...luster.security.authentication.Commands.json |   12 +
 .../cluster.security.authentication.json        |   12 +
 ...cluster.security.authorization.Commands.json |   13 +
 .../apispec/cluster.security.authorization.json |   13 +
 .../resources/apispec/collections.Commands.json |  218 ++
 .../collections.collection.Commands.json        |  137 +
 .../collections.collection.Commands.modify.json |   36 +
 .../collections.collection.Commands.reload.json |   11 +
 .../apispec/collections.collection.delete.json  |   13 +
 .../apispec/collections.collection.json         |   19 +
 .../collections.collection.shards.Commands.json |  114 +
 ...ctions.collection.shards.shard.Commands.json |   24 +
 ...lections.collection.shards.shard.delete.json |   27 +
 ....collection.shards.shard.replica.delete.json |   39 +
 .../src/resources/apispec/collections.json      |   13 +
 .../src/resources/apispec/core.RealtimeGet.json |   26 +
 .../apispec/core.SchemaEdit.addCopyField.json   |   27 +
 .../apispec/core.SchemaEdit.addField.json       |   98 +
 .../core.SchemaEdit.addFieldType.analyzers.json |   51 +
 .../apispec/core.SchemaEdit.addFieldType.json   |   53 +
 .../core.SchemaEdit.deleteCopyField.json        |   19 +
 .../core.SchemaEdit.deleteDynamicField.json     |   12 +
 .../apispec/core.SchemaEdit.deleteField.json    |   12 +
 .../core.SchemaEdit.deleteFieldType.json        |   14 +
 .../src/resources/apispec/core.SchemaEdit.json  |   47 +
 .../apispec/core.SchemaRead.copyFields.json     |   26 +
 ...ore.SchemaRead.dynamicFields_fieldTypes.json |   20 +
 .../apispec/core.SchemaRead.fields.json         |   34 +
 .../src/resources/apispec/core.SchemaRead.json  |   17 +
 .../src/resources/apispec/core.Update.json      |   17 +
 ...g.Commands.addRequestHandler.properties.json |   25 +
 .../apispec/core.config.Commands.generic.json   |   19 +
 .../resources/apispec/core.config.Commands.json |  215 ++
 .../core.config.Commands.runtimeLib.json        |   23 +
 .../apispec/core.config.Params.Commands.json    |   31 +
 .../resources/apispec/core.config.Params.json   |   13 +
 .../src/resources/apispec/core.config.json      |   18 +
 .../src/resources/apispec/core.system.blob.json |   20 +
 .../apispec/core.system.blob.upload.json        |   12 +
 .../src/resources/apispec/cores.Commands.json   |   85 +
 .../src/resources/apispec/cores.Status.json     |   20 +
 .../resources/apispec/cores.core.Commands.json  |  136 +
 .../apispec/cores.core.Commands.split.json      |   34 +
 solr/solrj/src/resources/apispec/emptySpec.json |   11 +
 .../src/resources/apispec/node.Commands.json    |   24 +
 solr/solrj/src/resources/apispec/node.Info.json |   11 +
 .../src/resources/apispec/node.invoke.json      |   16 +
 .../collection1/conf/schema-replication1.xml    |    4 +-
 .../solrj/solr/collection1/conf/schema-sql.xml  |   22 +-
 .../solrj/solr/collection1/conf/schema.xml      |   22 +-
 .../solr/collection1/conf/solrconfig-slave1.xml |   11 +-
 .../solr/collection1/conf/solrconfig-sql.xml    |    6 +-
 .../solrj/solr/collection1/conf/solrconfig.xml  |    6 +-
 .../solrj/solr/configsets/ml/conf/schema.xml    |   20 +-
 .../solr/configsets/ml/conf/solrconfig.xml      |    6 +-
 .../solr/configsets/shared/conf/schema.xml      |    2 +-
 .../solr/configsets/shared/conf/solrconfig.xml  |   10 +-
 .../solr/configsets/streaming/conf/schema.xml   |   20 +-
 .../configsets/streaming/conf/solrconfig.xml    |    8 +-
 .../solrj/solr/crazy-path-to-schema.xml         |    4 +-
 .../solrj/solr/multicore/core0/conf/schema.xml  |    2 +-
 .../solr/multicore/core0/conf/solrconfig.xml    |   10 +-
 .../solrj/solr/multicore/core1/conf/schema.xml  |    2 +-
 .../solr/multicore/core1/conf/solrconfig.xml    |   10 +-
 .../client/solrj/SolrSchemalessExampleTest.java |    2 +-
 .../solrj/cloud/autoscaling/TestPolicy.java     |  654 ++++
 .../embedded/SolrExampleStreamingTest.java      |   64 +-
 .../solrj/impl/BasicHttpSolrClientTest.java     |   16 -
 .../client/solrj/impl/CloudSolrClientTest.java  |    2 +-
 .../impl/ConcurrentUpdateSolrClientTest.java    |   36 +-
 .../client/solrj/impl/LBHttpSolrClientTest.java |    2 +-
 .../client/solrj/io/stream/JDBCStreamTest.java  |    2 +
 .../solrj/io/stream/StreamExpressionTest.java   |  107 +-
 .../io/stream/eval/ArrayEvaluatorTest.java      |  155 +
 .../io/stream/eval/LengthEvaluatorTest.java     |  119 +
 .../solr/client/solrj/request/SchemaTest.java   |   23 +-
 .../solrj/request/TestV1toV2ApiMapper.java      |   55 +
 .../solr/common/util/JsonValidatorTest.java     |  192 ++
 .../solr/common/util/TestJavaBinCodec.java      |   95 +-
 .../solr/common/util/TestNamedListCodec.java    |   57 +-
 .../apache/solr/common/util/TestPathTrie.java   |   61 +
 .../solr/BaseDistributedSearchTestCase.java     |   15 +-
 .../java/org/apache/solr/SolrTestCaseJ4.java    |  206 +-
 .../solr/cloud/AbstractDistribZkTestBase.java   |   18 +-
 .../cloud/AbstractFullDistribZkTestBase.java    |  179 +-
 .../apache/solr/cloud/AbstractZkTestCase.java   |    6 +-
 .../solr/cloud/StoppableCommitThread.java       |    2 +-
 .../org/apache/solr/util/ExternalPaths.java     |    6 +-
 .../org/apache/solr/util/SSLTestConfig.java     |   58 +-
 solr/webapp/web/js/angular/controllers/query.js |    2 +-
 .../web/js/angular/controllers/replication.js   |    6 +-
 1749 files changed, 79172 insertions(+), 47740 deletions(-)
----------------------------------------------------------------------



[23/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-6807: requestDispatcher/@handleSelect now defaults to false; stop using it. Deprecated StandardRequestHandler; stop using it.

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-hash.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-hash.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-hash.xml
index 94cceb61..cad70d8 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-hash.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-hash.xml
@@ -46,11 +46,11 @@
     </lst>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
   </requestDispatcher>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <!-- config for the admin interface -->
   <admin>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-headers.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-headers.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-headers.xml
index f7b4940..328fc9b 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-headers.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-headers.xml
@@ -24,7 +24,7 @@
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
   <searchComponent name="componentThatAddsHeader" class="org.apache.solr.servlet.ResponseHeaderTest$ComponentThatAddsHeader"/>
-  <requestHandler name="/withHeaders" class="solr.StandardRequestHandler">
+  <requestHandler name="/withHeaders" class="solr.SearchHandler">
     <arr name="first-components">
       <str>componentThatAddsHeader</str>
     </arr>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-highlight.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-highlight.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-highlight.xml
index 577f182..c714a41 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-highlight.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-highlight.xml
@@ -31,7 +31,7 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"/>
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
   <searchComponent class="solr.HighlightComponent" name="highlight">
     <highlighting class="org.apache.solr.highlight.DummyHighlighter">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-implicitproperties.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-implicitproperties.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-implicitproperties.xml
index d87d364..5ef9d72 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-implicitproperties.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-implicitproperties.xml
@@ -49,7 +49,7 @@
 
   </query>
 
-  <requestDispatcher handleSelect="false">
+  <requestDispatcher>
     <httpCaching never304="true"/>
   </requestDispatcher>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-infixsuggesters.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-infixsuggesters.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-infixsuggesters.xml
index 8fc42ff..a30186d 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-infixsuggesters.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-infixsuggesters.xml
@@ -25,7 +25,7 @@
 
   <updateHandler class="solr.DirectUpdateHandler2"/>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <searchComponent class="solr.SuggestComponent" name="analyzing_infix_suggester_random_short_dictionary">
     <lst name="suggester">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-logmergepolicyfactory.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-logmergepolicyfactory.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-logmergepolicyfactory.xml
index 27a1867..539fd5c 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-logmergepolicyfactory.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-logmergepolicyfactory.xml
@@ -32,6 +32,6 @@
     </mergePolicyFactory>
   </indexConfig>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema-test.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema-test.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema-test.xml
index 22aeeda..666132f 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema-test.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema-test.xml
@@ -23,5 +23,5 @@
   <dataDir>${solr.data.dir:}</dataDir>
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml
index 146b154..739ad22 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml
@@ -60,7 +60,7 @@
     </updateLog> 
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
@@ -72,7 +72,7 @@
     </lst>
   </requestHandler>
 
-  <initParams path="standard">
+  <initParams path="/select">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-master-throttled.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master-throttled.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master-throttled.xml
index 516d504..4a53776 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master-throttled.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master-throttled.xml
@@ -28,7 +28,7 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
@@ -39,7 +39,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -48,7 +48,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -56,7 +56,7 @@
     </lst>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1"/>
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-master.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master.xml
index b1345ac..e501af2 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master.xml
@@ -28,7 +28,7 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
@@ -43,7 +43,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -52,7 +52,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -60,7 +60,7 @@
     </lst>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1"/>
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-master1-keepOneBackup.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master1-keepOneBackup.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master1-keepOneBackup.xml
index 69f7659..bcd7874 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master1-keepOneBackup.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master1-keepOneBackup.xml
@@ -27,7 +27,7 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <requestHandler name="/replication" class="solr.ReplicationHandler">
     <lst name="master">
@@ -39,7 +39,7 @@
   </requestHandler>
   
 
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1"/>
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-master1.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master1.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master1.xml
index db39b1f..9271686 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master1.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master1.xml
@@ -28,7 +28,7 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
@@ -41,7 +41,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -50,7 +50,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -58,7 +58,7 @@
     </lst>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1"/>
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-master2.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master2.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master2.xml
index 91923c9..55301c2 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master2.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master2.xml
@@ -27,7 +27,7 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
@@ -39,7 +39,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -48,7 +48,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -56,7 +56,7 @@
     </lst>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1"/>
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-master3.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master3.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master3.xml
index b03aef4..1c1dd40 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master3.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master3.xml
@@ -27,7 +27,7 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
@@ -40,7 +40,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -49,7 +49,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -57,7 +57,7 @@
     </lst>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1"/>
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicy-defaults.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicy-defaults.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicy-defaults.xml
index aaf8593..3e0cf19 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicy-defaults.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicy-defaults.xml
@@ -28,6 +28,6 @@
     -->
   </indexConfig>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicy-legacy.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicy-legacy.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicy-legacy.xml
index a7361cc..b67d664 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicy-legacy.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicy-legacy.xml
@@ -26,6 +26,6 @@
     <useCompoundFile>${useCompoundFile:false}</useCompoundFile>
   </indexConfig>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicyfactory-nocfs.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicyfactory-nocfs.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicyfactory-nocfs.xml
index 4dd82d7..b93fabd 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicyfactory-nocfs.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-mergepolicyfactory-nocfs.xml
@@ -29,6 +29,6 @@
     </mergePolicyFactory>
   </indexConfig>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-nocache.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-nocache.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-nocache.xml
index 15e58af..137c519 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-nocache.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-nocache.xml
@@ -31,15 +31,15 @@
 
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
-  
-  <requestHandler name="standard" class="solr.StandardRequestHandler"/>
 
-  <requestDispatcher handleSelect="true" >
+  <requestHandler name="/select" class="solr.SearchHandler" />
+
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     <httpCaching never304="true" />
   </requestDispatcher>
 
-  <initParams path="standard">
+  <initParams path="/select">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-nomergepolicyfactory.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-nomergepolicyfactory.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-nomergepolicyfactory.xml
index a9e3801..62fb05b 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-nomergepolicyfactory.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-nomergepolicyfactory.xml
@@ -27,6 +27,6 @@
     <mergePolicyFactory class="org.apache.solr.index.NoMergePolicyFactory" />
   </indexConfig>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-noopregen.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-noopregen.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-noopregen.xml
index 1f54630..a3cd7b6 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-noopregen.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-noopregen.xml
@@ -24,7 +24,7 @@
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
   <query>
     <cache name="myPerSegmentCache" 
            class="solr.LRUCache"

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-paramset.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-paramset.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-paramset.xml
index c006ce7..7eefc9d 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-paramset.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-paramset.xml
@@ -25,7 +25,7 @@
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"/>
+  <requestHandler name="/select" class="solr.SearchHandler"/>
   <initParams name="a" path="/dump3,/dump6,/root/*,/root1/**">
     <lst name="defaults">
       <str name="a">A</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml
index f83df6c..5930d37 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-parsing-update-processor-chains.xml
@@ -23,7 +23,7 @@
   -->
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-phrasesuggest.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-phrasesuggest.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-phrasesuggest.xml
index 4507666..0f79d7c 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-phrasesuggest.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-phrasesuggest.xml
@@ -24,7 +24,7 @@
   <dataDir>${solr.data.dir:}</dataDir>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   
   <!-- WFSTLookup suggest component -->
   <searchComponent class="solr.SpellCheckComponent" name="suggest_wfst">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-plugcollector.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-plugcollector.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-plugcollector.xml
index 09f0974..431447c 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-plugcollector.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-plugcollector.xml
@@ -190,12 +190,12 @@ based HashBitset. -->
       The "standard" request handler is the default and will be used if qt
      is not specified in the request.
   -->
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
 
-  <requestHandler name="dismax" class="solr.SearchHandler" >
+  <requestHandler name="/dismax" class="solr.SearchHandler" >
     <lst name="defaults">
       <str name="defType">dismax</str>
       <str name="q.alt">*:*</str>
@@ -216,10 +216,10 @@ based HashBitset. -->
     </lst>
   </requestHandler>
 
-  <requestHandler name="mock" class="org.apache.solr.core.MockQuerySenderListenerReqHandler"/>
+  <requestHandler name="/mock" class="org.apache.solr.core.MockQuerySenderListenerReqHandler"/>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -228,7 +228,7 @@ based HashBitset. -->
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -322,7 +322,7 @@ based HashBitset. -->
    -->
   <queryConverter name="queryConverter" class="org.apache.solr.spelling.SpellingQueryConverter"/>
 
-  <requestHandler name="spellCheckCompRH" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckCompRH" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <!-- omp = Only More Popular -->
       <str name="spellcheck.onlyMorePopular">false</str>
@@ -335,7 +335,7 @@ based HashBitset. -->
       <str>spellcheck</str>
     </arr>
   </requestHandler>
-  <requestHandler name="spellCheckCompRH_Direct" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckCompRH_Direct" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <str name="spellcheck.dictionary">direct</str>
       <str name="spellcheck.onlyMorePopular">false</str>
@@ -346,7 +346,7 @@ based HashBitset. -->
       <str>spellcheck</str>
     </arr>
   </requestHandler>
-  <requestHandler name="spellCheckWithWordbreak" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckWithWordbreak" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <str name="spellcheck.dictionary">default</str>
       <str name="spellcheck.dictionary">wordbreak</str>
@@ -356,7 +356,7 @@ based HashBitset. -->
       <str>spellcheck</str>
     </arr>
   </requestHandler>
-  <requestHandler name="spellCheckWithWordbreak_Direct" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckWithWordbreak_Direct" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <str name="spellcheck.dictionary">direct</str>
       <str name="spellcheck.dictionary">wordbreak</str>
@@ -366,7 +366,7 @@ based HashBitset. -->
       <str>spellcheck</str>
     </arr>
   </requestHandler>
-  <requestHandler name="spellCheckCompRH1" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckCompRH1" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <str name="defType">dismax</str>
       <str name="qf">lowerfilt1^1</str>
@@ -376,13 +376,13 @@ based HashBitset. -->
     </arr>
   </requestHandler>
 
-  <requestHandler name="mltrh" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/mltrh" class="org.apache.solr.handler.component.SearchHandler">
 
   </requestHandler>
 
   <searchComponent name="tvComponent" class="org.apache.solr.handler.component.TermVectorComponent"/>
 
-  <requestHandler name="tvrh" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/tvrh" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
 
     </lst>
@@ -458,7 +458,7 @@ based HashBitset. -->
     </highlighting>
   </searchComponent>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>
@@ -549,7 +549,7 @@ based HashBitset. -->
     <processor class="solr.RunUpdateProcessorFactory" />
   </updateRequestProcessorChain>
 
-  <initParams path="standard,dismax,defaults,lazy,spellCheckCompRH,spellCheckWithWordbreak,spellCheckCompRH_Direct,spellCheckCompRH1,mltrh,tvrh,/terms">
+  <initParams path="/select,/dismax,/defaults,/lazy,/spellCheckCompRH,/spellCheckWithWordbreak,/spellCheckCompRH_Direct,/spellCheckCompRH1,/mltrh,/tvrh,/terms">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-postingshighlight.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-postingshighlight.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-postingshighlight.xml
index 9db6205..a578563 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-postingshighlight.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-postingshighlight.xml
@@ -24,7 +24,7 @@
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <lst name="defaults">
       <bool name="hl.defaultSummary">false</bool>
       <str name="df">text</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-query-parser-init.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-query-parser-init.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-query-parser-init.xml
index 24c2ea8..eb538fa 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-query-parser-init.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-query-parser-init.xml
@@ -23,7 +23,7 @@
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
   <!-- query parser without final NAME field lead to NPE during query parser initialization-->

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-querysender-noquery.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-querysender-noquery.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-querysender-noquery.xml
index 0945be2..9d4f83d 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-querysender-noquery.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-querysender-noquery.xml
@@ -68,7 +68,7 @@
 
   
   </query>
-  <requestHandler name="mock" class="org.apache.solr.core.MockQuerySenderListenerReqHandler" default="true">
+  <requestHandler name="/mock" class="org.apache.solr.core.MockQuerySenderListenerReqHandler" default="true">
     <!-- default values for query parameters -->
 
   </requestHandler>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-querysender.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-querysender.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-querysender.xml
index 7f7bf18..1404f8a 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-querysender.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-querysender.xml
@@ -42,8 +42,8 @@
          local query request for each NamedList in sequence. -->
     <listener event="newSearcher" class="solr.QuerySenderListener">
       <arr name="queries">
-        <lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> <str name="qt">mock</str></lst>
-        <lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> <str name="qt">mock</str></lst>
+        <lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> <str name="qt">/mock</str></lst>
+        <lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> <str name="qt">/mock</str></lst>
       </arr>
     </listener>
     <listener event="newSearcher"
@@ -55,7 +55,7 @@
     <listener event="firstSearcher" class="solr.QuerySenderListener">
       <arr name="queries">
         <lst> <str name="q">fast_warm</str> <str name="start">0</str> <str name="rows">10</str>
-          <str name="qt">mock</str>
+          <str name="qt">/mock</str>
         </lst>
       </arr>
     </listener>
@@ -64,7 +64,7 @@
 
   
   </query>
-  <requestHandler name="mock" class="org.apache.solr.core.MockQuerySenderListenerReqHandler" default="true">
+  <requestHandler name="/mock" class="org.apache.solr.core.MockQuerySenderListenerReqHandler" default="true">
     <!-- default values for query parameters -->
 
   </requestHandler>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-repeater.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-repeater.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-repeater.xml
index 76c379c..761d45d 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-repeater.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-repeater.xml
@@ -28,17 +28,17 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
 
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
   </requestHandler>
 
   <requestHandler name="/replication" class="solr.ReplicationHandler">
@@ -51,7 +51,7 @@
     </lst>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1"/>
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-reqHandler.incl
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-reqHandler.incl b/solr/core/src/test-files/solr/collection1/conf/solrconfig-reqHandler.incl
index 03f236f..cc97504 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-reqHandler.incl
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-reqHandler.incl
@@ -1,5 +1,5 @@
 
-  <requestHandler name="includedHandler"
+  <requestHandler name="/includedHandler"
                   class="solr.SearchHandler" >
   </requestHandler>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-response-log-component.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-response-log-component.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-response-log-component.xml
index f89b187..643d9a6 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-response-log-component.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-response-log-component.xml
@@ -20,8 +20,8 @@
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-  <requestHandler name="standard"
-     class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select"
+     class="solr.SearchHandler"></requestHandler>
 
   <!-- Used to specify an alternate directory to hold all index data.
        It defaults to "index" if not present, and should probably
@@ -37,22 +37,22 @@
   <searchComponent name="responselog" class="org.apache.solr.handler.component.ResponseLogComponent" />
 
   <!-- Log retrievedDocs -->
-  <requestHandler name="withlog" class="org.apache.solr.handler.component.SearchHandler">
-  <lst name="defaults">
-    <str name="defType">dismax</str>
-  </lst>
+  <requestHandler name="/withlog" class="org.apache.solr.handler.component.SearchHandler">
+    <lst name="defaults">
+      <str name="defType">dismax</str>
+    </lst>
     <arr name="last-components">
       <str>responselog</str>
     </arr>
   </requestHandler>
   
-  <requestHandler name="nolog" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/nolog" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <str name="defType">dismax</str>
     </lst>
   </requestHandler>
 
-  <initParams path="withlog,nolog">
+  <initParams path="/withlog,/nolog">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-schemaless.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-schemaless.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-schemaless.xml
index ac8321b..04ba1f2 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-schemaless.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-schemaless.xml
@@ -35,7 +35,7 @@
     </updateLog>
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-script-updateprocessor.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-script-updateprocessor.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-script-updateprocessor.xml
index 8fa8dcf..f87385e 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-script-updateprocessor.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-script-updateprocessor.xml
@@ -24,7 +24,7 @@
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-searcher-listeners1.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-searcher-listeners1.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-searcher-listeners1.xml
index 73fb42a..c71f8ba 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-searcher-listeners1.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-searcher-listeners1.xml
@@ -41,7 +41,7 @@
   <queryResponseWriter name="xml" default="true"
                        class="solr.XMLResponseWriter" />
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"/>
+  <requestHandler name="/select" class="solr.SearchHandler"/>
   
   <searchComponent name="mock" class="org.apache.solr.search.TestIndexSearcher$MockSearchComponent"/>
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-slave.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-slave.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-slave.xml
index 5ca7184..39a7870 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-slave.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-slave.xml
@@ -28,17 +28,17 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
 
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
   </requestHandler>
 
   <requestHandler name="/replication" class="solr.ReplicationHandler">
@@ -49,7 +49,7 @@
     </lst>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1"/>
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-slave1.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-slave1.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-slave1.xml
index aa2f8a4..26821b4 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-slave1.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-slave1.xml
@@ -28,21 +28,21 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
 
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
   </requestHandler>
 
 
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1"/>
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-solcoreproperties.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-solcoreproperties.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-solcoreproperties.xml
index 4278d67..fc707d4 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-solcoreproperties.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-solcoreproperties.xml
@@ -26,7 +26,7 @@
 
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
-  <requestHandler name="/select" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <lst name="defaults">
       <str name="p1">${foo.foo1}</str>
       <str name="p2">${foo.foo2}</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingmergepolicyfactory.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingmergepolicyfactory.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingmergepolicyfactory.xml
index a7a8358..17e6f4c 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingmergepolicyfactory.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingmergepolicyfactory.xml
@@ -31,7 +31,7 @@
     <lockType>${solr.tests.lockType:single}</lockType>
   </indexConfig>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <updateHandler class="solr.DirectUpdateHandler2">
     <updateLog>
@@ -47,7 +47,7 @@
       <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime>
     </autoSoftCommit>
   </updateHandler>
-  <initParams path="standard">
+  <initParams path="/select">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingresponse.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingresponse.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingresponse.xml
index 35ad58b..efb9eea 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingresponse.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-sortingresponse.xml
@@ -25,7 +25,7 @@
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <query>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
index 243eb5e..646a9eb 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spatial.xml
@@ -24,7 +24,7 @@
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
   <query>
     <cache name="perSegSpatialFieldCache_srptgeom"
            class="solr.LRUCache"

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-spellcheckcomponent.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spellcheckcomponent.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spellcheckcomponent.xml
index cf923c4..7760eb2 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spellcheckcomponent.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spellcheckcomponent.xml
@@ -33,8 +33,8 @@
       <maxWarmingSearchers>1</maxWarmingSearchers>
     </query>
   </indexConfig>
-  <requestHandler name="standard"
-     class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select"
+     class="solr.SearchHandler"></requestHandler>
 
   <!-- Used to specify an alternate directory to hold all index data.
        It defaults to "index" if not present, and should probably
@@ -156,7 +156,7 @@
    -->
   <queryConverter name="queryConverter" class="org.apache.solr.spelling.SpellingQueryConverter"/>
 
-  <requestHandler name="spellCheckCompRH" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckCompRH" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <!-- omp = Only More Popular -->
       <str name="spellcheck.onlyMorePopular">false</str>
@@ -169,7 +169,7 @@
       <str>spellcheck</str>
     </arr>
   </requestHandler>
-  <requestHandler name="spellCheckCompRH1" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckCompRH1" class="org.apache.solr.handler.component.SearchHandler">
       <lst name="defaults">
         <str name="defType">dismax</str>
         <str name="qf">lowerfilt1^1</str>
@@ -178,7 +178,7 @@
         <str>spellcheck</str>
       </arr>
  </requestHandler>
- <requestHandler name="spellCheckWithWordbreak" class="org.apache.solr.handler.component.SearchHandler">
+ <requestHandler name="/spellCheckWithWordbreak" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <str name="spellcheck.dictionary">default</str>
       <str name="spellcheck.dictionary">wordbreak</str>
@@ -188,7 +188,7 @@
       <str>spellcheck</str>
     </arr>
   </requestHandler>
-  <initParams path="spellCheckCompRH,spellCheckCompRH1,spellCheckWithWordbreak">
+  <initParams path="/spellCheckCompRH,/spellCheckCompRH1,/spellCheckWithWordbreak">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-spellchecker.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spellchecker.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spellchecker.xml
index 3b0aff6..a876fb6 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-spellchecker.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-spellchecker.xml
@@ -29,7 +29,7 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <!-- Suggest component -->
   <searchComponent class="solr.SpellCheckComponent" name="suggest_jaspell">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-sql.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-sql.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-sql.xml
index 6a0c5b5..8ec6489 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-sql.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-sql.xml
@@ -44,13 +44,13 @@
     </lst>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
   </requestDispatcher>
 
   <requestHandler name="/replication" class="solr.ReplicationHandler" startup="lazy" />
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
   <requestHandler name="/update" class="solr.UpdateRequestHandler"  />
 
   <requestHandler name="/admin/ping" class="solr.PingRequestHandler">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-suggestercomponent-context-filter-query.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-suggestercomponent-context-filter-query.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-suggestercomponent-context-filter-query.xml
index 394b25e..36b6755 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-suggestercomponent-context-filter-query.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-suggestercomponent-context-filter-query.xml
@@ -27,7 +27,7 @@
 
   <updateHandler class="solr.DirectUpdateHandler2"/>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <searchComponent class="solr.SuggestComponent" name="suggest">
     <!--Suggest Component for context filtering test -->

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-suggestercomponent.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-suggestercomponent.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-suggestercomponent.xml
index 661913c..857fb11 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-suggestercomponent.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-suggestercomponent.xml
@@ -28,7 +28,7 @@
 
   <updateHandler class="solr.DirectUpdateHandler2"/>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <searchComponent class="solr.SuggestComponent" name="suggest">
     

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-test-misc.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-test-misc.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-test-misc.xml
index 3dba272..dc7bb66 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-test-misc.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-test-misc.xml
@@ -45,8 +45,8 @@
             attr2="${non.existent.sys.prop:default-from-config}">prefix-${solr.test.sys.prop2}-suffix</propTest>
 
   <!-- see TestConfig.testDisableRequetsHandler -->
-  <requestHandler name="disabled" class="solr.StandardRequestHandler" enable="false"/>
-  <requestHandler name="enabled" class="solr.StandardRequestHandler" enable="true"/>
+  <requestHandler name="/disabled" class="solr.SearchHandler" enable="false"/>
+  <requestHandler name="/enabled" class="solr.SearchHandler" enable="true"/>
 
 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-testxmlparser.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-testxmlparser.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-testxmlparser.xml
index 40c39a1..401710e 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-testxmlparser.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-testxmlparser.xml
@@ -24,7 +24,7 @@
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
   <queryParser name="testxmlparser" class="XmlQParserPlugin">
     <str name="HandyQuery">org.apache.solr.search.HandyQueryBuilder</str>
     <str name="HelloQuery">org.apache.solr.search.HelloQueryBuilder</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-tieredmergepolicyfactory.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-tieredmergepolicyfactory.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-tieredmergepolicyfactory.xml
index af5d208..4a58100 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-tieredmergepolicyfactory.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-tieredmergepolicyfactory.xml
@@ -36,6 +36,6 @@
     </mergeScheduler>
   </indexConfig>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-tlog.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-tlog.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-tlog.xml
index cf12c4a..12e5089 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-tlog.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-tlog.xml
@@ -44,8 +44,7 @@
    <processor class="solr.RunUpdateProcessorFactory" />
  </updateRequestProcessorChain>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
-  </requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler" />
   
   <peerSync>
     <useRangeVersions>${solr.peerSync.useRangeVersions:true}</useRangeVersions>
@@ -158,7 +157,7 @@
 
   </query>
 
-  <initParams path="standard">
+  <initParams path="/select">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-uninvertdocvaluesmergepolicyfactory.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-uninvertdocvaluesmergepolicyfactory.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-uninvertdocvaluesmergepolicyfactory.xml
index 613357b..5f15430 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-uninvertdocvaluesmergepolicyfactory.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-uninvertdocvaluesmergepolicyfactory.xml
@@ -33,6 +33,6 @@
     <mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>
   </indexConfig>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-update-processor-chains.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-update-processor-chains.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-update-processor-chains.xml
index 426f3c0..4113bd1 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-update-processor-chains.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-update-processor-chains.xml
@@ -25,7 +25,7 @@
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <requestHandler name="/update" class="solr.UpdateRequestHandler"  />
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-warmer-randommergepolicyfactory.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-warmer-randommergepolicyfactory.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-warmer-randommergepolicyfactory.xml
index 1e1936b..21101b1 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-warmer-randommergepolicyfactory.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-warmer-randommergepolicyfactory.xml
@@ -24,7 +24,7 @@
   <dataDir>${solr.data.dir:}</dataDir>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   
   <indexConfig>
     <!-- we don't use solrconfig.snippet.randomindexconfig.xml here

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml
index 7466d01..41726ce 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig.xml
@@ -200,17 +200,13 @@
        If the set cardinality <= maxSize elements, then HashDocSet will be used instead of the bitset
        based HashBitset. -->
 
-  <!-- requestHandler plugins... incoming queries will be dispatched to the
-     correct handler based on the 'qt' param matching the
-     name of registered handlers.
-      The "standard" request handler is the default and will be used if qt
-     is not specified in the request.
+  <!-- requestHandler plugins
   -->
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
-  <requestHandler name="dismax" class="solr.SearchHandler" >
+  <requestHandler name="/dismax" class="solr.SearchHandler" >
     <lst name="defaults">
      <str name="defType">dismax</str>
      <str name="q.alt">*:*</str>
@@ -231,10 +227,10 @@
     </lst>
   </requestHandler>
 
-  <requestHandler name="mock" class="org.apache.solr.core.MockQuerySenderListenerReqHandler"/>
+  <requestHandler name="/mock" class="org.apache.solr.core.MockQuerySenderListenerReqHandler"/>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -243,7 +239,7 @@
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
     <lst name="defaults">
       <int name="rows">4</int>
       <bool name="hl">true</bool>
@@ -341,7 +337,7 @@
    -->
   <queryConverter name="queryConverter" class="org.apache.solr.spelling.SpellingQueryConverter"/>
 
-  <requestHandler name="spellCheckCompRH" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckCompRH" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <!-- omp = Only More Popular -->
       <str name="spellcheck.onlyMorePopular">false</str>
@@ -354,7 +350,7 @@
       <str>spellcheck</str>
     </arr>
   </requestHandler>
-    <requestHandler name="spellCheckCompRH_Direct" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckCompRH_Direct" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <str name="spellcheck.dictionary">direct</str>
       <str name="spellcheck.onlyMorePopular">false</str>
@@ -365,7 +361,7 @@
       <str>spellcheck</str>
     </arr>
   </requestHandler>
-  <requestHandler name="spellCheckWithWordbreak" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckWithWordbreak" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <str name="spellcheck.dictionary">default</str>
       <str name="spellcheck.dictionary">wordbreak</str>
@@ -375,7 +371,7 @@
       <str>spellcheck</str>
     </arr>
   </requestHandler>
-  <requestHandler name="spellCheckWithWordbreak_Direct" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckWithWordbreak_Direct" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <str name="spellcheck.dictionary">direct</str>
       <str name="spellcheck.dictionary">wordbreak</str>
@@ -385,7 +381,7 @@
       <str>spellcheck</str>
     </arr>
   </requestHandler>
-  <requestHandler name="spellCheckCompRH1" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckCompRH1" class="org.apache.solr.handler.component.SearchHandler">
       <lst name="defaults">
         <str name="defType">dismax</str>
         <str name="qf">lowerfilt1^1</str>
@@ -395,13 +391,13 @@
       </arr>
  </requestHandler>
  
-  <requestHandler name="mltrh" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/mltrh" class="org.apache.solr.handler.component.SearchHandler">
 
   </requestHandler>
 
   <searchComponent name="tvComponent" class="org.apache.solr.handler.component.TermVectorComponent"/>
 
-  <requestHandler name="tvrh" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/tvrh" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
 
     </lst>
@@ -460,7 +456,7 @@
   </highlighting>
   </searchComponent>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="true" multipartUploadLimitInKB="-1" />
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>
@@ -578,7 +574,8 @@
     <str name="storageIO">org.apache.solr.rest.ManagedResourceStorage$InMemoryStorageIO</str>
   </restManager>
 
-  <initParams path="standard,dismax,defaults,lazy,spellCheckCompRH,spellCheckWithWordbreak,spellCheckCompRH_Direct,spellCheckCompRH1,mltrh,tvrh,/search-facet-def,/search-facet-invariants,/terms">
+  <!-- warning: not a best practice; requests generally ought to be explicit to thus not require this -->
+  <initParams path="/select,/dismax,/defaults,/lazy,/spellCheckCompRH,/spellCheckWithWordbreak,/spellCheckCompRH_Direct,/spellCheckCompRH1,/mltrh,/tvrh,/search-facet-def,/search-facet-invariants,/terms">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig_SimpleTextCodec.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig_SimpleTextCodec.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig_SimpleTextCodec.xml
index f3abf9b..7b0c3e3 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig_SimpleTextCodec.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig_SimpleTextCodec.xml
@@ -21,6 +21,6 @@
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"/>
+  <requestHandler name="/select" class="solr.SearchHandler"/>
   <codecFactory class="solr.SimpleTextCodecFactory"/>
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig_codec.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig_codec.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig_codec.xml
index 0c3e81e..ad08096 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig_codec.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig_codec.xml
@@ -21,7 +21,7 @@
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <codecFactory class="solr.SchemaCodecFactory">
     <str name="compressionMode">${tests.COMPRESSION_MODE:BEST_COMPRESSION}</str>
   </codecFactory>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig_codec2.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig_codec2.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig_codec2.xml
index d3790a4..c4a8ae7 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig_codec2.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig_codec2.xml
@@ -20,7 +20,7 @@
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
   <codecFactory class="solr.SchemaCodecFactory"/>
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig_perf.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig_perf.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig_perf.xml
index cc6f97b..6f35efa 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig_perf.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig_perf.xml
@@ -60,7 +60,7 @@
 
   </query>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <!--Make sure your system has some authentication before enabling remote streaming!  -->
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     <httpCaching lastModifiedFrom="openTime"
@@ -68,7 +68,6 @@
     </httpCaching>
   </requestDispatcher>
 
-  <requestHandler name="standard" class="solr.SearchHandler" default="true">
-  </requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/configsets/bad-mergepolicy/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/bad-mergepolicy/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/bad-mergepolicy/conf/solrconfig.xml
index 49bbf58..3ef080d 100644
--- a/solr/core/src/test-files/solr/configsets/bad-mergepolicy/conf/solrconfig.xml
+++ b/solr/core/src/test-files/solr/configsets/bad-mergepolicy/conf/solrconfig.xml
@@ -31,6 +31,6 @@
 
   <updateHandler class="solr.DirectUpdateHandler2"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
 
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/configsets/cdcr-source/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cdcr-source/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/cdcr-source/conf/solrconfig.xml
index f2528c3..6469038 100644
--- a/solr/core/src/test-files/solr/configsets/cdcr-source/conf/solrconfig.xml
+++ b/solr/core/src/test-files/solr/configsets/cdcr-source/conf/solrconfig.xml
@@ -64,8 +64,7 @@
     </updateLog>
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
-  </requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <requestHandler name="/update" class="solr.UpdateRequestHandler">
     <lst name="defaults">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/configsets/cdcr-target/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cdcr-target/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/cdcr-target/conf/solrconfig.xml
index ef24fa4..bb4a774 100644
--- a/solr/core/src/test-files/solr/configsets/cdcr-target/conf/solrconfig.xml
+++ b/solr/core/src/test-files/solr/configsets/cdcr-target/conf/solrconfig.xml
@@ -51,8 +51,7 @@
     </updateLog>
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
-  </requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <requestHandler name="/update" class="solr.UpdateRequestHandler">
     <lst name="defaults">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/configsets/exitable-directory/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/exitable-directory/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/exitable-directory/conf/solrconfig.xml
index 31c374c..af1036f 100644
--- a/solr/core/src/test-files/solr/configsets/exitable-directory/conf/solrconfig.xml
+++ b/solr/core/src/test-files/solr/configsets/exitable-directory/conf/solrconfig.xml
@@ -42,7 +42,7 @@
     <processor class="solr.RunUpdateProcessorFactory" />
   </updateRequestProcessorChain>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
   </requestHandler>
 
   <updateHandler class="solr.DirectUpdateHandler2">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/crazy-path-to-config.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/crazy-path-to-config.xml b/solr/core/src/test-files/solr/crazy-path-to-config.xml
index c6dc859..00781a9 100644
--- a/solr/core/src/test-files/solr/crazy-path-to-config.xml
+++ b/solr/core/src/test-files/solr/crazy-path-to-config.xml
@@ -37,9 +37,11 @@
     <HashDocSet maxSize="3000" loadFactor="0.75"/>
     <boolTofilterOptimizer enabled="true" cacheSize="32" threshold=".05"/>
   </query>
-  
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
-  <requestHandler name="crazy_custom_qt" class="solr.StandardRequestHandler">
+
+  <requestDispatcher/>
+
+  <requestHandler name="/select" class="solr.SearchHandler" />
+  <requestHandler name="/crazy_custom_qt" class="solr.SearchHandler">
     <lst name="defaults">
       <str name="fl">implicit</str>
       <str name="df">subject</str>
@@ -55,7 +57,7 @@
     <gettableFiles>solrconfig.xml schema.xml</gettableFiles>
   </admin>
 
-  <initParams path="standard,crazy_custom_qt">
+  <initParams path="/select,/crazy_custom_qt">
     <lst name="defaults">
       <str name="df">subject</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java b/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
index 2122c90..52e2e78 100644
--- a/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
+++ b/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
@@ -122,7 +122,7 @@ public class BasicFunctionalityTest extends SolrTestCaseJ4 {
     SolrCore core = h.getCore();
 
     // test that we got the expected config, not just hardcoded defaults
-    assertNotNull(core.getRequestHandler("mock"));
+    assertNotNull(core.getRequestHandler("/mock"));
 
     // test stats call
     SolrMetricManager manager = core.getCoreContainer().getMetricManager();
@@ -756,12 +756,12 @@ public class BasicFunctionalityTest extends SolrTestCaseJ4 {
             );
 
     assertQ("defaults handler returns fewer matches",
-            req("q", "id:[42 TO 47]",   "qt","defaults"),
+            req("q", "id:[42 TO 47]",   "qt","/defaults"),
             "*[count(//doc)=4]"
             );
 
     assertQ("defaults handler includes highlighting",
-            req("q", "name:Zapp OR title:General",   "qt","defaults"),
+            req("q", "name:Zapp OR title:General",   "qt","/defaults"),
             "//lst[@name='highlighting']"
             );
 


[42/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10977: Randomize the usage of Points based numerics in schema15.xml and all impacted tests

Posted by ab...@apache.org.
 SOLR-10977: Randomize the usage of Points based numerics in schema15.xml and all impacted tests


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

Branch: refs/heads/jira/solr-10879
Commit: b7fb61d7b96a594766264c5c09ef3ba22870e223
Parents: 46bfd9c
Author: Chris Hostetter <ho...@apache.org>
Authored: Thu Jun 29 12:05:15 2017 -0700
Committer: Chris Hostetter <ho...@apache.org>
Committed: Thu Jun 29 12:05:15 2017 -0700

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  1 +
 .../solr/collection1/conf/schema15.xml          | 22 ++++++++++----------
 2 files changed, 12 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b7fb61d7/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 62204cd..30d334b 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -362,6 +362,7 @@ Other Changes
   - SOLR-10947: Randomize the usage of Points based numerics in contrib test schemas (hossman)
   - SOLR-10970: Randomize PointFields in all tests using schema-*sort* files (hossman)
   - SOLR-10971: Randomize PointFields in CdcrBootstrapTest (hossman)
+  - SOLR-10977: Randomize the usage of Points based numerics in schema15.xml and all impacted tests (hossman)
 
 * SOLR-6807: Changed requestDispatcher's handleSelect to default to false, thus ignoring "qt".
   Simplified configs to not refer to handleSelect or "qt".  Switch all tests that assumed true to assume false

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b7fb61d7/solr/core/src/test-files/solr/collection1/conf/schema15.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema15.xml b/solr/core/src/test-files/solr/collection1/conf/schema15.xml
index 7db2142..cae5aee 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema15.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema15.xml
@@ -31,15 +31,15 @@
        1.5: omitNorms defaults to true for primitive field types (int, float, boolean, string...)
        1.6: useDocValuesAsStored defaults to true.
      -->
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
-
-  <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+  <fieldType name="float" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+  <fieldType name="double" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+
+  <fieldType name="tint" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="tfloat" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="tlong" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="tdouble" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="8" positionIncrementGap="0"/>
   <fieldType name="currency" class="solr.CurrencyField" currencyConfig="currency.xml" multiValued="false"/>
 
   <!-- Field type demonstrating an Analyzer failure -->
@@ -96,8 +96,8 @@
   <!-- format for date is 1995-12-31T23:59:59.999Z and only the fractional
        seconds part (.999) is optional.
     -->
-  <fieldType name="date" class="solr.TrieDateField" sortMissingLast="true"/>
-  <fieldType name="tdate" class="solr.TrieDateField" sortMissingLast="true" precisionStep="6"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" sortMissingLast="true"/>
+  <fieldType name="tdate" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" sortMissingLast="true" precisionStep="6"/>
 
   <fieldType name="text" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
     <analyzer type="index">


[56/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-6671: More generic fix to assert Solr's dataHome

Posted by ab...@apache.org.
SOLR-6671: More generic fix to assert Solr's dataHome


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/20dcb56d
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/20dcb56d
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/20dcb56d

Branch: refs/heads/jira/solr-10879
Commit: 20dcb56da85accabd8e32b41afaca71707797ade
Parents: eaf1d45
Author: Uwe Schindler <us...@apache.org>
Authored: Mon Jul 3 08:15:54 2017 +0200
Committer: Uwe Schindler <us...@apache.org>
Committed: Mon Jul 3 08:15:54 2017 +0200

----------------------------------------------------------------------
 .../src/test/org/apache/solr/core/DirectoryFactoryTest.java   | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/20dcb56d/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java b/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
index 2c2ddd9..aa00342 100755
--- a/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
+++ b/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
@@ -20,7 +20,6 @@ import java.io.IOException;
 import java.nio.file.Paths;
 import java.util.Properties;
 
-import org.apache.lucene.util.Constants;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.handler.admin.CoreAdminHandler;
@@ -74,11 +73,7 @@ public class DirectoryFactoryTest extends LuceneTestCase {
 
   private void assertDataHome(String expected, String instanceDir, RAMDirectoryFactory rdf, MockCoreContainer cc, String... properties) throws IOException {
     String dataHome = rdf.getDataHome(new CoreDescriptor("core_name", Paths.get(instanceDir), cc.containerProperties, cc.isZooKeeperAware(), properties));
-    if (Constants.WINDOWS) {
-      // TODO: find a less-hacky way to assert this!
-      dataHome = dataHome.replaceFirst("^[A-Z]:", "").replace("\\", "/");
-    }
-    assertEquals(expected, dataHome);
+    assertEquals(Paths.get(expected).toAbsolutePath(), Paths.get(dataHome).toAbsolutePath());
   }
 
 


[29/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10910: Clean up a few details left over from pluggable transient core and untangling CoreDescriptor/CoreContainer references

Posted by ab...@apache.org.
SOLR-10910: Clean up a few details left over from pluggable transient core and untangling CoreDescriptor/CoreContainer references


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/8f71bb40
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/8f71bb40
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/8f71bb40

Branch: refs/heads/jira/solr-10879
Commit: 8f71bb40a55f6e7906e596938d0bf13900f77a94
Parents: 811621c
Author: Erick Erickson <er...@apache.org>
Authored: Wed Jun 28 21:02:14 2017 -0700
Committer: Erick Erickson <er...@apache.org>
Committed: Wed Jun 28 21:02:14 2017 -0700

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  3 +
 .../org/apache/solr/core/CoreContainer.java     | 56 ++++++------
 .../src/java/org/apache/solr/core/SolrCore.java |  2 +-
 .../java/org/apache/solr/core/SolrCores.java    | 91 +++++++++++---------
 .../apache/solr/core/SolrResourceLoader.java    |  1 -
 .../solr/cloud/BasicDistributedZkTest.java      | 29 +++----
 .../solr/cloud/UnloadDistributedZkTest.java     | 12 ++-
 .../org/apache/solr/cloud/ZkControllerTest.java | 19 ++--
 .../org/apache/solr/core/TestCoreDiscovery.java |  3 +-
 .../org/apache/solr/core/TestLazyCores.java     | 44 ++++++----
 10 files changed, 138 insertions(+), 122 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8f71bb40/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 39fc14c..62204cd 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -495,6 +495,9 @@ when using one of Exact*StatsCache (Mikhail Khludnev)
 * SOLR-10963: Fix example json in MultipleAdditiveTreesModel javadocs.
   (Stefan Langenmaier via Christine Poerschke)
 
+* SOLR-10910: Clean up a few details left over from pluggable transient core and untangling
+  CoreDescriptor/CoreContainer references (Erick Erickson)
+
 Optimizations
 ----------------------
 * SOLR-10634: JSON Facet API: When a field/terms facet will retrieve all buckets (i.e. limit:-1)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8f71bb40/solr/core/src/java/org/apache/solr/core/CoreContainer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index 90bbf5d..322952b 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -135,7 +135,7 @@ public class CoreContainer {
 
   protected CoreAdminHandler coreAdminHandler = null;
   protected CollectionsHandler collectionsHandler = null;
-  protected TransientSolrCoreCache transientSolrCoreCache = null;
+
   private InfoHandler infoHandler;
   protected ConfigSetsHandler configSetsHandler = null;
 
@@ -150,8 +150,6 @@ public class CoreContainer {
 
   private UpdateShardHandler updateShardHandler;
 
-  private TransientSolrCoreCacheFactory transientCoreCache;
-
   private ExecutorService coreContainerWorkExecutor = ExecutorUtil.newMDCAwareCachedThreadPool(
       new DefaultSolrThreadFactory("coreContainerWorkExecutor") );
 
@@ -507,7 +505,8 @@ public class CoreContainer {
     updateShardHandler = new UpdateShardHandler(cfg.getUpdateShardHandlerConfig());
     updateShardHandler.initializeMetrics(metricManager, SolrInfoBean.Group.node.toString(), "updateShardHandler");
 
-    transientCoreCache = TransientSolrCoreCacheFactory.newInstance(loader, this);
+    solrCores.load(loader);
+
 
     logging = LogWatcher.newRegisteredLogWatcher(cfg.getLogWatcherConfig(), loader);
 
@@ -596,7 +595,7 @@ public class CoreContainer {
 
       for (final CoreDescriptor cd : cds) {
         if (cd.isTransient() || !cd.isLoadOnStartup()) {
-          getTransientCacheHandler().addTransientDescriptor(cd.getName(), cd);
+          solrCores.getTransientCacheHandler().addTransientDescriptor(cd.getName(), cd);
         } else if (asyncSolrCoreLoad) {
           solrCores.markCoreAsLoading(cd);
         }
@@ -660,16 +659,6 @@ public class CoreContainer {
   }
 
 
-  public TransientSolrCoreCache getTransientCacheHandler() {
-
-    if (transientCoreCache == null) {
-      log.error("No transient handler has been defined. Check solr.xml to see if an attempt to provide a custom " +
-          "TransientSolrCoreCacheFactory was done incorrectly since the default should have been used otherwise.");
-      return null;
-    }
-    return transientCoreCache.getTransientSolrCoreCache();
-  }
-
   public void securityNodeChanged() {
     log.info("Security node changed, reloading security.json");
     reloadSecurityProperties();
@@ -843,13 +832,13 @@ public class CoreContainer {
       core.close();
       throw new IllegalStateException("This CoreContainer has been closed");
     }
+    solrCores.addCoreDescriptor(cd);
     SolrCore old = solrCores.putCore(cd, core);
       /*
       * set both the name of the descriptor and the name of the
       * core, since the descriptors name is used for persisting.
       */
 
-    solrCores.addCoreDescriptor(new CoreDescriptor(cd.getName(), cd));
     core.setName(cd.getName());
 
     coreInitFailures.remove(cd.getName());
@@ -893,7 +882,8 @@ public class CoreContainer {
     CoreDescriptor cd = new CoreDescriptor(coreName, instancePath, parameters, getContainerProperties(), isZooKeeperAware());
 
     // TODO: There's a race here, isn't there?
-    if (getLoadedCoreNames().contains(coreName)) {
+    // Since the core descriptor is removed when a core is unloaded, it should never be anywhere when a core is created.
+    if (getAllCoreNames().contains(coreName)) {
       log.warn("Creating a core with existing name is not allowed");
       // TODO: Shouldn't this be a BAD_REQUEST?
       throw new SolrException(ErrorCode.SERVER_ERROR, "Core with name '" + coreName + "' already exists.");
@@ -991,6 +981,7 @@ public class CoreContainer {
       return core;
     } catch (Exception e) {
       coreInitFailures.put(dcore.getName(), new CoreLoadFailure(dcore, e));
+      solrCores.removeCoreDescriptor(dcore);
       final SolrException solrException = new SolrException(ErrorCode.SERVER_ERROR, "Unable to create core [" + dcore.getName() + "]", e);
       if(core != null && !core.isClosed())
         IOUtils.closeQuietly(core);
@@ -998,6 +989,7 @@ public class CoreContainer {
     } catch (Throwable t) {
       SolrException e = new SolrException(ErrorCode.SERVER_ERROR, "JVM Error creating core [" + dcore.getName() + "]: " + t.getMessage(), t);
       coreInitFailures.put(dcore.getName(), new CoreLoadFailure(dcore, e));
+      solrCores.removeCoreDescriptor(dcore);
       if(core != null && !core.isClosed())
         IOUtils.closeQuietly(core);
       throw t;
@@ -1104,24 +1096,30 @@ public class CoreContainer {
   }
 
   /**
-   * @return a Collection of the names that loaded cores are mapped to
+   * Gets the cores that are currently loaded, i.e. cores that have
+   * 1: loadOnStartup=true and are either not-transient or, if transient, have been loaded and have not been aged out
+   * 2: loadOnStartup=false and have been loaded but are either non-transient or have not been aged out.
+   *
+   * Put another way, this will not return any names of cores that are lazily loaded but have not been called for yet
+   * or are transient and either not loaded or have been swapped out.
+   *
    */
   public Collection<String> getLoadedCoreNames() {
     return solrCores.getLoadedCoreNames();
   }
 
   /** This method is currently experimental.
-   * @return a Collection of the names that a specific core is mapped to.
+   *
+   * @return a Collection of the names that a specific core object is mapped to, there are more than one.
    */
-  public Collection<String> getCoreNames(SolrCore core) {
-    return solrCores.getCoreNames(core);
+  public Collection<String> getNamesForCore(SolrCore core) {
+    return solrCores.getNamesForCore(core);
   }
 
   /**
-   * get a list of all the cores that are currently loaded
-   * @return a list of al lthe available core names in either permanent or transient core lists.
+   * get a list of all the cores that are currently known, whether currently loaded or not
+   * @return a list of all the available core names in either permanent or transient cores
    *
-   * Note: this implies that the core is loaded
    */
   public Collection<String> getAllCoreNames() {
     return solrCores.getAllCoreNames();
@@ -1266,6 +1264,8 @@ public class CoreContainer {
    */
   public void unload(String name, boolean deleteIndexDir, boolean deleteDataDir, boolean deleteInstanceDir) {
 
+    CoreDescriptor cd = solrCores.getCoreDescriptor(name);
+    
     if (name != null) {
       // check for core-init errors first
       CoreLoadFailure loadFailure = coreInitFailures.remove(name);
@@ -1274,11 +1274,15 @@ public class CoreContainer {
         // which we may not be able to do because of the init error.  So we just go with what we
         // can glean from the CoreDescriptor - datadir and instancedir
         SolrCore.deleteUnloadedCore(loadFailure.cd, deleteDataDir, deleteInstanceDir);
+        // If last time around we didn't successfully load, make sure that all traces of the coreDescriptor are gone.
+        if (cd != null) {
+          solrCores.removeCoreDescriptor(cd);
+          coresLocator.delete(this, cd);
+        }
         return;
       }
     }
-
-    CoreDescriptor cd = solrCores.getCoreDescriptor(name);
+      
     if (cd == null) {
       throw new SolrException(ErrorCode.BAD_REQUEST, "Cannot unload non-existent core [" + name + "]");
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8f71bb40/solr/core/src/java/org/apache/solr/core/SolrCore.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCore.java b/solr/core/src/java/org/apache/solr/core/SolrCore.java
index 76e2cad..5319881 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCore.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCore.java
@@ -1137,7 +1137,7 @@ public final class SolrCore implements SolrInfoBean, SolrMetricProducer, Closeab
     manager.registerGauge(this, registry, () -> getIndexSize(), true, "sizeInBytes", Category.INDEX.toString());
     manager.registerGauge(this, registry, () -> NumberUtils.readableSize(getIndexSize()), true, "size", Category.INDEX.toString());
     if (coreContainer != null) {
-      manager.registerGauge(this, registry, () -> coreContainer.getCoreNames(this), true, "aliases", Category.CORE.toString());
+      manager.registerGauge(this, registry, () -> coreContainer.getNamesForCore(this), true, "aliases", Category.CORE.toString());
       final CloudDescriptor cd = getCoreDescriptor().getCloudDescriptor();
       if (cd != null) {
         manager.registerGauge(this, registry, () -> {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8f71bb40/solr/core/src/java/org/apache/solr/core/SolrCores.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrCores.java b/solr/core/src/java/org/apache/solr/core/SolrCores.java
index 87ffac3..7f4b9a0 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrCores.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrCores.java
@@ -64,6 +64,10 @@ class SolrCores implements Observer {
   // to essentially queue them up to be handled via pendingCoreOps.
   private static final List<SolrCore> pendingCloses = new ArrayList<>();
 
+  private TransientSolrCoreCacheFactory transientCoreCache;
+
+  private TransientSolrCoreCache transientSolrCoreCache = null;
+  
   SolrCores(CoreContainer container) {
     this.container = container;
   }
@@ -71,8 +75,10 @@ class SolrCores implements Observer {
   protected void addCoreDescriptor(CoreDescriptor p) {
     synchronized (modifyLock) {
       if (p.isTransient()) {
-        if (container.getTransientCacheHandler() != null) {
-          container.getTransientCacheHandler().addTransientDescriptor(p.getName(), p);
+        if (getTransientCacheHandler() != null) {
+          getTransientCacheHandler().addTransientDescriptor(p.getName(), p);
+        } else {
+          log.warn("We encountered a core marked as transient, but there is no transient handler defined. This core will be inaccessible");
         }
       } else {
         residentDesciptors.put(p.getName(), p);
@@ -83,8 +89,8 @@ class SolrCores implements Observer {
   protected void removeCoreDescriptor(CoreDescriptor p) {
     synchronized (modifyLock) {
       if (p.isTransient()) {
-        if (container.getTransientCacheHandler() != null) {
-          container.getTransientCacheHandler().removeTransientDescriptor(p.getName());
+        if (getTransientCacheHandler() != null) {
+          getTransientCacheHandler().removeTransientDescriptor(p.getName());
         }
       } else {
         residentDesciptors.remove(p.getName());
@@ -92,6 +98,9 @@ class SolrCores implements Observer {
     }
   }
 
+  public void load(SolrResourceLoader loader) {
+    transientCoreCache = TransientSolrCoreCacheFactory.newInstance(loader, container);
+  }
   // We are shutting down. You can't hold the lock on the various lists of cores while they shut down, so we need to
   // make a temporary copy of the names and shut them down outside the lock.
   protected void close() {
@@ -99,7 +108,7 @@ class SolrCores implements Observer {
     Collection<SolrCore> coreList = new ArrayList<>();
 
     
-    TransientSolrCoreCache transientSolrCoreCache = container.getTransientCacheHandler();
+    TransientSolrCoreCache transientSolrCoreCache = getTransientCacheHandler();
     // Release observer
     if (transientSolrCoreCache != null) {
       transientSolrCoreCache.close();
@@ -147,25 +156,14 @@ class SolrCores implements Observer {
 
     } while (coreList.size() > 0);
   }
-
-  //WARNING! This should be the _only_ place you put anything into the list of transient cores!
-  protected SolrCore putTransientCore(NodeConfig cfg, String name, SolrCore core, SolrResourceLoader loader) {
-    SolrCore retCore = null;
-    log.info("Opening transient core {}", name);
-    synchronized (modifyLock) {
-      if (container.getTransientCacheHandler() != null) {
-        retCore = container.getTransientCacheHandler().addCore(name, core);
-      }
-    }
-    return retCore;
-  }
-
+  
   // Returns the old core if there was a core of the same name.
+  //WARNING! This should be the _only_ place you put anything into the list of transient cores!
   protected SolrCore putCore(CoreDescriptor cd, SolrCore core) {
     synchronized (modifyLock) {
       if (cd.isTransient()) {
-        if (container.getTransientCacheHandler() != null) {
-          return container.getTransientCacheHandler().addCore(cd.getName(), core);
+        if (getTransientCacheHandler() != null) {
+          return getTransientCacheHandler().addCore(cd.getName(), core);
         }
       } else {
         return cores.put(cd.getName(), core);
@@ -196,8 +194,8 @@ class SolrCores implements Observer {
 
   /**
    * Gets the cores that are currently loaded, i.e. cores that have
-   * 1> loadOnStartup=true and are either not-transient or, if transient, have been loaded and have not been swapped out
-   * 2> loadOnStartup=false and have been loaded but either non-transient or have not been swapped out.
+   * 1> loadOnStartup=true and are either not-transient or, if transient, have been loaded and have not been aged out
+   * 2> loadOnStartup=false and have been loaded but either non-transient or have not been aged out.
    * 
    * Put another way, this will not return any names of cores that are lazily loaded but have not been called for yet
    * or are transient and either not loaded or have been swapped out.
@@ -209,20 +207,19 @@ class SolrCores implements Observer {
 
     synchronized (modifyLock) {
       set.addAll(cores.keySet());
-      if (container.getTransientCacheHandler() != null) {
-        set.addAll(container.getTransientCacheHandler().getLoadedCoreNames());
+      if (getTransientCacheHandler() != null) {
+        set.addAll(getTransientCacheHandler().getLoadedCoreNames());
       }
     }
     return set;
   }
 
   /** This method is currently experimental.
-   * @return a Collection of the names that a specific core is mapped to.
-   * 
-   * Note: this implies that the core is loaded
+   *
+   * @return a Collection of the names that a specific core object is mapped to, there are more than one.
    */
   @Experimental
-  List<String> getCoreNames(SolrCore core) {
+  List<String> getNamesForCore(SolrCore core) {
     List<String> lst = new ArrayList<>();
 
     synchronized (modifyLock) {
@@ -231,8 +228,8 @@ class SolrCores implements Observer {
           lst.add(entry.getKey());
         }
       }
-      if (container.getTransientCacheHandler() != null) {
-        lst.addAll(container.getTransientCacheHandler().getNamesForCore(core));
+      if (getTransientCacheHandler() != null) {
+        lst.addAll(getTransientCacheHandler().getNamesForCore(core));
       }
     }
     return lst;
@@ -241,14 +238,14 @@ class SolrCores implements Observer {
   /**
    * Gets a list of all cores, loaded and unloaded 
    *
-   * @return all cores names, whether loaded or unloaded, transient or permenent.
+   * @return all cores names, whether loaded or unloaded, transient or permanent.
    */
   public Collection<String> getAllCoreNames() {
     Set<String> set = new TreeSet<>();
     synchronized (modifyLock) {
       set.addAll(cores.keySet());
-      if (container.getTransientCacheHandler() != null) {
-        set.addAll(container.getTransientCacheHandler().getAllCoreNames());
+      if (getTransientCacheHandler() != null) {
+        set.addAll(getTransientCacheHandler().getAllCoreNames());
       }
       set.addAll(residentDesciptors.keySet());
     }
@@ -302,7 +299,7 @@ class SolrCores implements Observer {
       SolrCore ret = cores.remove(name);
       // It could have been a newly-created core. It could have been a transient core. The newly-created cores
       // in particular should be checked. It could have been a dynamic core.
-      TransientSolrCoreCache transientHandler = container.getTransientCacheHandler();
+      TransientSolrCoreCache transientHandler = getTransientCacheHandler();
       if (ret == null && transientHandler != null) {
         ret = transientHandler.removeCore(name);
       }
@@ -315,8 +312,8 @@ class SolrCores implements Observer {
     synchronized (modifyLock) {
       SolrCore core = cores.get(name);
 
-      if (core == null && container.getTransientCacheHandler() != null) {
-        core = container.getTransientCacheHandler().getCore(name);
+      if (core == null && getTransientCacheHandler() != null) {
+        core = getTransientCacheHandler().getCore(name);
       }
 
       if (core != null && incRefCount) {
@@ -336,7 +333,7 @@ class SolrCores implements Observer {
       if (cores.containsKey(name)) {
         return true;
       }
-      if (container.getTransientCacheHandler() != null && container.getTransientCacheHandler().containsCore(name)) {
+      if (getTransientCacheHandler() != null && getTransientCacheHandler().containsCore(name)) {
         // Check pending
         for (SolrCore core : pendingCloses) {
           if (core.getName().equals(name)) {
@@ -355,7 +352,7 @@ class SolrCores implements Observer {
       if (cores.containsKey(name)) {
         return true;
       }
-      if (container.getTransientCacheHandler() != null && container.getTransientCacheHandler().containsCore(name)) {
+      if (getTransientCacheHandler() != null && getTransientCacheHandler().containsCore(name)) {
         return true;
       }
     }
@@ -367,8 +364,8 @@ class SolrCores implements Observer {
     synchronized (modifyLock) {
       CoreDescriptor desc = residentDesciptors.get(cname);
       if (desc == null) {
-        if (container.getTransientCacheHandler() == null) return null;
-        desc = container.getTransientCacheHandler().getTransientDescriptor(cname);
+        if (getTransientCacheHandler() == null) return null;
+        desc = getTransientCacheHandler().getTransientDescriptor(cname);
         if (desc == null) {
           return null;
         }
@@ -456,7 +453,7 @@ class SolrCores implements Observer {
     synchronized (modifyLock) {
       if (residentDesciptors.containsKey(coreName))
         return residentDesciptors.get(coreName);
-      return container.getTransientCacheHandler().getTransientDescriptor(coreName);
+      return getTransientCacheHandler().getTransientDescriptor(coreName);
     }
   }
 
@@ -545,4 +542,16 @@ class SolrCores implements Observer {
       modifyLock.notifyAll(); // Wakes up closer thread too
     }
   }
+
+  public TransientSolrCoreCache getTransientCacheHandler() {
+
+    if (transientCoreCache == null) {
+      log.error("No transient handler has been defined. Check solr.xml to see if an attempt to provide a custom " +
+          "TransientSolrCoreCacheFactory was done incorrectly since the default should have been used otherwise.");
+      return null;
+    }
+    return transientCoreCache.getTransientSolrCoreCache();
+  }
+
+
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8f71bb40/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
index ef79875..22753dd 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
@@ -105,7 +105,6 @@ public class SolrResourceLoader implements ResourceLoader,Closeable
   private final List<ResourceLoaderAware> waitingForResources = Collections.synchronizedList(new ArrayList<ResourceLoaderAware>());
   private static final Charset UTF_8 = StandardCharsets.UTF_8;
 
-  //TODO: Solr5. Remove this completely when you obsolete putting <core> tags in solr.xml (See Solr-4196)
   private final Properties coreProperties;
 
   private volatile boolean live;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8f71bb40/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
index fcc51ac..518142a 100644
--- a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
@@ -535,9 +535,8 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
   }
 
   private void testStopAndStartCoresInOneInstance() throws Exception {
-    SolrClient client = clients.get(0);
-    String url3 = getBaseUrl(client);
-    try (final HttpSolrClient httpSolrClient = getHttpSolrClient(url3)) {
+    JettySolrRunner jetty = jettys.get(0);
+    try (final HttpSolrClient httpSolrClient = (HttpSolrClient) jetty.newClient()) {
       httpSolrClient.setConnectionTimeout(15000);
       httpSolrClient.setSoTimeout(60000);
       ThreadPoolExecutor executor = null;
@@ -548,7 +547,7 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
         int cnt = 3;
 
         // create the cores
-        createCores(httpSolrClient, executor, "multiunload2", 1, cnt);
+        createCollectionInOneInstance(httpSolrClient, jetty.getNodeName(), executor, "multiunload2", 1, cnt);
       } finally {
         if (executor != null) {
           ExecutorUtil.shutdownAndAwaitTermination(executor);
@@ -573,8 +572,13 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
 
   }
 
-  protected void createCores(final HttpSolrClient client,
-      ThreadPoolExecutor executor, final String collection, final int numShards, int cnt) {
+  /**
+   * Create a collection in single node
+   */
+  protected void createCollectionInOneInstance(final SolrClient client, String nodeName,
+                                               ThreadPoolExecutor executor, final String collection,
+                                               final int numShards, int numReplicas) {
+    assertNotNull(nodeName);
     try {
       assertEquals(0, CollectionAdminRequest.createCollection(collection, "conf1", numShards, 1)
           .setCreateNodeSet("")
@@ -582,22 +586,13 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
     } catch (SolrServerException | IOException e) {
       throw new RuntimeException(e);
     }
-    String nodeName = null;
-    for (JettySolrRunner jetty : jettys) {
-      if (client.getBaseURL().contains(":"+jetty.getLocalPort())) {
-        nodeName = jetty.getNodeName();
-        break;
-      }
-    }
-    assertNotNull(nodeName);
-    for (int i = 0; i < cnt; i++) {
+    for (int i = 0; i < numReplicas; i++) {
       final int freezeI = i;
-      final String freezeNodename = nodeName;
       executor.execute(() -> {
         try {
           assertTrue(CollectionAdminRequest.addReplicaToShard(collection, "shard"+((freezeI%numShards)+1))
               .setCoreName(collection + freezeI)
-              .setNode(freezeNodename).process(client).isSuccess());
+              .setNode(nodeName).process(client).isSuccess());
         } catch (SolrServerException | IOException e) {
           throw new RuntimeException(e);
         }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8f71bb40/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
index 19dd998..daa73cf 100644
--- a/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
@@ -18,7 +18,6 @@ package org.apache.solr.cloud;
 
 import org.apache.lucene.util.LuceneTestCase.Slow;
 import org.apache.solr.SolrTestCaseJ4.SuppressSSL;
-import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
@@ -348,18 +347,17 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
   }
   
   private void testUnloadLotsOfCores() throws Exception {
-    SolrClient client = clients.get(2);
-    String url3 = getBaseUrl(client);
-    try (final HttpSolrClient adminClient = getHttpSolrClient(url3)) {
+    JettySolrRunner jetty = jettys.get(0);
+    try (final HttpSolrClient adminClient = (HttpSolrClient) jetty.newClient()) {
       adminClient.setConnectionTimeout(15000);
       adminClient.setSoTimeout(60000);
-      int cnt = atLeast(3);
+      int numReplicas = atLeast(3);
       ThreadPoolExecutor executor = new ExecutorUtil.MDCAwareThreadPoolExecutor(0, Integer.MAX_VALUE,
           5, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
           new DefaultSolrThreadFactory("testExecutor"));
       try {
         // create the cores
-        createCores(adminClient, executor, "multiunload", 2, cnt);
+        createCollectionInOneInstance(adminClient, jetty.getNodeName(), executor, "multiunload", 2, numReplicas);
       } finally {
         ExecutorUtil.shutdownAndAwaitTermination(executor);
       }
@@ -368,7 +366,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
           TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
           new DefaultSolrThreadFactory("testExecutor"));
       try {
-        for (int j = 0; j < cnt; j++) {
+        for (int j = 0; j < numReplicas; j++) {
           final int freezeJ = j;
           executor.execute(() -> {
             Unload unloadCmd = new Unload(true);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8f71bb40/solr/core/src/test/org/apache/solr/cloud/ZkControllerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/ZkControllerTest.java b/solr/core/src/test/org/apache/solr/cloud/ZkControllerTest.java
index d05cec9..d17d779 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ZkControllerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ZkControllerTest.java
@@ -30,7 +30,6 @@ import org.apache.solr.core.CloudConfig;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.CoreDescriptor;
 import org.apache.solr.core.SolrXmlConfig;
-import org.apache.solr.core.TransientSolrCoreCache;
 import org.apache.solr.handler.admin.CoreAdminHandler;
 import org.apache.solr.handler.component.HttpShardHandlerFactory;
 import org.apache.solr.update.UpdateShardHandler;
@@ -328,30 +327,26 @@ public class ZkControllerTest extends SolrTestCaseJ4 {
 
   private static class MockCoreContainer extends CoreContainer {
     UpdateShardHandler updateShardHandler = new UpdateShardHandler(UpdateShardHandlerConfig.DEFAULT);
+
     public MockCoreContainer() {
       super(SolrXmlConfig.fromString(null, "<solr/>"));
       this.shardHandlerFactory = new HttpShardHandlerFactory();
       this.coreAdminHandler = new CoreAdminHandler();
     }
-    
+
     @Override
-    public void load() {}
-    
+    public void load() {
+    }
+
     @Override
     public UpdateShardHandler getUpdateShardHandler() {
       return updateShardHandler;
     }
-    
+
     @Override
     public void shutdown() {
       updateShardHandler.close();
       super.shutdown();
     }
-    
-    @Override
-    public TransientSolrCoreCache getTransientCacheHandler() {
-      return transientSolrCoreCache;
-    }
-
-  }
+  }    
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8f71bb40/solr/core/src/test/org/apache/solr/core/TestCoreDiscovery.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestCoreDiscovery.java b/solr/core/src/test/org/apache/solr/core/TestCoreDiscovery.java
index 95c8cb9..bf0568f 100644
--- a/solr/core/src/test/org/apache/solr/core/TestCoreDiscovery.java
+++ b/solr/core/src/test/org/apache/solr/core/TestCoreDiscovery.java
@@ -22,6 +22,7 @@ import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Paths;
+import java.util.Arrays;
 import java.util.Properties;
 
 import com.google.common.collect.ImmutableMap;
@@ -152,7 +153,7 @@ public class TestCoreDiscovery extends SolrTestCaseJ4 {
     try {
 
       TestLazyCores.checkInCores(cc, "core1");
-      TestLazyCores.checkNotInCores(cc, "lazy1", "core2");
+      TestLazyCores.checkNotInCores(cc, Arrays.asList("lazy1", "core2"));
 
       // force loading of core2 and lazy1 by getting them from the CoreContainer
       try (SolrCore core1 = cc.getCore("core1");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8f71bb40/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestLazyCores.java b/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
index 7c41470..4c50480 100644
--- a/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
+++ b/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
@@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -100,8 +101,8 @@ public class TestLazyCores extends SolrTestCaseJ4 {
 
       // NOTE: This checks the initial state for loading, no need to do this elsewhere.
       checkInCores(cc, "collection1", "collection2", "collection5");
-      checkNotInCores(cc, "collection3", "collection4", "collection6", "collection7",
-          "collection8", "collection9");
+      checkNotInCores(cc, Arrays.asList("collection3", "collection4", "collection6", "collection7",
+          "collection8", "collection9"));
 
       SolrCore core1 = cc.getCore("collection1");
       assertFalse("core1 should not be transient", core1.getCoreDescriptor().isTransient());
@@ -176,7 +177,7 @@ public class TestLazyCores extends SolrTestCaseJ4 {
     CoreContainer cc = init();
     try {
       // Make sure Lazy4 isn't loaded. Should be loaded on the get
-      checkNotInCores(cc, "collection4");
+      checkNotInCores(cc, Arrays.asList("collection4"));
       SolrCore core4 = cc.getCore("collection4");
 
       checkSearch(core4);
@@ -205,7 +206,7 @@ public class TestLazyCores extends SolrTestCaseJ4 {
       // First check that all the cores that should be loaded at startup actually are.
 
       checkInCores(cc, "collection1", "collection2", "collection5");
-      checkNotInCores(cc, "collection3", "collection4", "collection6", "collection7", "collection8", "collection9");
+      checkNotInCores(cc, Arrays.asList("collection3", "collection4", "collection6", "collection7", "collection8", "collection9"));
 
       // By putting these in non-alpha order, we're also checking that we're  not just seeing an artifact.
       SolrCore core1 = cc.getCore("collection1");
@@ -215,28 +216,28 @@ public class TestLazyCores extends SolrTestCaseJ4 {
       SolrCore core5 = cc.getCore("collection5");
 
       checkInCores(cc, "collection1", "collection2", "collection3", "collection4", "collection5");
-      checkNotInCores(cc, "collection6", "collection7", "collection8", "collection9");
+      checkNotInCores(cc, Arrays.asList("collection6", "collection7", "collection8", "collection9"));
 
       // map should be full up, add one more and verify
       SolrCore core6 = cc.getCore("collection6");
       checkInCores(cc, "collection1", "collection2", "collection3", "collection4", "collection5",
           "collection6");
-      checkNotInCores(cc, "collection7", "collection8", "collection9");
+      checkNotInCores(cc, Arrays.asList("collection7", "collection8", "collection9"));
 
       SolrCore core7 = cc.getCore("collection7");
       checkInCores(cc, "collection1", "collection2", "collection3", "collection4", "collection5",
           "collection6", "collection7");
-      checkNotInCores(cc, "collection8", "collection9");
+      checkNotInCores(cc, Arrays.asList("collection8", "collection9"));
 
       SolrCore core8 = cc.getCore("collection8");
       checkInCores(cc, "collection1", "collection2", "collection4", "collection5", "collection6",
           "collection7", "collection8");
-      checkNotInCores(cc, "collection3", "collection9");
+      checkNotInCores(cc, Arrays.asList("collection3", "collection9"));
 
       SolrCore core9 = cc.getCore("collection9");
       checkInCores(cc, "collection1", "collection4", "collection5", "collection6", "collection7",
           "collection8", "collection9");
-      checkNotInCores(cc, "collection2", "collection3");
+      checkNotInCores(cc, Arrays.asList("collection2", "collection3"));
 
 
       // Note decrementing the count when the core is removed from the lazyCores list is appropriate, since the
@@ -396,8 +397,8 @@ public class TestLazyCores extends SolrTestCaseJ4 {
       final SolrCore c4 = cc.getCore("core4");
       final SolrCore c5 = cc.getCore("core5");
 
-      checkNotInCores(cc, "core1", "collection2", "collection3", "collection4", "collection6"
-          , "collection7", "collection8", "collection9");
+      checkNotInCores(cc, Arrays.asList("core1", "collection2", "collection3", "collection4", "collection6"
+          , "collection7", "collection8", "collection9"));
 
       checkInCores(cc, "collection1", "collection5", "core2", "core3", "core4", "core5");
 
@@ -467,7 +468,7 @@ public class TestLazyCores extends SolrTestCaseJ4 {
       checkInCores(cc, "core1", "core2");
 
       // Did the bad cores fail to load?
-      checkNotInCores(cc, "badSchema1", "badSchema2", "badConfig1", "badConfig2");
+      checkNotInCores(cc, Collections.emptyList(), Arrays.asList("badSchema1", "badSchema2", "badConfig1", "badConfig2"));
 
       //  Can we still search the "good" cores even though there were core init failures?
       SolrCore core1 = cc.getCore("core1");
@@ -644,7 +645,10 @@ public class TestLazyCores extends SolrTestCaseJ4 {
     }
   }
 
-  public static void checkNotInCores(CoreContainer cc, String... nameCheck) {
+  public static void checkNotInCores(CoreContainer cc, List<String> nameCheck) {
+    checkNotInCores(cc, nameCheck, Collections.emptyList());
+  }
+  public static void checkNotInCores(CoreContainer cc, List<String> nameCheck, List<String> namesBad) {
     Collection<String> loadedNames = cc.getLoadedCoreNames();
     for (String name : nameCheck) {
       assertFalse("core " + name + " was found in the list of cores", loadedNames.contains(name));
@@ -657,7 +661,7 @@ public class TestLazyCores extends SolrTestCaseJ4 {
     // the names in nameCheck should be loaded and thus should not be in names.
     
     Collection<String> allNames = cc.getAllCoreNames();
-    // Every core, loaded or not should be in the accumulated coredescriptors:
+    // Every core that has not failed to load should be in coreDescriptors.
     List<CoreDescriptor> descriptors = cc.getCoreDescriptors();
 
     assertEquals("There should be as many coreDescriptors as coreNames", allNames.size(), descriptors.size());
@@ -671,10 +675,18 @@ public class TestLazyCores extends SolrTestCaseJ4 {
           allNames.contains(name));
     }
 
+    // failed cores should have had their descriptors removed.
     for (String name : nameCheck) {
       assertTrue("Not-currently-loaded core " + name + " should have been found in the list of all possible core names",
           allNames.contains(name));
     }
+
+    // Failed cores should not be in coreDescriptors.
+    for (String name : namesBad) {
+      assertFalse("Failed core " + name + " should have been found in the list of all possible core names",
+          allNames.contains(name));
+    }
+
   }
 
   public static void checkInCores(CoreContainer cc, String... nameCheck) {
@@ -795,7 +807,7 @@ public class TestLazyCores extends SolrTestCaseJ4 {
       }
       
       // Just proving that some cores have been aged out.
-      checkNotInCores(cc, "collection2", "collection3");
+      checkNotInCores(cc, Arrays.asList("collection2", "collection3"));
 
       // Close our get of all cores above.
       for (SolrCore core : openCores) core.close();
@@ -807,7 +819,7 @@ public class TestLazyCores extends SolrTestCaseJ4 {
       for (String coreName : coreList) {
         // The point of this test is to insure that when cores are aged out and re-opened
         // that the docs are there, so insure that the core we're testing is gone, gone, gone. 
-        checkNotInCores(cc, coreName);
+        checkNotInCores(cc, Arrays.asList(coreName));
         
         // Load the core up again.
         SolrCore core = cc.getCore(coreName);


[39/58] [abbrv] lucene-solr:jira/solr-10879: LUCENE-7887: don't clear BufferedUpdatesStream on abort

Posted by ab...@apache.org.
LUCENE-7887: don't clear BufferedUpdatesStream on abort


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

Branch: refs/heads/jira/solr-10879
Commit: c9c0121d9399ff0009c51d6a32632dd0962e8c8f
Parents: cabb1fa
Author: Mike McCandless <mi...@apache.org>
Authored: Thu Jun 29 05:52:19 2017 -0400
Committer: Mike McCandless <mi...@apache.org>
Committed: Thu Jun 29 05:53:10 2017 -0400

----------------------------------------------------------------------
 .../java/org/apache/lucene/index/BufferedUpdatesStream.java    | 3 +++
 .../java/org/apache/lucene/index/FrozenBufferedUpdates.java    | 6 +-----
 lucene/core/src/java/org/apache/lucene/index/IndexWriter.java  | 2 --
 3 files changed, 4 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c9c0121d/lucene/core/src/java/org/apache/lucene/index/BufferedUpdatesStream.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/BufferedUpdatesStream.java b/lucene/core/src/java/org/apache/lucene/index/BufferedUpdatesStream.java
index 8c0a2be..07d2b66 100644
--- a/lucene/core/src/java/org/apache/lucene/index/BufferedUpdatesStream.java
+++ b/lucene/core/src/java/org/apache/lucene/index/BufferedUpdatesStream.java
@@ -175,11 +175,14 @@ class BufferedUpdatesStream implements Accountable {
     // TODO: would be a bit more memory efficient to track this per-segment, so when each segment writes it writes all packets finished for
     // it, rather than only recording here, across all segments.  But, more complex code, and more CPU, and maybe not so much impact in
     // practice?
+    assert packet.applied.getCount() == 1: "packet=" + packet;
 
     packet.applied.countDown();
 
     updates.remove(packet);
     numTerms.addAndGet(-packet.numTermDeletes);
+    assert numTerms.get() >= 0: "numTerms=" + numTerms + " packet=" + packet;
+    
     bytesUsed.addAndGet(-packet.bytesUsed);
 
     finishedSegment(packet.delGen());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c9c0121d/lucene/core/src/java/org/apache/lucene/index/FrozenBufferedUpdates.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/FrozenBufferedUpdates.java b/lucene/core/src/java/org/apache/lucene/index/FrozenBufferedUpdates.java
index d5d1de0..8248841 100644
--- a/lucene/core/src/java/org/apache/lucene/index/FrozenBufferedUpdates.java
+++ b/lucene/core/src/java/org/apache/lucene/index/FrozenBufferedUpdates.java
@@ -299,7 +299,6 @@ class FrozenBufferedUpdates {
           if (infoStream.isEnabled("BD")) {
             infoStream.message("BD", "packet matches no segments");
           }
-          
           break;
         }
 
@@ -422,10 +421,7 @@ class FrozenBufferedUpdates {
       throw new IllegalArgumentException("gen is not yet set; call BufferedUpdatesStream.push first");
     }
 
-    if (applied.getCount() == 0) {
-      // already done
-      return totalDelCount;
-    }
+    assert applied.getCount() != 0;
 
     if (privateSegment != null) {
       assert segStates.length == 1;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c9c0121d/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
----------------------------------------------------------------------
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
index 4870282..2ef928b 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
@@ -2364,8 +2364,6 @@ public class IndexWriter implements Closeable, TwoPhaseCommit, Accountable {
       // set it to false before calling rollbackInternal
       mergeScheduler.close();
 
-      bufferedUpdatesStream.clear();
-
       docWriter.close(); // mark it as closed first to prevent subsequent indexing actions/flushes 
       docWriter.abort(this); // don't sync on IW here
       synchronized(this) {


[19/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/ExpressionFactory.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/ExpressionFactory.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/ExpressionFactory.java
new file mode 100644
index 0000000..b59469f
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/ExpressionFactory.java
@@ -0,0 +1,821 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.solr.analytics.function.MergingReductionCollectionManager;
+import org.apache.solr.analytics.function.ReductionCollectionManager;
+import org.apache.solr.analytics.function.mapping.*;
+import org.apache.solr.analytics.function.mapping.CompareFunction.EqualFunction;
+import org.apache.solr.analytics.function.mapping.CompareFunction.GTEFunction;
+import org.apache.solr.analytics.function.mapping.CompareFunction.GTFunction;
+import org.apache.solr.analytics.function.mapping.CompareFunction.LTEFunction;
+import org.apache.solr.analytics.function.mapping.CompareFunction.LTFunction;
+import org.apache.solr.analytics.function.mapping.ConcatFunction.ConcatSeparatedFunction;
+import org.apache.solr.analytics.function.mapping.NumericConvertFunction.CeilingFunction;
+import org.apache.solr.analytics.function.mapping.NumericConvertFunction.FloorFunction;
+import org.apache.solr.analytics.function.mapping.NumericConvertFunction.RoundFunction;
+import org.apache.solr.analytics.function.mapping.LogicFunction.AndFunction;
+import org.apache.solr.analytics.function.mapping.LogicFunction.OrFunction;
+import org.apache.solr.analytics.function.reduction.*;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.value.*;
+import org.apache.solr.analytics.value.AnalyticsValueStream.ExpressionType;
+import org.apache.solr.analytics.value.constant.ConstantValue;
+import org.apache.solr.analytics.function.field.*;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.schema.BoolField;
+import org.apache.solr.schema.DatePointField;
+import org.apache.solr.schema.DoublePointField;
+import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.FloatPointField;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.schema.IntPointField;
+import org.apache.solr.schema.LongPointField;
+import org.apache.solr.schema.SchemaField;
+import org.apache.solr.schema.StrField;
+import org.apache.solr.schema.TrieDateField;
+import org.apache.solr.schema.TrieDoubleField;
+import org.apache.solr.schema.TrieFloatField;
+import org.apache.solr.schema.TrieIntField;
+import org.apache.solr.schema.TrieLongField;
+
+/**
+ * A factory to parse and create expressions, and capture information about those expressions along the way.
+ * 
+ * <p>
+ * In order to use, first call {@link #startRequest()} and create all ungrouped expressions,
+ * then call {@link #createReductionManager} to get the ungrouped reduction manager.
+ * <br>
+ * Then for each grouping call {@link #startGrouping()} first then create all expressions within that grouping,
+ * finally calling {@link #createGroupingReductionManager}  to get the reduction manager for that grouping.
+ */
+public class ExpressionFactory {
+  private static final Pattern functionNamePattern = Pattern.compile("^\\s*([^().\\s]+)\\s*(?:\\(.*\\)\\s*)?$", Pattern.CASE_INSENSITIVE);
+  private static final Pattern functionParamsPattern = Pattern.compile("^\\s*(?:[^(.)]+)\\s*\\(\\s*(.+)\\s*\\)\\s*$", Pattern.CASE_INSENSITIVE);
+  private static final String funtionVarParamUniqueName = ".%s_(%d)";
+
+  /**
+   * Used to denote a variable length parameter.
+   */
+  public final static String variableLengthParamSuffix = "..";
+  /**
+   * The character used to denote the start of a for each lambda expression
+   */
+  public final static char variableForEachSep = ':';
+  /**
+   * The character used to denote the looped parameter in the for each lambda expression
+   */
+  public final static char variableForEachParam = '_';
+
+  private HashMap<String, VariableFunctionInfo> systemVariableFunctions;
+  private HashMap<String, VariableFunctionInfo> variableFunctions;
+  private HashSet<String> variableFunctionNameHistory;
+  
+  private HashMap<String, CreatorFunction> expressionCreators;
+  private final ConstantFunction constantCreator;
+  
+  private LinkedHashMap<String, ReductionFunction> reductionFunctions;
+  private LinkedHashMap<String, ReductionDataCollector<?>> collectors;
+  private LinkedHashMap<String, AnalyticsField> fields;
+  private HashMap<String, AnalyticsValueStream> expressions;
+  
+  private IndexSchema schema;
+  
+  private Map<String, ReductionDataCollector<?>> groupedCollectors;
+  private Map<String, AnalyticsField> groupedFields;
+  private boolean isGrouped;
+
+  public ExpressionFactory(IndexSchema schema) {
+    this.schema = schema;
+    
+    expressionCreators = new HashMap<>();
+    systemVariableFunctions = new HashMap<>();
+    
+    constantCreator = ConstantValue.creatorFunction;
+    addSystemFunctions();
+  }
+  
+  /**
+   * Get the index schema used by this factory.
+   * 
+   * @return the index schema
+   */
+  public IndexSchema getSchema() {
+    return schema;
+  }
+  
+  /**
+   * Prepare the factory to start building the request.
+   */
+  public void startRequest() {
+    reductionFunctions = new LinkedHashMap<>();
+    collectors = new LinkedHashMap<>();
+    fields = new LinkedHashMap<>();
+    expressions = new HashMap<>();
+
+    variableFunctions = new HashMap<>();
+    variableFunctions.putAll(systemVariableFunctions);
+    variableFunctionNameHistory = new HashSet<>();
+    
+    isGrouped = false;
+  }
+  
+  /**
+   * Prepare the factory to start building the next grouping.
+   * <br>
+   * NOTE: MUST be called before each new grouping.
+   */
+  public void startGrouping() {
+    groupedCollectors = new HashMap<>();
+    groupedFields = new HashMap<>();
+    
+    isGrouped = true;
+  }
+
+  /**
+   * Add a system function to the expression factory.
+   * This will be treated as a native function and not a variable function.
+   * 
+   * @param functionName the unique name for the function
+   * @param functionCreator the creator function to generate an expression
+   * @return this factory, to easily chain function adds
+   * @throws SolrException if the functionName is not unique
+   */
+  public ExpressionFactory addSystemFunction(final String functionName, final CreatorFunction functionCreator) throws SolrException {
+    if (expressionCreators.containsKey(functionName)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"System function " + functionName + " defined twice.");
+    }
+    expressionCreators.put(CountFunction.name, CountFunction.creatorFunction);
+    return this;
+  }
+
+  /**
+   * Add a variable function that will be treated like a system function.
+   * 
+   * @param functionSignature the function signature of the variable function (e.g. {@code func(a,b)} )
+   * @param returnSignature the return signature of the variable function (e.g. {@code div(sum(a,b),count(b))} )
+   * @return this factory, to easily chain function adds
+   * @throws SolrException if the name of the function is not unique or the syntax of either signature is incorrect
+   */
+  public ExpressionFactory addSystemVariableFunction(final String functionSignature, final String returnSignature) throws SolrException {
+    return addVariableFunction(functionSignature, returnSignature, systemVariableFunctions);
+  }
+
+  /**
+   * Add a variable function that was defined in an analytics request.
+   * 
+   * @param functionSignature the function signature of the variable function (e.g. {@code func(a,b)} )
+   * @param returnSignature the return signature of the variable function (e.g. {@code div(sum(a,b),count(b))} )
+   * @return this factory, to easily chain function adds
+   * @throws SolrException if the name of the function is not unique or the syntax of either signature is incorrect
+   */
+  public ExpressionFactory addUserDefinedVariableFunction(final String functionSignature, final String returnSignature) throws SolrException {
+    return addVariableFunction(functionSignature, returnSignature, variableFunctions);
+  }
+  
+  /**
+   * Add a variable function to the given map of variable functions. 
+   * 
+   * @param functionSignature the function signature of the variable function (e.g. {@code func(a,b)} )
+   * @param returnSignature the return signature of the variable function (e.g. {@code div(sum(a,b),count(b))} )
+   * @param variableFunctions the map of variable functions to add the new function to
+   * @return this factory, to easily chain function adds
+   * @throws SolrException if the name of the function is not unique or the syntax of either signature is incorrect
+   */
+  private ExpressionFactory addVariableFunction(final String functionSignature,
+                                                final String returnSignature,
+                                                Map<String,VariableFunctionInfo> variableFunctions) throws SolrException {
+    String functionName = getFunctionName(functionSignature);
+    if (expressionCreators.containsKey(functionName)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"Users cannot define a variable function with the same name as an existing function: " + functionName);
+    }
+    VariableFunctionInfo varFuncInfo = new VariableFunctionInfo();
+    varFuncInfo.params = getParams(functionSignature, null, null);
+    varFuncInfo.returnSignature = returnSignature;
+    variableFunctions.put(functionName, varFuncInfo);
+    return this;
+  }
+
+  /**
+   * Create a reduction manager to manage the collection of all expressions that have been created since
+   * {@link #startRequest()} was called.
+   * 
+   * @param isCloudCollection whether the request is a distributed request
+   * @return a reduction manager
+   */
+  public ReductionCollectionManager createReductionManager(boolean isCloudCollection) {
+    ReductionDataCollector<?>[] collectorsArr = new ReductionDataCollector<?>[collectors.size()];
+    collectors.values().toArray(collectorsArr);
+    if (isCloudCollection) {
+      return new MergingReductionCollectionManager(collectorsArr, fields.values());
+    } else {
+      return new ReductionCollectionManager(collectorsArr, fields.values());
+    }
+  }
+
+  /**
+   * Create a reduction manager to manage the collection of all expressions that have been created since
+   * {@link #startGrouping()} was called.
+   * 
+   * @param isCloudCollection whether the request is a distributed request
+   * @return a reduction manager
+   */
+  public ReductionCollectionManager createGroupingReductionManager(boolean isCloudCollection) {
+    ReductionDataCollector<?>[] collectorsArr = new ReductionDataCollector<?>[groupedCollectors.size()];
+    groupedCollectors.values().toArray(collectorsArr);
+    if (isCloudCollection) {
+      return new MergingReductionCollectionManager(collectorsArr, groupedFields.values());
+    } else {
+      return new ReductionCollectionManager(collectorsArr, groupedFields.values());
+    }
+  }
+  
+  /**
+   * Parse and build an expression from the given expression string.
+   * 
+   * @param expressionStr string that represents the desired expression
+   * @return the object representation of the expression
+   * @throws SolrException if an error occurs while constructing the expression
+   */
+  public AnalyticsValueStream createExpression(String expressionStr) throws SolrException {
+    return createExpression(expressionStr, new HashMap<>(), null, null);
+  }
+
+  /**
+   * Create an expression from the given expression string, with the given variable function information.
+   * 
+   * @param expressionStr string that represents the desired expression
+   * @param varFuncParams the current set of variable function parameters and their values. If this expression is not a variable function
+   * return signature, the map should be empty.
+   * @param varFuncVarParamName if the current expression is a variable function return signature, this must be the name of the variable length
+   * parameter if it is included in the function signature.
+   * @param varFuncVarParamValues if the current expression is a variable function return signature, this must be the array values of the variable length
+   * parameter if they are included when calling the function.
+   * @return the object representation of the expression
+   * @throws SolrException if an error occurs while constructing the expression
+   */
+  private AnalyticsValueStream createExpression(String expressionStr, Map<String,AnalyticsValueStream> varFuncParams,
+                                                String varFuncVarParamName, String[] varFuncVarParamValues) throws SolrException {
+    AnalyticsValueStream expression;
+    expressionStr = expressionStr.trim();
+    
+    boolean isField = false;
+    try {
+      // Try to make a constant value
+      expression = constantCreator.apply(expressionStr);
+    } catch (SolrException e1) {
+      // Not a constant
+      // If the expression has parens, it is an expression otherwise it is a field
+      if (!expressionStr.contains("(")) {
+        try {
+          // Try to make a field out of it
+          expression = createField(schema.getField(expressionStr));
+          isField = true;
+        } catch (SolrException e2) {
+          throw new SolrException(ErrorCode.BAD_REQUEST,"The following is not a field, constant or function : " + expressionStr); 
+        }  
+      } else {
+        // Must be a function
+        expression = createFunction(expressionStr, varFuncParams, varFuncVarParamName, varFuncVarParamValues);
+      }
+    }
+
+    // Try to use an already made expression instead of the new one.
+    // This will decrease the amount of collection needed to be done.
+    if (expressions.containsKey(expression.getExpressionStr())) {
+      expression = expressions.get(expression.getExpressionStr());
+      // If this is a grouped expression, make sure that the reduction info for the expression is included in the grouped reduction manager.
+      if (expression.getExpressionType() == ExpressionType.REDUCTION && isGrouped) {
+        ((ReductionFunction)expression).synchronizeDataCollectors( collector -> {
+          groupedCollectors.put(collector.getExpressionStr(), collector);
+          return collector;
+        });
+      }
+    }
+    else {
+      expressions.put(expression.getExpressionStr(), expression);
+      // Make sure that the reduction info for the expression is included in the reduction manager and grouped reduction manager if necessary.
+      if (expression.getExpressionType() == ExpressionType.REDUCTION) {
+        reductionFunctions.put(expression.getExpressionStr(), (ReductionFunction)expression);
+        ((ReductionFunction)expression).synchronizeDataCollectors( collector -> {
+          String collectorStr = collector.getExpressionStr();
+          ReductionDataCollector<?> usedCollector = collectors.get(collectorStr);
+          if (usedCollector == null) {
+            usedCollector = collector;
+            collectors.put(collectorStr, collector);
+          }
+          if (isGrouped) {
+            groupedCollectors.put(collectorStr, usedCollector);
+          }
+          return usedCollector;
+        });
+      }
+      // Add the field info to the reduction manager
+      if (isField) {
+        fields.put(expression.getExpressionStr(), (AnalyticsField)expression);
+      }
+    }
+    // If this is a grouped expression, make sure that the field info is included in the grouped reduction manager.
+    if (isField && isGrouped) {
+      groupedFields.put(expression.getExpressionStr(), (AnalyticsField)expression);
+    }
+    return expression;
+  }
+  
+  /**
+   * Create a function expression from the given expression string, with the given variable function information.
+   * 
+   * @param expressionStr string that represents the desired expression
+   * @param varFuncParams the current set of variable function parameters and their values. If this expression is not a variable function
+   * return signature, the map should be empty.
+   * @param varFuncVarParamName if the current expression is a variable function return signature, this must be the name of the variable length
+   * parameter if it is included in the function signature.
+   * @param varFuncVarParamValues if the current expression is a variable function return signature, this must be the array values of the variable length
+   * parameter if they are included when calling the function.
+   * @return the object representation of the expression
+   * @throws SolrException if an error occurs while constructing the expression
+   */
+  private AnalyticsValueStream createFunction(String expressionStr, Map<String,AnalyticsValueStream> varFuncParams,
+                                              String varFuncVarParamName, String[] varFuncVarParamValues) throws SolrException {
+    AnalyticsValueStream expression = null;
+    String name = getFunctionName(expressionStr);
+
+    final String[] params = getParams(expressionStr, varFuncVarParamName, varFuncVarParamValues);
+    AnalyticsValueStream[] paramStreams = new AnalyticsValueStream[params.length];
+    for (int i = 0; i < params.length; i++) {
+      // First check if the parameter is a variable function variable otherwise create the expression
+      if (varFuncParams.containsKey(params[i])) {
+        paramStreams[i] = varFuncParams.get(params[i]);
+      } else {
+        paramStreams[i] = createExpression(params[i], varFuncParams, varFuncVarParamName, varFuncVarParamValues);
+      }
+    }
+    // Check to see if the function name is a variable function name, if so apply the variables to the return signature
+    if (variableFunctions.containsKey(name)) {
+      if (variableFunctionNameHistory.contains(name)) {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The following variable function is self referencing : " + name); 
+      }
+      variableFunctionNameHistory.add(name);
+      VariableFunctionInfo newVarFunc = variableFunctions.get(name);
+      Map<String, AnalyticsValueStream> newVarFuncParams = new HashMap<>();
+      
+      boolean varLenEnd = false;
+      
+      for (int i = 0; i < newVarFunc.params.length; ++i) {
+        String variable = newVarFunc.params[i];
+        if (variable.endsWith(variableLengthParamSuffix)) {
+          if (i != newVarFunc.params.length - 1) {
+            throw new SolrException(ErrorCode.BAD_REQUEST,"The following invocation of a variable function has the incorrect number of arguments : " + expressionStr);
+          }
+          variable = variable.substring(0, variable.length() - variableLengthParamSuffix.length()).trim();
+          int numVars = paramStreams.length - i;
+          String[] newVarFuncVarParamValues = new String[numVars];
+          for (int j = 0; j < numVars; ++j) {
+            // Create a new name for each variable length parameter value
+            String paramName = String.format(Locale.ROOT, funtionVarParamUniqueName, variable, j);
+            newVarFuncVarParamValues[j] = paramName;
+            newVarFuncParams.put(paramName, paramStreams[i + j]);
+          }
+          expression = createFunction(newVarFunc.returnSignature, newVarFuncParams, variable, newVarFuncVarParamValues);
+          varLenEnd = true;
+        } else {
+          newVarFuncParams.put(variable, paramStreams[i]);
+        }
+      }
+      if (!varLenEnd) {
+        expression = createExpression(newVarFunc.returnSignature, newVarFuncParams, null, null);
+      }
+      variableFunctionNameHistory.remove(name);
+      return expression;
+    } else if (expressionCreators.containsKey(name)) {
+      // It is a regular system function
+      expression = expressionCreators.get(name).apply(paramStreams);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The following function does not exist: " + name);
+    }
+    return expression;
+  }
+
+  /**
+   * Create an {@link AnalyticsField} out of the given {@link SchemaField}.
+   * <p>
+   * Currently only fields with doc-values enabled are supported.
+   * 
+   * @param field the field to convert for analytics
+   * @return an analytics representation of the field
+   * @throws SolrException if the field is not supported by the analytics framework
+   */
+  private AnalyticsField createField(SchemaField field) throws SolrException {
+    String fieldName = field.getName();
+    if (fields.containsKey(fieldName)) {
+      return fields.get(fieldName);
+    }
+    if (!field.hasDocValues()) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The field "+fieldName+" does not have docValues enabled.");
+    }
+    boolean multivalued = field.multiValued();
+    FieldType fieldType = field.getType();
+    AnalyticsField aField;
+    if (fieldType instanceof BoolField) {
+      if (multivalued) {
+        aField = new BooleanMultiField(fieldName);
+      } else {
+        aField = new BooleanField(fieldName);
+      }
+    } else if (fieldType instanceof TrieIntField) {
+      if (multivalued) {
+        aField = new IntMultiField(fieldName);
+      } else {
+        aField = new IntField(fieldName);
+      }
+    } else if (fieldType instanceof IntPointField) {
+      if (multivalued) {
+        aField = new IntMultiPointField(fieldName);
+      } else {
+        aField = new IntField(fieldName);
+      }
+    } else if (fieldType instanceof TrieLongField) {
+      if (multivalued) {
+        aField = new LongMultiField(fieldName);
+      } else {
+        aField = new LongField(fieldName);
+      }
+    } else if (fieldType instanceof LongPointField) {
+      if (multivalued) {
+        aField = new LongMultiPointField(fieldName);
+      } else {
+        aField = new LongField(fieldName);
+      }
+    } else if (fieldType instanceof TrieFloatField) {
+      if (multivalued) {
+        aField = new FloatMultiField(fieldName);
+      } else {
+        aField = new FloatField(fieldName);
+      }
+    } else if (fieldType instanceof FloatPointField) {
+      if (multivalued) {
+        aField = new FloatMultiPointField(fieldName);
+      } else {
+        aField = new FloatField(fieldName);
+      }
+    } else if (fieldType instanceof TrieDoubleField) {
+      if (multivalued) {
+        aField = new DoubleMultiField(fieldName);
+      } else {
+        aField = new DoubleField(fieldName);
+      }
+    } else if (fieldType instanceof DoublePointField) {
+      if (multivalued) {
+        aField = new DoubleMultiPointField(fieldName);
+      } else {
+        aField = new DoubleField(fieldName);
+      }
+    } else if (fieldType instanceof TrieDateField) {
+      if (multivalued) {
+        aField = new DateMultiField(fieldName);
+      } else {
+        aField = new DateField(fieldName);
+      }
+    } else if (fieldType instanceof DatePointField) {
+      if (multivalued) {
+        aField = new DateMultiPointField(fieldName);
+      } else {
+        aField = new DateField(fieldName);
+      }
+    } else if (fieldType instanceof StrField) {
+      if (multivalued) {
+        aField = new StringMultiField(fieldName);
+      } else {
+        aField = new StringField(fieldName);
+      }
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"FieldType of the following field not supported by analytics: "+fieldName);
+    }
+    return aField;
+  }
+
+  /**
+   * Get the name of the top function used in the given expression.
+   * 
+   * @param expression the expression to find the function name of
+   * @return the name of the function 
+   * @throws SolrException if the expression has incorrect syntax
+   */
+  private static String getFunctionName(String expression) throws SolrException {
+    Matcher m = functionNamePattern.matcher(expression);
+    if (!m.matches()) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The following function has no name: " + expression);
+    }
+    String name = m.group(1);
+    return name;
+  }
+  
+  /**
+   * Get the params of a function.
+   * 
+   * @param function the function to parse
+   * @return an array of param strings
+   * @throws SolrException if the function has incorrect syntax
+   */
+  private static String[] getFunctionParams(String function) throws SolrException {
+    return getParams(function, null, null);
+  }
+
+  /**
+   * Parse a function expression string and break up the parameters of the function into separate strings.
+   * <p>
+   * The parsing replaces the variable length parameter, and lambda for-each's using the variable length parameter,
+   * with the parameter values in the returned parameter string.
+   * <p>
+   * Parsing breaks up parameters by commas (',') and ignores ',' inside of extra parens and quotes (both ' and "), since these commas are either
+   * splitting up the parameters of nested functions or are apart of strings.
+   * <br>
+   * The only escaping that needs to be done is " within a double quote string and ' within a single quote string and \ within any string.
+   * For example\:
+   * <ul>
+   * <li> {@code func("This is \" the \\ escaping ' example")} will be treated as {@code func(This is " the \ escaping ' example)}
+   * <li> {@code func('This is " the \\ escaping \' example')} will be treated as {@code func(This is " the \ escaping ' example)}
+   * </ul>
+   * In string constants the \ character is used to escape quotes, so it can never be used alone. in order to write a \ you must write \\
+   * 
+   * @param expression the function expression to parse
+   * @param varLengthParamName the name of the variable length parameter that is used in the expression, pass null if none is used.
+   * @param varLengthParamValues the values of the variable length parameter that are used in the expression, pass null if none are used.
+   * @return the parsed and split arguments to the function
+   * @throws SolrException if the expression has incorrect syntax.
+   */
+  private static String[] getParams(String expression, String varLengthParamName, String[] varLengthParamValues) throws SolrException {
+    Matcher m = functionParamsPattern.matcher(expression);
+    if (!m.matches()) {
+      return new String[0];
+    }
+    String paramsStr = m.group(1);
+    
+    ArrayList<String> paramsList = new ArrayList<String>();
+    StringBuilder param = new StringBuilder();
+    
+    // Variables to help while filling out the values of for-each lambda functions.
+    boolean inForEach = false;
+    int forEachStart = -1;
+    int forEachIter = -1;
+    int forEachLevel = -1;
+    
+    // The current level of nested parenthesis, 0 means the iteration is in no nested parentheses
+    int parenCount = 0;
+    // If the iteration is currently in a single-quote string constant
+    boolean singleQuoteOn = false;
+    // If the iteration is currently in a double-quote string constant
+    boolean doubleQuoteOn = false;
+    // If the iteration is currently in any kind of string constant
+    boolean quoteOn = false;
+    // Is the next character escaped.
+    boolean escaped = false;
+    
+    char[] chars = paramsStr.toCharArray();
+    
+    // Iterate through every character, building the params one at a time
+    for (int i = 0; i < chars.length; ++i) {
+      char c = chars[i];
+      
+      if (c == ' ' && !quoteOn) {
+        // Ignore white space that is not in string constants
+        continue;
+      } else if (c == ',' && parenCount == 0 && !quoteOn) {
+        // This signifies the end of one parameter and the start of another, since we are not in a nested parenthesis or a string constant
+        String paramStr = param.toString();
+        if (paramStr.length() == 0) {
+          throw new SolrException(ErrorCode.BAD_REQUEST,"Empty parameter in expression: " + expression);
+        }
+        // check to see if the parameter is a variable length parameter
+        if (paramStr.equals(varLengthParamName)) {
+          // Add every variable length parameter value, since there are a variable amount
+          for (String paramName : varLengthParamValues) {
+            paramsList.add(paramName);
+          }
+        } else {
+          paramsList.add(paramStr);
+        }
+        
+        param.setLength(0);
+        continue;
+      } else if (c == ',' && !quoteOn && inForEach) {
+        // separate the for each parameters, so they can be replaced with the result of the for each
+        if (param.charAt(param.length()-1) == variableForEachParam && 
+            (param.charAt(param.length()-2) == '(' || param.charAt(param.length()-2) == ',')) {
+          param.setLength(param.length()-1);
+          param.append(varLengthParamValues[forEachIter++]);
+        }
+      } else if (c == '"' && !singleQuoteOn) {
+        // Deal with escaping, or ending string constants
+        if (doubleQuoteOn && !escaped) {
+          doubleQuoteOn = false;
+          quoteOn = false;
+        } else if (!quoteOn) {
+          doubleQuoteOn = true;
+          quoteOn = true;
+        } else {
+          // only happens if escaped is true
+          escaped = false;
+        }
+      }  else if (c== '\'' && !doubleQuoteOn) {
+        // Deal with escaping, or ending string constants
+        if (singleQuoteOn && !escaped) {
+          singleQuoteOn = false;
+          quoteOn = false;
+        } else if (!singleQuoteOn) {
+          singleQuoteOn = true;
+          quoteOn = true;
+        } else {
+          // only happens if escaped is true
+          escaped = false;
+        }
+      } else if (c == '(' && !quoteOn) {
+        // Reached a further level of nested parentheses
+        parenCount++;
+      } else if (c == ')' && !quoteOn) {
+        // Returned from a level of nested parentheses
+        parenCount--;
+        if (parenCount < 0) {
+          throw new SolrException(ErrorCode.BAD_REQUEST,"The following expression has extra end parens: " + param.toString());
+        }
+        if (inForEach) {
+          if (param.charAt(param.length()-1) == variableForEachParam && 
+              (param.charAt(param.length()-2) == '(' || param.charAt(param.length()-2) == ',')) {
+            param.setLength(param.length()-1);
+            param.append(varLengthParamValues[forEachIter++]);
+          }
+          if (forEachLevel == parenCount) {
+            // at the end of the for-each start the parsing of the for-each again, with the next value of the variable length parameter
+            if (forEachIter == 0) {
+              throw new SolrException(ErrorCode.BAD_REQUEST,"For each statement for variable '" + varLengthParamName + "' has no use of lambda variable " + variableForEachParam);
+            } else if (forEachIter < varLengthParamValues.length) {
+              if (parenCount == 0) {
+                param.append(')');
+                paramsList.add(param.toString());
+                param.setLength(0);
+              } else {
+                param.append(')');
+                param.append(',');
+              }
+              i = forEachStart;
+              continue;
+            } else {
+              inForEach = false;
+            }
+          }
+        }
+      }
+      if (c == '\\') {
+        // Escaping or escaped backslash
+        if (!quoteOn) {
+          throw new SolrException(ErrorCode.BAD_REQUEST,"The following expression has escaped characters outside of quotation marks: " + expression.toString());
+        }
+        if (escaped) {
+          escaped = false;
+        } else {
+          escaped = true;
+          if (parenCount == 0) {
+            continue;
+          }
+        }
+      } else if (escaped) {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"Invalid escape character '" + c + "' used in the following expression: " + expression.toString());
+      }
+      if (c == variableForEachSep && !quoteOn && varLengthParamName != null) {
+        int varStart = param.length()-varLengthParamName.length();
+        if (param.subSequence(varStart, param.length()).equals(varLengthParamName)) {
+          inForEach = true;
+          forEachStart = i;
+          forEachIter = 0;
+          forEachLevel = parenCount;
+          param.setLength(varStart);
+          continue;
+        }
+        throw new SolrException(ErrorCode.BAD_REQUEST,"For-each called on invalid parameter '" + param.toString().trim());
+      }
+      param.append(c);
+    }
+    String paramStr = param.toString().trim();
+    if (paramStr.length() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"Empty parameter in expression: " + expression);
+    }
+    if (parenCount > 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The following expression needs more end parens: " + param.toString());
+    }
+    if (quoteOn) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"Misplaced quotation marks in expression: " + expression);
+    }
+    if (paramStr.equals(varLengthParamName)) {
+      for (String paramName : varLengthParamValues) {
+        paramsList.add(paramName);
+      }
+    } else {
+      paramsList.add(paramStr);
+    }
+    return paramsList.toArray(new String[paramsList.size()]);
+  }
+  
+  /**
+   * Add the natively supported functionality.
+   */
+  public void addSystemFunctions() {
+    // Mapping Functions
+    expressionCreators.put(AbsoluteValueFunction.name, AbsoluteValueFunction.creatorFunction);
+    expressionCreators.put(AndFunction.name, AndFunction.creatorFunction);
+    expressionCreators.put(AddFunction.name, AddFunction.creatorFunction);
+    expressionCreators.put(BottomFunction.name, BottomFunction.creatorFunction);
+    expressionCreators.put(CeilingFunction.name, CeilingFunction.creatorFunction);
+    expressionCreators.put(ConcatFunction.name, ConcatFunction.creatorFunction);
+    expressionCreators.put(ConcatSeparatedFunction.name, ConcatSeparatedFunction.creatorFunction);
+    expressionCreators.put(DateMathFunction.name, DateMathFunction.creatorFunction);
+    expressionCreators.put(DateParseFunction.name, DateParseFunction.creatorFunction);
+    expressionCreators.put(DivideFunction.name, DivideFunction.creatorFunction);
+    expressionCreators.put(DocCountFunction.name, DocCountFunction.creatorFunction);
+    expressionCreators.put(EqualFunction.name,EqualFunction.creatorFunction);
+    expressionCreators.put(FillMissingFunction.name, FillMissingFunction.creatorFunction);
+    expressionCreators.put(FilterFunction.name, FilterFunction.creatorFunction);
+    expressionCreators.put(FloorFunction.name, FloorFunction.creatorFunction);
+    expressionCreators.put(GTFunction.name,GTFunction.creatorFunction);
+    expressionCreators.put(GTEFunction.name,GTEFunction.creatorFunction);
+    expressionCreators.put(IfFunction.name, IfFunction.creatorFunction);
+    expressionCreators.put(JoinFunction.name, JoinFunction.creatorFunction);
+    expressionCreators.put(LogFunction.name,LogFunction.creatorFunction);
+    expressionCreators.put(LTFunction.name,LTFunction.creatorFunction);
+    expressionCreators.put(LTEFunction.name,LTEFunction.creatorFunction);
+    expressionCreators.put(MultFunction.name, MultFunction.creatorFunction);
+    expressionCreators.put(NegateFunction.name, NegateFunction.creatorFunction);
+    expressionCreators.put(OrFunction.name, OrFunction.creatorFunction);
+    expressionCreators.put(PowerFunction.name, PowerFunction.creatorFunction);
+    expressionCreators.put(ReplaceFunction.name, ReplaceFunction.creatorFunction);
+    expressionCreators.put(RemoveFunction.name, RemoveFunction.creatorFunction);
+    expressionCreators.put(RoundFunction.name, RoundFunction.creatorFunction);
+    expressionCreators.put(StringCastFunction.name, StringCastFunction.creatorFunction);
+    expressionCreators.put(SubtractFunction.name, SubtractFunction.creatorFunction);
+    expressionCreators.put(TopFunction.name, TopFunction.creatorFunction);
+    
+    // Reduction Functions
+    expressionCreators.put(CountFunction.name, CountFunction.creatorFunction);
+    expressionCreators.put(MaxFunction.name, MaxFunction.creatorFunction);
+    expressionCreators.put(MedianFunction.name, MedianFunction.creatorFunction);
+    expressionCreators.put(MinFunction.name, MinFunction.creatorFunction);
+    expressionCreators.put(MissingFunction.name, MissingFunction.creatorFunction);
+    expressionCreators.put(OrdinalFunction.name, OrdinalFunction.creatorFunction);
+    expressionCreators.put(PercentileFunction.name, PercentileFunction.creatorFunction);
+    expressionCreators.put(SumFunction.name, SumFunction.creatorFunction);
+    expressionCreators.put(UniqueFunction.name, UniqueFunction.creatorFunction);
+    
+    // Variables
+    addSystemVariableFunction("wmean(a,b)","div(mean(prod(a,b)),sum(b))");
+    addSystemVariableFunction("mean(a)","div(sum(a),count(a))");
+    addSystemVariableFunction("sumofsquares(a)","sum(pow(a,2))");
+    addSystemVariableFunction("sqrt(a)","pow(a,0.5)");
+    addSystemVariableFunction("variance(a)","sub(mean(pow(a,2)),pow(mean(a),2))");
+    addSystemVariableFunction("stddev(a)","sqrt(variance(a))");
+    addSystemVariableFunction("csv(a..)","concatsep(',',a)");
+    addSystemVariableFunction("csv_output(a..)","concatsep(',',a:fillmissing(join(_,';'),''))");
+  }
+
+  /**
+   * Used for system analytics functions for initialization. Should take in a list of expression parameters and return an expression.
+   */
+  @FunctionalInterface
+  public static interface CreatorFunction {
+    AnalyticsValueStream apply(AnalyticsValueStream[] t) throws SolrException;
+  }
+  /**
+   * Used to initialize analytics constants.
+   */
+  @FunctionalInterface
+  public static interface ConstantFunction {
+    AnalyticsValueStream apply(String t) throws SolrException;
+  }
+}
+class VariableFunctionInfo {
+  public String[] params;
+  public String returnSignature;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/BasicAccumulator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/BasicAccumulator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/BasicAccumulator.java
deleted file mode 100644
index cbd8078..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/BasicAccumulator.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.accumulator;
-
-import java.io.IOException;
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Supplier;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.solr.analytics.expression.Expression;
-import org.apache.solr.analytics.expression.ExpressionFactory;
-import org.apache.solr.analytics.request.AnalyticsRequest;
-import org.apache.solr.analytics.request.ExpressionRequest;
-import org.apache.solr.analytics.statistics.StatsCollector;
-import org.apache.solr.analytics.statistics.StatsCollectorSupplierFactory;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.search.DocSet;
-import org.apache.solr.search.SolrIndexSearcher;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A <code>BasicAccumulator</code> manages the ValueCounters and Expressions without regard to Facets.
- */
-public class BasicAccumulator extends ValueAccumulator {
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-  protected final SolrIndexSearcher searcher;
-  protected final AnalyticsRequest request;
-  protected final DocSet docs;
-  protected final Supplier<StatsCollector[]> statsCollectorArraySupplier;
-  protected final StatsCollector[] statsCollectors;
-  protected final Expression[] expressions;
-  protected final String[] expressionNames;
-  protected final String[] expressionStrings;
-  protected final Set<String> hiddenExpressions;
-  protected LeafReaderContext context = null;
-  
-  public BasicAccumulator(SolrIndexSearcher searcher, DocSet docs, AnalyticsRequest request) throws IOException {
-    this.searcher = searcher;
-    this.docs = docs;
-    this.request = request;
-    final List<ExpressionRequest> exRequests = new ArrayList<ExpressionRequest>(request.getExpressions()); // make a copy here
-    Collections.sort(exRequests);
-    log.info("Processing request '"+request.getName()+"'");
-    statsCollectorArraySupplier = StatsCollectorSupplierFactory.create(searcher.getSchema(), exRequests);
-    statsCollectors = statsCollectorArraySupplier.get();
-    int size = exRequests.size();
-    expressionNames = new String[size];
-    expressionStrings = new String[size];
-    int count = 0;
-    for (ExpressionRequest expRequest : exRequests) {
-      expressionNames[count] = expRequest.getName();
-      expressionStrings[count++] = expRequest.getExpressionString();
-    }
-    expressions = makeExpressions(statsCollectors);
-    hiddenExpressions = request.getHiddenExpressions();
-  }
-  
-  @Override
-  protected void doSetNextReader(LeafReaderContext context) throws IOException {
-    this.context = context;
-    for (StatsCollector counter : statsCollectors) {
-      counter.setNextReader(context);
-    }
-  }
- 
-  public static BasicAccumulator create(SolrIndexSearcher searcher, DocSet docs, AnalyticsRequest request) throws IOException {
-    return new BasicAccumulator(searcher,docs,request);
-  }
-  
-  /**
-   * Passes the documents on to the {@link StatsCollector}s to be collected.
-   * @param doc Document to collect from
-   */
-  @Override
-  public void collect(int doc) throws IOException {
-    for (StatsCollector statsCollector : statsCollectors) {
-      statsCollector.collect(doc);
-    }
-  }
-  
-  @Override
-  public void compute() {
-    for (StatsCollector statsCollector : statsCollectors) {
-      statsCollector.compute();
-    }
-  }
-  
-  public NamedList<?> export(){
-    NamedList<Object> base = new NamedList<>();
-    for (int count = 0; count < expressions.length; count++) {
-      if (!hiddenExpressions.contains(expressionNames[count])) {
-        base.add(expressionNames[count], expressions[count].getValue());
-      }
-    }
-    return base;
-  }
-  
-  /**
-   * Builds an array of Expressions with the given list of counters
-   * @param statsCollectors the stats collectors
-   * @return The array of Expressions
-   */
-  public Expression[] makeExpressions(StatsCollector[] statsCollectors) {
-   Expression[] expressions = new Expression[expressionStrings.length];
-    for (int count = 0; count < expressionStrings.length; count++) {
-      expressions[count] = ExpressionFactory.create(expressionStrings[count], statsCollectors);
-    }
-    return expressions;
-  }
-  
-  /**
-   * Returns the value of an expression to use in a field or query facet.
-   * @param expressionName the name of the expression
-   * @return String String representation of pivot value
-   */
-  @SuppressWarnings({ "deprecation", "rawtypes" })
-  public String getResult(String expressionName) {
-    for (int count = 0; count < expressionNames.length; count++) {
-      if (expressionName.equals(expressionNames[count])) {
-        Comparable value = expressions[count].getValue();
-        if (value.getClass().equals(Date.class)) {
-          return ((Date)value).toInstant().toString();
-        } else {
-          return value.toString();
-        }
-      }
-    }
-    throw new SolrException(ErrorCode.BAD_REQUEST, "Pivot expression "+expressionName+" not found.");
-  }
-
-  /**
-   * Used for JMX stats collecting. Counts the number of stats requests
-   * @return number of unique stats collectors
-   */
-  public long getNumStatsCollectors() {
-    return statsCollectors.length;
-  }
-
-  /**
-   * Used for JMX stats collecting. Counts the number of queries in all query facets
-   * @return number of queries requested in all query facets.
-   */
-  public long getNumQueries() {
-    return 0l;
-  }
-  
-  @Override
-  public boolean needsScores() {
-    return true; // TODO: is this true?
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/FacetingAccumulator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/FacetingAccumulator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/FacetingAccumulator.java
deleted file mode 100644
index d8828a6..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/FacetingAccumulator.java
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.accumulator;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-
-import com.google.common.collect.Iterables;
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.search.BooleanClause.Occur;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.Query;
-import org.apache.solr.analytics.accumulator.facet.FacetValueAccumulator;
-import org.apache.solr.analytics.accumulator.facet.FieldFacetAccumulator;
-import org.apache.solr.analytics.accumulator.facet.QueryFacetAccumulator;
-import org.apache.solr.analytics.accumulator.facet.RangeFacetAccumulator;
-import org.apache.solr.analytics.expression.Expression;
-import org.apache.solr.analytics.expression.ExpressionFactory;
-import org.apache.solr.analytics.request.AnalyticsContentHandler;
-import org.apache.solr.analytics.request.AnalyticsRequest;
-import org.apache.solr.analytics.request.FieldFacetRequest;
-import org.apache.solr.analytics.request.FieldFacetRequest.FacetSortSpecification;
-import org.apache.solr.analytics.request.QueryFacetRequest;
-import org.apache.solr.analytics.request.RangeFacetRequest;
-import org.apache.solr.analytics.statistics.StatsCollector;
-import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.analytics.util.RangeEndpointCalculator;
-import org.apache.solr.analytics.util.RangeEndpointCalculator.FacetRange;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.schema.SchemaField;
-import org.apache.solr.search.DocSet;
-import org.apache.solr.search.Filter;
-import org.apache.solr.search.QParser;
-import org.apache.solr.search.SolrIndexSearcher;
-import org.apache.solr.search.SyntaxError;
-
-/**
- * A <code>FacetingAccumulator</code> manages the StatsCollectors and Expressions for facets.
- */
-public class FacetingAccumulator extends BasicAccumulator implements FacetValueAccumulator {
-  public static final String MISSING_VALUE = "(MISSING)";
-  protected boolean basicsAndFieldFacetsComputed;
-  protected int leafNum;
-  protected LeafReaderContext leaf;
-  protected final AnalyticsRequest analyticsRequest;
-  protected final Map<String,Map<String,Expression[]>> fieldFacetExpressions;
-  protected final Map<String,Map<String,Expression[]>> rangeFacetExpressions;
-  protected final Map<String,Map<String,Expression[]>> queryFacetExpressions;
-  protected final Map<String,Map<String,StatsCollector[]>> fieldFacetCollectors;
-  protected final Map<String,Map<String,StatsCollector[]>> rangeFacetCollectors;
-  protected final Map<String,Map<String,StatsCollector[]>> queryFacetCollectors;
-  protected final List<FieldFacetAccumulator> facetAccumulators;
-  protected final Set<String> hiddenFieldFacets;
-  /** the current value of this stat field */
-  protected final SolrQueryRequest queryRequest;
-  
-  protected List<RangeFacetRequest> rangeFacets = null;
-  protected List<QueryFacetRequest> queryFacets = null;
-  
-  protected long queryCount;
-  
-  public FacetingAccumulator(SolrIndexSearcher searcher, DocSet docs, AnalyticsRequest request, SolrQueryRequest queryRequest) throws IOException {
-    // The parent Basic Accumulator keeps track of overall stats while
-    // the Faceting Accumulator only manages the facet stats
-    super(searcher, docs, request);
-    this.analyticsRequest = request;
-    this.queryRequest = queryRequest;
-    basicsAndFieldFacetsComputed = false;
-    List<FieldFacetRequest> fieldFreqs = request.getFieldFacets();
-    List<RangeFacetRequest> rangeFreqs = request.getRangeFacets();
-    List<QueryFacetRequest> queryFreqs = request.getQueryFacets();
-
-    this.fieldFacetExpressions = new TreeMap<>();
-    this.rangeFacetExpressions = new LinkedHashMap<>(rangeFreqs.size());
-    this.queryFacetExpressions = new LinkedHashMap<>(queryFreqs.size());
-    this.fieldFacetCollectors = new LinkedHashMap<>(fieldFreqs.size());
-    this.rangeFacetCollectors = new LinkedHashMap<>(rangeFreqs.size());
-    this.queryFacetCollectors = new LinkedHashMap<>(queryFreqs.size());
-    this.facetAccumulators = new ArrayList<>();
-    this.hiddenFieldFacets = new HashSet<>();
-    
-    /**
-     * For each field facet request add a bucket to the {@link Expression} map and {@link StatsCollector} map.
-     * Field facets are computed during the initial collection of documents, therefore
-     * the FieldFacetAccumulators are created initially.
-     */
-    for( FieldFacetRequest freq : fieldFreqs ){
-      final FieldFacetRequest fr = (FieldFacetRequest) freq;
-      if (fr.isHidden()) {
-        hiddenFieldFacets.add(fr.getName());
-      }
-      final SchemaField ff = fr.getField();
-      final FieldFacetAccumulator facc = FieldFacetAccumulator.create(searcher, this, ff);
-      facetAccumulators.add(facc);
-      fieldFacetExpressions.put(freq.getName(), new TreeMap<String, Expression[]>() );
-      fieldFacetCollectors.put(freq.getName(), new TreeMap<String,StatsCollector[]>());
-    }
-    /**
-     * For each range and query facet request add a bucket to the corresponding
-     * {@link Expression} map and {@link StatsCollector} map.
-     * Range and Query Facets are computed in the post processing, so the accumulators
-     * are not created initially.
-     */
-    for( RangeFacetRequest freq : rangeFreqs ){
-      if( rangeFacets == null ) rangeFacets = new ArrayList<>();
-      rangeFacets.add(freq);
-      rangeFacetExpressions.put(freq.getName(), new LinkedHashMap<String,Expression[]>() );
-      rangeFacetCollectors.put(freq.getName(), new LinkedHashMap<String,StatsCollector[]>());
-    }
-    for( QueryFacetRequest freq : queryFreqs ){
-      if( queryFacets == null ) queryFacets = new ArrayList<>();
-      queryFacets.add(freq);
-      queryFacetExpressions.put(freq.getName(), new LinkedHashMap<String,Expression[]>() );
-      queryFacetCollectors.put(freq.getName(), new LinkedHashMap<String,StatsCollector[]>());
-    }
-    this.queryCount = 0l;
-  }
-  
-  public static FacetingAccumulator create(SolrIndexSearcher searcher, DocSet docs, AnalyticsRequest request, SolrQueryRequest queryRequest) throws IOException {
-    return new FacetingAccumulator(searcher,docs,request,queryRequest);
-  }
-
-  /**
-   * Update the readers for the {@link BasicAccumulator}, field facets and field facet {@link StatsCollector}s.
-   * @param context The context to read documents from.
-   * @throws IOException if there is an error setting the next reader
-   */
-  @Override
-  protected void doSetNextReader(LeafReaderContext context) throws IOException {
-    super.doSetNextReader(context);
-    for( Map<String,StatsCollector[]> valueList : fieldFacetCollectors.values() ){
-      for (StatsCollector[] statsCollectorList : valueList.values()) {
-        for (StatsCollector statsCollector : statsCollectorList) {
-          statsCollector.setNextReader(context);
-        }
-      }
-    }
-    for (FieldFacetAccumulator fa : facetAccumulators) {
-      fa.getLeafCollector(context);
-    }
-  }
-  
-  /**
-   * Updates the reader for all of the range facet {@link StatsCollector}s.
-   * @param context The context to read documents from.
-   * @throws IOException if there is an error setting the next reader
-   */
-  public void setRangeStatsCollectorReaders(LeafReaderContext context) throws IOException {
-    super.getLeafCollector(context);
-    for( Map<String,StatsCollector[]> rangeList : rangeFacetCollectors.values() ){
-      for (StatsCollector[] statsCollectorList : rangeList.values()) {
-        for (StatsCollector statsCollector : statsCollectorList) {
-          statsCollector.setNextReader(context);
-        }
-      }
-    }
-  }
-
-  
-  /**
-   * Updates the reader for all of the query facet {@link StatsCollector}s.
-   * @param context The context to read documents from.
-   * @throws IOException if there is an error setting the next reader
-   */
-  public void setQueryStatsCollectorReaders(LeafReaderContext context) throws IOException {
-    super.getLeafCollector(context);
-    for( Map<String,StatsCollector[]> queryList : queryFacetCollectors.values() ){
-      for (StatsCollector[] statsCollectorList : queryList.values()) {
-        for (StatsCollector statsCollector : statsCollectorList) {
-          statsCollector.setNextReader(context);
-        }
-      }
-    }
-  }
-
-  /**
-   * Called from Analytics stats, adds documents to the field 
-   * facets and the super {@link BasicAccumulator}.
-   */
-  @Override
-  public void collect(int doc) throws IOException {
-    for( FieldFacetAccumulator fa : facetAccumulators ){
-      fa.collect(doc);
-    }
-    super.collect(doc);
-  }
-  
-  /**
-   * Given a document, fieldFacet field and facetValue, adds the document to the
-   * {@link StatsCollector}s held in the bucket corresponding to the fieldFacet field and facetValue.
-   * Called during initial document collection.
-   */
-  @Override
-  public void collectField(int doc, String facetField, String facetValue) throws IOException {
-    Map<String,StatsCollector[]> map = fieldFacetCollectors.get(facetField);
-    StatsCollector[] statsCollectors = map.get(facetValue);
-    // If the facetValue has not been seen yet, a StatsCollector array is
-    // created and associated with that bucket.
-    if( statsCollectors == null ){
-      statsCollectors = statsCollectorArraySupplier.get();
-      map.put(facetValue,statsCollectors);
-      fieldFacetExpressions.get(facetField).put(facetValue,makeExpressions(statsCollectors));
-      for (StatsCollector statsCollector : statsCollectors) {
-        statsCollector.setNextReader(context);
-      }
-    }
-    for (StatsCollector statsCollector : statsCollectors) {
-      statsCollector.collect(doc);
-    }
-  }
-  
-  /**
-   * Given a document, rangeFacet field and range, adds the document to the
-   * {@link StatsCollector}s held in the bucket corresponding to the rangeFacet field and range.
-   * Called during post processing.
-   */
-  @Override
-  public void collectRange(int doc, String facetField, String range) throws IOException {
-    Map<String,StatsCollector[]> map = rangeFacetCollectors.get(facetField);
-    StatsCollector[] statsCollectors = map.get(range);
-    // If the range has not been seen yet, a StatsCollector array is
-    // created and associated with that bucket.
-    if( statsCollectors == null ){
-      statsCollectors = statsCollectorArraySupplier.get();
-      map.put(range,statsCollectors);
-      rangeFacetExpressions.get(facetField).put(range,makeExpressions(statsCollectors));
-      for (StatsCollector statsCollector : statsCollectors) {
-        statsCollector.setNextReader(context);
-      }
-    }
-    for (StatsCollector statsCollector : statsCollectors) {
-      statsCollector.collect(doc);
-    }
-  }
-  
-  /**
-   * Given a document, queryFacet name and query, adds the document to the
-   * {@link StatsCollector}s held in the bucket corresponding to the queryFacet name and query.
-   * Called during post processing.
-   */
-  @Override
-  public void collectQuery(int doc, String facetName, String query) throws IOException {
-    Map<String,StatsCollector[]> map = queryFacetCollectors.get(facetName);
-    StatsCollector[] statsCollectors = map.get(query);
-    // If the query has not been seen yet, a StatsCollector array is
-    // created and associated with that bucket.
-    if( statsCollectors == null ){
-      statsCollectors = statsCollectorArraySupplier.get();
-      map.put(query,statsCollectors);
-      queryFacetExpressions.get(facetName).put(query,makeExpressions(statsCollectors));
-      for (StatsCollector statsCollector : statsCollectors) {
-        statsCollector.setNextReader(context);
-      }
-    }
-    for (StatsCollector statsCollector : statsCollectors) {
-      statsCollector.collect(doc);
-    }
-  }
-
-  /**
-   * A comparator to compare expression values for field facet sorting.
-   */
-  public static class EntryComparator implements Comparator<Entry<String,Expression[]>> {
-    private final Comparator<Expression> comp;
-    private final int comparatorExpressionPlace;
-   
-    public EntryComparator(Comparator<Expression> comp, int comparatorExpressionPlace) {
-      this.comp = comp;
-      this.comparatorExpressionPlace = comparatorExpressionPlace;
-    }
-
-    @Override
-    public int compare(Entry<String,Expression[]> o1, Entry<String,Expression[]> o2) {
-      return comp.compare(o1.getValue()[comparatorExpressionPlace], o2.getValue()[comparatorExpressionPlace]);
-    }
-  }
-  
-  /**
-   * Finalizes the statistics within the each facet bucket before exporting;
-   */
-  @Override
-  public void compute() {
-    if (!basicsAndFieldFacetsComputed) {
-      super.compute();
-      for( Map<String, StatsCollector[]> f : fieldFacetCollectors.values() ){
-        for( StatsCollector[] arr : f.values() ){
-          for( StatsCollector b : arr ){
-            b.compute();
-          }
-        }
-      }
-      basicsAndFieldFacetsComputed = true;
-    }
-  }
-  
-  /**
-   * Finalizes the statistics within the a specific query facet before exporting;
-   */
-  public void computeQueryFacet(String facet) {
-    Map<String, StatsCollector[]> f = queryFacetCollectors.get(facet);
-    for( StatsCollector[] arr : f.values() ){
-      for( StatsCollector b : arr ){
-        b.compute();
-      }
-    }
-  }
-  
-  /**
-   * Finalizes the statistics within the a specific range facet before exporting;
-   */
-  public void computeRangeFacet(String facet) {
-    Map<String, StatsCollector[]> f = rangeFacetCollectors.get(facet);
-    for( StatsCollector[] arr : f.values() ){
-      for( StatsCollector b : arr ){
-        b.compute();
-      }
-    }
-  }
-  
-  /**
-   * Returns the value of an expression to use in a range or query facet.
-   * @param expressionName the name of the expression
-   * @param fieldFacet the facet field
-   * @param facetValue the facet value
-   * @return String String representation of pivot value
-   */
-  @SuppressWarnings({ "deprecation", "rawtypes" })
-  public String getResult(String expressionName, String fieldFacet, String facetValue) {
-    if (facetValue.contains(AnalyticsParams.RESULT) && !facetValue.contains(AnalyticsParams.QUERY_RESULT)) {
-      try {
-        String[] pivotStr = ExpressionFactory.getArguments(facetValue.substring(facetValue.indexOf('(')+1,facetValue.lastIndexOf(')')).trim());
-        if (pivotStr.length==1) {
-          facetValue = getResult(pivotStr[0]);
-        } else if (pivotStr.length==3) {
-          facetValue = getResult(pivotStr[0],pivotStr[1],pivotStr[2]);
-        } else {
-          throw new SolrException(ErrorCode.BAD_REQUEST, "Result request "+facetValue+" has an invalid amount of arguments.");
-        }
-      } catch (IndexOutOfBoundsException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST, "Result request "+facetValue+" is invalid. Lacks parentheses.",e);
-      }
-    } 
-    if (fieldFacetExpressions.get(fieldFacet)!=null) {
-      Expression[] facetExpressions = fieldFacetExpressions.get(fieldFacet).get(facetValue);
-      for (int count = 0; count < expressionNames.length; count++) {
-        if (expressionName.equals(expressionNames[count])) {
-          Comparable value = facetExpressions[count].getValue();
-          if (value.getClass().equals(Date.class)) {
-            return ((Date)value).toInstant().toString();
-          } else {
-            return value.toString();
-          }
-        }
-      }
-    }
-    throw new SolrException(ErrorCode.BAD_REQUEST,"Field Facet Pivot expression "+expressionName+" not found.");
-  }
-  
-  /**
-   * Returns the value of an expression to use in a range or query facet.
-   * @param currentFacet the name of the current facet
-   * @param expressionName the name of the expression
-   * @param queryFacet the facet query
-   * @param facetValue the field value
-   * @return String String representation of pivot value
-   */
-  @SuppressWarnings({ "deprecation", "rawtypes" })
-  public String getQueryResult(String currentFacet, String expressionName, String queryFacet, String facetValue) {
-    if (facetValue.contains(AnalyticsParams.RESULT) && !facetValue.contains(AnalyticsParams.QUERY_RESULT)) {
-      try {
-        String[] pivotStr = ExpressionFactory.getArguments(facetValue.substring(facetValue.indexOf('(')+1,facetValue.lastIndexOf(')')).trim());
-        if (pivotStr.length==1) {
-          facetValue = getResult(pivotStr[0]);
-        } else if (pivotStr.length==3) {
-          facetValue = getResult(pivotStr[0],pivotStr[1],pivotStr[2]);
-        } else {
-          throw new SolrException(ErrorCode.BAD_REQUEST, "Result request "+facetValue+" has an invalid amount of arguments.");
-        }
-      } catch (IndexOutOfBoundsException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"Result request "+facetValue+" is invalid. Lacks parentheses.",e);
-      }
-    } 
-    if (facetValue.contains(AnalyticsParams.QUERY_RESULT)) {
-      try {
-        String[] pivotStr = ExpressionFactory.getArguments(facetValue.substring(facetValue.indexOf('(')+1,facetValue.lastIndexOf(')')).trim());
-        if (pivotStr.length==1) {
-          facetValue = getResult(pivotStr[0]);
-        } else if (pivotStr.length==3) {
-          facetValue = getQueryResult(currentFacet,pivotStr[0],pivotStr[1],pivotStr[2]);
-        } else {
-          throw new SolrException(ErrorCode.BAD_REQUEST,"Result request "+facetValue+" has an invalid amount of arguments.");
-        }
-      } catch (IndexOutOfBoundsException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"Result request "+facetValue+" is invalid. Lacks parentheses.",e);
-      }
-    } 
-    if (queryFacetExpressions.get(queryFacet)!=null) {
-      Expression[] facetExpressions = queryFacetExpressions.get(queryFacet).get(facetValue);
-      for (int count = 0; count < expressionNames.length; count++) {
-        if (expressionName.equals(expressionNames[count])) {
-          Comparable value = facetExpressions[count].getValue();
-          if (value.getClass().equals(Date.class)) {
-            return ((Date)value).toInstant().toString();
-          } else {
-            return value.toString();
-          }
-        }
-      }
-    }
-    throw new SolrException(ErrorCode.BAD_REQUEST,"Field Facet Pivot expression "+expressionName+" not found.");
-  }
-  
-  @Override
-  @SuppressWarnings("unchecked")
-  public NamedList<?> export() {
-    final NamedList<Object> base = (NamedList<Object>)super.export();
-    NamedList<NamedList<?>> facetList = new NamedList<>();
-    
-    // Add the field facet buckets to the output
-    base.add("fieldFacets",facetList);
-    for( FieldFacetRequest freq : request.getFieldFacets() ){
-      final String name = freq.getName();
-      if (hiddenFieldFacets.contains(name)) {
-        continue;
-      }
-      final Map<String,Expression[]> buckets = fieldFacetExpressions.get(name);
-      final NamedList<Object> bucketBase = new NamedList<>();
-
-      Iterable<Entry<String,Expression[]>> iter = buckets.entrySet();
-      
-      final FieldFacetRequest fr = (FieldFacetRequest) freq;
-     
-      final FacetSortSpecification sort = fr.getSort();
-      final int limit = fr.getLimit();
-      final int offset = fr.getOffset();
-      final boolean showMissing = fr.showsMissing();
-      if (!showMissing) {
-        buckets.remove(MISSING_VALUE);
-      }
-      // Sorting the buckets if a sort specification is provided
-      if( sort != null && buckets.values().iterator().hasNext()){
-        int sortPlace = Arrays.binarySearch(expressionNames, sort.getStatistic());
-        final Expression first = buckets.values().iterator().next()[sortPlace];
-        final Comparator<Expression> comp = (Comparator<Expression>) first.comparator(sort.getDirection());
-        
-        final List<Entry<String,Expression[]>> sorted = new ArrayList<>(buckets.size());
-        Iterables.addAll(sorted, iter);
-        Collections.sort(sorted, new EntryComparator(comp,sortPlace));
-        iter = sorted;
-      }
-      // apply the limit
-      if( limit > AnalyticsContentHandler.DEFAULT_FACET_LIMIT ){
-        if( offset > 0 ){
-          iter = Iterables.skip(iter, offset);
-        }
-        iter = Iterables.limit(iter, limit);
-      }
-      
-      // Export each expression in the bucket.
-      for( Entry<String,Expression[]> bucket : iter ){
-        bucketBase.add(bucket.getKey(),export(bucket.getValue()));
-      }
-      
-      facetList.add(name, bucketBase);
-    }
-
-    // Add the range facet buckets to the output
-    facetList = new NamedList<>();
-    base.add("rangeFacets",facetList);
-    for( RangeFacetRequest freq : request.getRangeFacets() ){
-      final String name = freq.getName();
-      final Map<String,Expression[]> buckets = rangeFacetExpressions.get(name);
-      final NamedList<Object> bucketBase = new NamedList<>();
-
-      Iterable<Entry<String,Expression[]>> iter = buckets.entrySet();
-      
-      for( Entry<String,Expression[]> bucket : iter ){
-        bucketBase.add(bucket.getKey(),export(bucket.getValue()));
-      }
-      
-      facetList.add(name, bucketBase);
-    }
-    
-    // Add the query facet buckets to the output
-    facetList = new NamedList<>();
-    base.add("queryFacets",facetList);
-    for( QueryFacetRequest freq : request.getQueryFacets() ){
-      final String name = freq.getName();
-      final Map<String,Expression[]> buckets = queryFacetExpressions.get(name);
-      final NamedList<Object> bucketBase = new NamedList<>();
-
-      Iterable<Entry<String,Expression[]>> iter = buckets.entrySet();
-      
-      for( Entry<String,Expression[]> bucket : iter ){
-        bucketBase.add(bucket.getKey(),export(bucket.getValue()));
-      }
-      
-      facetList.add(name, bucketBase);
-    }
-
-    return base;
-  }
-  
-  /**
-   * Exports a list of expressions as a NamedList
-   * @param expressionArr an array of expressions
-   * @return named list of expressions
-   */
-  public NamedList<?> export(Expression[] expressionArr) {
-    NamedList<Object> base = new NamedList<>();
-    for (int count = 0; count < expressionArr.length; count++) {
-      if (!hiddenExpressions.contains(expressionNames[count])) {
-        base.add(expressionNames[count], expressionArr[count].getValue());
-      }
-    }
-    return base;
-  }
-
-  /**
-   * Processes the query and range facets.
-   * Must be called if range and/or query facets are supported.
-   */
-  @Override
-  public void postProcess() throws IOException {
-    super.compute();
-    for( Map<String, StatsCollector[]> f : fieldFacetCollectors.values() ){
-      for( StatsCollector[] arr : f.values() ){
-        for( StatsCollector b : arr ){
-          b.compute();
-        }
-      }
-    }
-    basicsAndFieldFacetsComputed = true;
-    final Filter filter = docs.getTopFilter();
-    if( rangeFacets != null ){
-      processRangeFacets(filter); 
-    }
-    if( queryFacets != null ){
-      processQueryFacets(filter); 
-    }
-  }
-  
-  /**
-   * Initiates the collecting of query facets
-   * @param filter the base filter to work against
-   * @throws IOException if searching failed
-   */
-  public void processQueryFacets(final Filter filter) throws IOException {
-    for( QueryFacetRequest qfr : queryFacets ){
-      for( String query : qfr.getQueries() ){
-        if (query.contains(AnalyticsParams.RESULT) && !query.contains(AnalyticsParams.QUERY_RESULT)) {
-          try {
-            String[] pivotStr = ExpressionFactory.getArguments(query.substring(query.indexOf('(')+1,query.lastIndexOf(')')).trim());
-            if (pivotStr.length==1) {
-              query = getResult(pivotStr[0]);
-            } else if (pivotStr.length==3) {
-              query = getResult(pivotStr[0],pivotStr[1],pivotStr[2]);
-            } else {
-              throw new SolrException(ErrorCode.BAD_REQUEST,"Result request "+query+" has an invalid amount of arguments.");
-            }
-          } catch (IndexOutOfBoundsException e) {
-            throw new SolrException(ErrorCode.BAD_REQUEST,"Result request "+query+" is invalid. Lacks parentheses.",e);
-          }
-        } else if (query.contains(AnalyticsParams.QUERY_RESULT)) {
-          try {
-            String[] pivotStr = ExpressionFactory.getArguments(query.substring(query.indexOf('(')+1,query.lastIndexOf(')')).trim());
-            if (pivotStr.length==3) {
-              query = getQueryResult(qfr.getName(),pivotStr[0],pivotStr[1],pivotStr[2]);
-            } else {
-              throw new SolrException(ErrorCode.BAD_REQUEST,"Result request "+query+" has an invalid amount of arguments.");
-            }
-          } catch (IndexOutOfBoundsException e) {
-            throw new SolrException(ErrorCode.BAD_REQUEST,"Result request "+query+" is invalid. Lacks parentheses.",e);
-          }
-        }
-        QueryFacetAccumulator qAcc = new QueryFacetAccumulator(this,qfr.getName(),query);
-        final Query q;
-        try {
-          q = QParser.getParser(query, queryRequest).getQuery();
-        } catch( SyntaxError e ){
-          throw new SolrException(ErrorCode.BAD_REQUEST,"Invalid query '"+query+"'",e);
-        }
-        // The searcher sends docIds to the QueryFacetAccumulator which forwards
-        // them to <code>collectQuery()</code> in this class for collection.
-        Query filtered = new BooleanQuery.Builder()
-            .add(q, Occur.MUST)
-            .add(filter, Occur.FILTER)
-            .build();
-        searcher.search(filtered, qAcc);
-        computeQueryFacet(qfr.getName());
-        queryCount++;
-      }
-    }
-  }
-  
-  @Override
-  public long getNumQueries() {
-    return queryCount;
-  }
-
-  /**
-   * Initiates the collecting of range facets
-   * @param filter the base filter to use
-   * @throws IOException if searching fails
-   */
-  public void processRangeFacets(final Filter filter) throws IOException {
-    for( RangeFacetRequest rfr : rangeFacets ){
-      String[] pivotStr;
-      String start = rfr.getStart();
-      if (start.contains(AnalyticsParams.QUERY_RESULT)) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"Query result requests can not be used in Range Facets");
-      } else if (start.contains(AnalyticsParams.RESULT)) {
-        try {
-          pivotStr = ExpressionFactory.getArguments(start.substring(start.indexOf('(')+1,start.indexOf(')')).trim());
-          if (pivotStr.length==1) {
-            rfr.setStart(getResult(pivotStr[0]));
-          } else if (pivotStr.length==3) {
-            rfr.setStart(getResult(pivotStr[0],pivotStr[1],pivotStr[2]));
-          } else {
-            throw new SolrException(ErrorCode.BAD_REQUEST, "Result request "+start+" has an invalid amount of arguments.");
-          }
-        } catch (IndexOutOfBoundsException e) {
-          throw new SolrException(ErrorCode.BAD_REQUEST, "Result request "+start+" is invalid. Lacks parentheses.",e);
-        }
-      }
-      String end = rfr.getEnd();
-      if (end.contains(AnalyticsParams.QUERY_RESULT)) {
-        throw new SolrException(ErrorCode.BAD_REQUEST, "Query result requests can not be used in Range Facets");
-      } else if (end.contains(AnalyticsParams.RESULT)) {
-        try {
-          pivotStr = ExpressionFactory.getArguments(end.substring(end.indexOf('(')+1,end.indexOf(')')).trim());
-          if (pivotStr.length==1) {
-            rfr.setEnd(getResult(pivotStr[0]));
-          } else if (pivotStr.length==3) {
-            rfr.setEnd(getResult(pivotStr[0],pivotStr[1],pivotStr[2]));
-          } else {
-            throw new SolrException(ErrorCode.BAD_REQUEST, "Result request "+end+" has an invalid amount of arguments.");
-          }
-        } catch (IndexOutOfBoundsException e) {
-          throw new SolrException(ErrorCode.BAD_REQUEST, "Result request "+end+" is invalid. Lacks parentheses.",e);
-        }
-      }
-      String[] gaps = rfr.getGaps();
-      for (int count = 0; count<gaps.length; count++){
-        String gap = gaps[count];
-        if (gap.contains(AnalyticsParams.QUERY_RESULT)) {
-          throw new SolrException(ErrorCode.BAD_REQUEST, "Query result requests can not be used in Range Facets");
-        } else if (gap.contains(AnalyticsParams.RESULT)) {
-          try {
-            pivotStr = ExpressionFactory.getArguments(gap.substring(gap.indexOf('(')+1,gap.indexOf(')')).trim());
-            if (pivotStr.length==1) {
-              gaps[count]=getResult(pivotStr[0]);
-            } else if (pivotStr.length==3) {
-              gaps[count]=getResult(pivotStr[0],pivotStr[1],pivotStr[2]);
-            } else {
-              throw new SolrException(ErrorCode.BAD_REQUEST, "Result request "+gap+" has an invalid amount of arguments.");
-            }
-          } catch (IndexOutOfBoundsException e) {
-            throw new SolrException(ErrorCode.BAD_REQUEST, "Result request "+gap+" is invalid. Lacks parentheses.",e);
-          }
-        }
-      }
-      // Computes the end points of the ranges in the rangeFacet
-      final RangeEndpointCalculator<? extends Comparable<?>> rec = RangeEndpointCalculator.create(rfr);
-      final SchemaField sf = rfr.getField();
-      
-      // Create a rangeFacetAccumulator for each range and 
-      // collect the documents for that range.
-      for( FacetRange range : rec.getRanges() ){
-        final String upper;
-        final String lower;
-        String facetValue = "";
-        if( range.lower == null ){
-          facetValue = "(*";
-          lower = null;
-        } else {
-          lower = range.lower;
-          facetValue = ((range.includeLower)?"[":"(") + range.lower;
-        }
-        facetValue+=" TO ";
-        if( range.upper == null ){
-          upper = null;
-          facetValue += "*)";
-        } else {
-          upper = range.upper;
-          facetValue += range.upper + ((range.includeUpper)?"]":")");
-        }
-        
-        Query q = sf.getType().getRangeQuery(null, sf, lower, upper, range.includeLower,range.includeUpper);
-        RangeFacetAccumulator rAcc = new RangeFacetAccumulator(this,rfr.getName(),facetValue);
-        // The searcher sends docIds to the RangeFacetAccumulator which forwards
-        // them to <code>collectRange()</code> in this class for collection.
-        Query filtered = new BooleanQuery.Builder()
-            .add(q, Occur.MUST)
-            .add(filter, Occur.FILTER)
-            .build();
-        searcher.search(filtered, rAcc);
-        computeRangeFacet(sf.getName());
-      }
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/ValueAccumulator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/ValueAccumulator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/ValueAccumulator.java
deleted file mode 100644
index 489d3de..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/ValueAccumulator.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.accumulator;
-
-import java.io.IOException;
-
-import org.apache.lucene.search.SimpleCollector;
-import org.apache.solr.common.util.NamedList;
-
-/**
- * Abstract Collector that manages all StatsCollectors, Expressions and Facets.
- */
-public abstract class ValueAccumulator extends SimpleCollector {
-  
-  /**
-   * Finalizes the statistics within each StatsCollector.
-   * Must be called before <code>export()</code>.
-   */
-  public abstract void compute();
-  public abstract NamedList<?> export();
-  
-  public void postProcess() throws IOException {
-    // NOP
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/FacetValueAccumulator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/FacetValueAccumulator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/FacetValueAccumulator.java
deleted file mode 100644
index 1b6fbb7..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/accumulator/facet/FacetValueAccumulator.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.accumulator.facet;
-
-import java.io.IOException;
-
-import org.apache.lucene.index.LeafReaderContext;
-
-/**
- * Interface that describes the methods needed for an Accumulator to be able to handle 
- * fieldFacets, rangeFacets and queryFacets.
- */
-public interface FacetValueAccumulator {
-
-  void collectField(int doc, String facetName, String facetValue) throws IOException;
-  void collectQuery(int doc, String facetName, String facetValue) throws IOException;
-  void collectRange(int doc, String facetName, String facetValue) throws IOException;
-  void setQueryStatsCollectorReaders(LeafReaderContext context) throws IOException;
-  void setRangeStatsCollectorReaders(LeafReaderContext context) throws IOException;
-
-}


[46/58] [abbrv] lucene-solr:jira/solr-10879: LUCENE-5822 Add markdown-compatible README.md

Posted by ab...@apache.org.
LUCENE-5822 Add markdown-compatible README.md

Signed-off-by: Mike Drob <md...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/2e1c5063
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/2e1c5063
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/2e1c5063

Branch: refs/heads/jira/solr-10879
Commit: 2e1c5063a5cdd76098730265dc551c43ad8526ae
Parents: 15118d4
Author: Jason Gerlowski <je...@us.ibm.com>
Authored: Tue Jun 27 18:04:15 2017 -0400
Committer: Mike Drob <md...@apache.org>
Committed: Fri Jun 30 10:57:09 2017 -0500

----------------------------------------------------------------------
 README.md          | 103 ++++++++++++++++++++++++++++++++++++++++++++++++
 README.txt         |  13 ------
 lucene/CHANGES.txt |   2 +
 3 files changed, 105 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/2e1c5063/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7181297
--- /dev/null
+++ b/README.md
@@ -0,0 +1,103 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ -->
+
+# Apache Lucene and Solr
+
+Apache Lucene is a high-performance, full featured text search engine library
+written in Java.
+
+Apache Solr is an enterprise search platform written using Apache Lucene.
+Major features include full-text search, index replication and sharding, and
+result faceting and highlighting.
+
+## Online Documentation
+
+This README file only contains basic setup instructions.  For more
+comprehensive documentation, visit:
+
+- Lucene: <http://lucene.apache.org/core/documentation.html>
+- Solr: <http://lucene.apache.org/solr/guide/>
+
+## Building Lucene/Solr
+
+(You do not need to do this if you downloaded a pre-built package.)
+
+Lucene and Solr are built using [Apache Ant](http://ant.apache.org/).  To build
+Lucene and Solr, run:
+
+`ant compile`
+
+The Solr server can then be packaged and prepared for startup by running the
+following command from the `solr/` directory:
+
+`ant server`
+
+## Running Solr
+
+After [building Solr](#building-lucene-solr), the server can be started using
+the `bin/solr` control scripts.  Solr can be run in either standalone or
+distributed (SolrCloud mode).
+
+To run Solr in standalone mode, run the following command from the `solr/`
+directory:
+
+`bin/solr start`
+
+To run Solr in SolrCloud mode, run the following command from the `solr/`
+directory:
+
+`bin/solr start -c`
+
+The `bin/solr` control script allows heavy modification of the started Solr.
+Common options are described in some detail in solr/README.txt.  For an
+exhaustive treatment of options, run `bin/solr start -h` from the `solr/`
+directory.
+
+## Development/IDEs
+
+Ant can be used to generate project files compatible with most common IDEs.
+Run the ant command corresponding to your IDE of choice before attempting to
+import Lucene/Solr.
+
+- *Eclipse* - `ant eclipse`
+- *IntelliJ* - `ant idea`
+- *Netbeans* - `ant netbeans`
+
+## Running Tests
+
+The standard test suite can be run with the command:
+
+`ant test`
+
+Like Solr itself, the test-running can be customized or tailored in a number or
+ways.  For an exhaustive discussion of the options available, run:
+
+`ant test-help`
+
+## Contributing
+
+Please review the [Contributing to Solr
+Guide](https://wiki.apache.org/solr/HowToContribute) for information on
+contributing.
+
+## Discussion and Support
+
+- [Users Mailing List](http://lucene.apache.org/solr/community.html#solr-user-list-solr-userluceneapacheorg)
+- [Developers Mailing List](http://lucene.apache.org/solr/community.html#developer-list-devluceneapacheorg)
+- [Lucene Issue Tracker](https://issues.apache.org/jira/browse/LUCENE)
+- [Solr Issue Tracker](https://issues.apache.org/jira/browse/SOLR)
+- IRC: `#solr` and `#solr-dev` on freenode.net

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/2e1c5063/README.txt
----------------------------------------------------------------------
diff --git a/README.txt b/README.txt
deleted file mode 100644
index 3599b5b..0000000
--- a/README.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Apache Lucene/Solr
-
-lucene/ is a search engine library
-solr/ is a search engine server that uses lucene
-
-To compile the sources run 'ant compile'
-To run all the tests run 'ant test'
-To setup your ide run 'ant idea', 'ant netbeans', or 'ant eclipse'
-For Maven info, see dev-tools/maven/README.maven
-
-For more information on how to contribute see:
-http://wiki.apache.org/lucene-java/HowToContribute
-http://wiki.apache.org/solr/HowToContribute

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/2e1c5063/lucene/CHANGES.txt
----------------------------------------------------------------------
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 69ba53f..909b6ce 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -167,6 +167,8 @@ Other
   resolved against Lucene's class loader by default. Please use another builder
   method to change to a custom classloader.  (Uwe Schindler)
 
+* LUCENE-5822: Convert README to Markdown (Jason Gerlowski via Mike Drob)
+
 ======================= Lucene 6.7.0 =======================
 
 New Features


[52/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-6671: Fix precommit and use the Lucene-Constant to detect Windows. Also allow other local drives!

Posted by ab...@apache.org.
SOLR-6671: Fix precommit and use the Lucene-Constant to detect Windows. Also allow other local drives!


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/7b322bd6
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/7b322bd6
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/7b322bd6

Branch: refs/heads/jira/solr-10879
Commit: 7b322bd67e5a3a9c7f9ecf165d89da60c3767fbd
Parents: 8000b25
Author: Uwe Schindler <us...@apache.org>
Authored: Sun Jul 2 11:44:10 2017 +0200
Committer: Uwe Schindler <us...@apache.org>
Committed: Sun Jul 2 11:44:10 2017 +0200

----------------------------------------------------------------------
 .../src/test/org/apache/solr/core/DirectoryFactoryTest.java | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/7b322bd6/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java b/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
index 35bb09b..2c2ddd9 100755
--- a/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
+++ b/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
@@ -20,19 +20,17 @@ import java.io.IOException;
 import java.nio.file.Paths;
 import java.util.Properties;
 
-import org.apache.commons.exec.OS;
+import org.apache.lucene.util.Constants;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.handler.admin.CoreAdminHandler;
 import org.apache.solr.handler.component.HttpShardHandlerFactory;
-import org.apache.solr.util.MockCoreContainer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
 public class DirectoryFactoryTest extends LuceneTestCase {
 
-  private static boolean IS_WINDOWS = (OS.isFamilyDOS() || OS.isFamilyWin9x() || OS.isFamilyWindows());
   public void testLockTypesUnchanged() throws Exception {
     assertEquals("simple", DirectoryFactory.LOCK_TYPE_SIMPLE);
     assertEquals("native", DirectoryFactory.LOCK_TYPE_NATIVE);
@@ -76,8 +74,9 @@ public class DirectoryFactoryTest extends LuceneTestCase {
 
   private void assertDataHome(String expected, String instanceDir, RAMDirectoryFactory rdf, MockCoreContainer cc, String... properties) throws IOException {
     String dataHome = rdf.getDataHome(new CoreDescriptor("core_name", Paths.get(instanceDir), cc.containerProperties, cc.isZooKeeperAware(), properties));
-    if (IS_WINDOWS) {
-      dataHome = dataHome.replaceFirst("^C:", "").replaceAll("\\\\","/");
+    if (Constants.WINDOWS) {
+      // TODO: find a less-hacky way to assert this!
+      dataHome = dataHome.replaceFirst("^[A-Z]:", "").replace("\\", "/");
     }
     assertEquals(expected, dataHome);
   }


[36/58] [abbrv] lucene-solr:jira/solr-10879: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/lucene-solr

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b4fa0e78/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
----------------------------------------------------------------------


[49/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10954: this was supposed to be in the solrj package

Posted by ab...@apache.org.
SOLR-10954: this was supposed to be in the solrj package


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/2e56e7eb
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/2e56e7eb
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/2e56e7eb

Branch: refs/heads/jira/solr-10879
Commit: 2e56e7eb28a99109aa0b7c35a9698250f531b984
Parents: f3c851a
Author: Noble Paul <no...@apache.org>
Authored: Sat Jul 1 11:44:22 2017 +0930
Committer: Noble Paul <no...@apache.org>
Committed: Sat Jul 1 11:44:22 2017 +0930

----------------------------------------------------------------------
 .../solr/common/cloud/ReplicaPosition.java      | 55 --------------------
 .../solr/common/cloud/ReplicaPosition.java      | 55 ++++++++++++++++++++
 2 files changed, 55 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/2e56e7eb/solr/core/src/java/org/apache/solr/common/cloud/ReplicaPosition.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/common/cloud/ReplicaPosition.java b/solr/core/src/java/org/apache/solr/common/cloud/ReplicaPosition.java
deleted file mode 100644
index d64d1d1..0000000
--- a/solr/core/src/java/org/apache/solr/common/cloud/ReplicaPosition.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.common.cloud;
-
-
-public class ReplicaPosition implements Comparable<ReplicaPosition> {
-  public final String shard;
-  public final int index;
-  public final Replica.Type type;
-  public String node;
-
-  public ReplicaPosition(String shard, int replicaIdx, Replica.Type type) {
-    this.shard = shard;
-    this.index = replicaIdx;
-    this.type = type;
-  }
-  public ReplicaPosition(String shard, int replicaIdx, Replica.Type type, String node) {
-    this.shard = shard;
-    this.index = replicaIdx;
-    this.type = type;
-    this.node = node;
-  }
-
-  @Override
-  public int compareTo(ReplicaPosition that) {
-    //this is to ensure that we try one replica from each shard first instead of
-    // all replicas from same shard
-    return that.index > index ? -1 : that.index == index ? 0 : 1;
-  }
-
-  @Override
-  public String toString() {
-    return shard + ":" + index;
-  }
-
-  public ReplicaPosition setNode(String node) {
-    this.node = node;
-    return this;
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/2e56e7eb/solr/solrj/src/java/org/apache/solr/common/cloud/ReplicaPosition.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/cloud/ReplicaPosition.java b/solr/solrj/src/java/org/apache/solr/common/cloud/ReplicaPosition.java
new file mode 100644
index 0000000..d64d1d1
--- /dev/null
+++ b/solr/solrj/src/java/org/apache/solr/common/cloud/ReplicaPosition.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.common.cloud;
+
+
+public class ReplicaPosition implements Comparable<ReplicaPosition> {
+  public final String shard;
+  public final int index;
+  public final Replica.Type type;
+  public String node;
+
+  public ReplicaPosition(String shard, int replicaIdx, Replica.Type type) {
+    this.shard = shard;
+    this.index = replicaIdx;
+    this.type = type;
+  }
+  public ReplicaPosition(String shard, int replicaIdx, Replica.Type type, String node) {
+    this.shard = shard;
+    this.index = replicaIdx;
+    this.type = type;
+    this.node = node;
+  }
+
+  @Override
+  public int compareTo(ReplicaPosition that) {
+    //this is to ensure that we try one replica from each shard first instead of
+    // all replicas from same shard
+    return that.index > index ? -1 : that.index == index ? 0 : 1;
+  }
+
+  @Override
+  public String toString() {
+    return shard + ":" + index;
+  }
+
+  public ReplicaPosition setNode(String node) {
+    this.node = node;
+    return this;
+  }
+}


[27/58] [abbrv] lucene-solr:jira/solr-10879: minor doc change for chroot in CDCR

Posted by ab...@apache.org.
minor doc change for chroot in CDCR


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

Branch: refs/heads/jira/solr-10879
Commit: d0c86d078e8dab4c4ea8e5b19fa33f4fd648d8c3
Parents: c98e2a5
Author: Erick Erickson <er...@apache.org>
Authored: Wed Jun 28 19:31:37 2017 -0700
Committer: Erick Erickson <er...@apache.org>
Committed: Wed Jun 28 19:31:37 2017 -0700

----------------------------------------------------------------------
 .../solr-ref-guide/src/cross-data-center-replication-cdcr.adoc | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d0c86d07/solr/solr-ref-guide/src/cross-data-center-replication-cdcr.adoc
----------------------------------------------------------------------
diff --git a/solr/solr-ref-guide/src/cross-data-center-replication-cdcr.adoc b/solr/solr-ref-guide/src/cross-data-center-replication-cdcr.adoc
index 6772955..bffa71f 100644
--- a/solr/solr-ref-guide/src/cross-data-center-replication-cdcr.adoc
+++ b/solr/solr-ref-guide/src/cross-data-center-replication-cdcr.adoc
@@ -181,7 +181,11 @@ Here is a sample of a source configuration file, a section in `solrconfig.xml`.
 ----
 <requestHandler name="/cdcr" class="solr.CdcrRequestHandler">
   <lst name="replica">
-    <str name="zkHost">10.240.18.211:2181</str>
+    <str name="zkHost">10.240.18.211:2181,10.240.18.212:2181</str>
+    <!--
+    If you have chrooted your Solr information at the target you must include the chroot, for example:
+    <str name="zkHost">10.240.18.211:2181,10.240.18.212:2181/solr</str>
+    -->
     <str name="source">collection1</str>
     <str name="target">collection1</str>
   </lst>


[32/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10272: Adding user _default configset to test-files, fixing solr & solr.cmd script bugs

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_it.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_it.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_it.txt
new file mode 100644
index 0000000..1219cc7
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_it.txt
@@ -0,0 +1,303 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/italian/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | An Italian stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ad             |  a (to) before vowel
+al             |  a + il
+allo           |  a + lo
+ai             |  a + i
+agli           |  a + gli
+all            |  a + l'
+agl            |  a + gl'
+alla           |  a + la
+alle           |  a + le
+con            |  with
+col            |  con + il
+coi            |  con + i (forms collo, cogli etc are now very rare)
+da             |  from
+dal            |  da + il
+dallo          |  da + lo
+dai            |  da + i
+dagli          |  da + gli
+dall           |  da + l'
+dagl           |  da + gll'
+dalla          |  da + la
+dalle          |  da + le
+di             |  of
+del            |  di + il
+dello          |  di + lo
+dei            |  di + i
+degli          |  di + gli
+dell           |  di + l'
+degl           |  di + gl'
+della          |  di + la
+delle          |  di + le
+in             |  in
+nel            |  in + el
+nello          |  in + lo
+nei            |  in + i
+negli          |  in + gli
+nell           |  in + l'
+negl           |  in + gl'
+nella          |  in + la
+nelle          |  in + le
+su             |  on
+sul            |  su + il
+sullo          |  su + lo
+sui            |  su + i
+sugli          |  su + gli
+sull           |  su + l'
+sugl           |  su + gl'
+sulla          |  su + la
+sulle          |  su + le
+per            |  through, by
+tra            |  among
+contro         |  against
+io             |  I
+tu             |  thou
+lui            |  he
+lei            |  she
+noi            |  we
+voi            |  you
+loro           |  they
+mio            |  my
+mia            |
+miei           |
+mie            |
+tuo            |
+tua            |
+tuoi           |  thy
+tue            |
+suo            |
+sua            |
+suoi           |  his, her
+sue            |
+nostro         |  our
+nostra         |
+nostri         |
+nostre         |
+vostro         |  your
+vostra         |
+vostri         |
+vostre         |
+mi             |  me
+ti             |  thee
+ci             |  us, there
+vi             |  you, there
+lo             |  him, the
+la             |  her, the
+li             |  them
+le             |  them, the
+gli            |  to him, the
+ne             |  from there etc
+il             |  the
+un             |  a
+uno            |  a
+una            |  a
+ma             |  but
+ed             |  and
+se             |  if
+perché         |  why, because
+anche          |  also
+come           |  how
+dov            |  where (as dov')
+dove           |  where
+che            |  who, that
+chi            |  who
+cui            |  whom
+non            |  not
+più            |  more
+quale          |  who, that
+quanto         |  how much
+quanti         |
+quanta         |
+quante         |
+quello         |  that
+quelli         |
+quella         |
+quelle         |
+questo         |  this
+questi         |
+questa         |
+queste         |
+si             |  yes
+tutto          |  all
+tutti          |  all
+
+               |  single letter forms:
+
+a              |  at
+c              |  as c' for ce or ci
+e              |  and
+i              |  the
+l              |  as l'
+o              |  or
+
+               | forms of avere, to have (not including the infinitive):
+
+ho
+hai
+ha
+abbiamo
+avete
+hanno
+abbia
+abbiate
+abbiano
+avrò
+avrai
+avrà
+avremo
+avrete
+avranno
+avrei
+avresti
+avrebbe
+avremmo
+avreste
+avrebbero
+avevo
+avevi
+aveva
+avevamo
+avevate
+avevano
+ebbi
+avesti
+ebbe
+avemmo
+aveste
+ebbero
+avessi
+avesse
+avessimo
+avessero
+avendo
+avuto
+avuta
+avuti
+avute
+
+               | forms of essere, to be (not including the infinitive):
+sono
+sei
+è
+siamo
+siete
+sia
+siate
+siano
+sarò
+sarai
+sarà
+saremo
+sarete
+saranno
+sarei
+saresti
+sarebbe
+saremmo
+sareste
+sarebbero
+ero
+eri
+era
+eravamo
+eravate
+erano
+fui
+fosti
+fu
+fummo
+foste
+furono
+fossi
+fosse
+fossimo
+fossero
+essendo
+
+               | forms of fare, to do (not including the infinitive, fa, fat-):
+faccio
+fai
+facciamo
+fanno
+faccia
+facciate
+facciano
+farò
+farai
+farà
+faremo
+farete
+faranno
+farei
+faresti
+farebbe
+faremmo
+fareste
+farebbero
+facevo
+facevi
+faceva
+facevamo
+facevate
+facevano
+feci
+facesti
+fece
+facemmo
+faceste
+fecero
+facessi
+facesse
+facessimo
+facessero
+facendo
+
+               | forms of stare, to be (not including the infinitive):
+sto
+stai
+sta
+stiamo
+stanno
+stia
+stiate
+stiano
+starò
+starai
+starà
+staremo
+starete
+staranno
+starei
+staresti
+starebbe
+staremmo
+stareste
+starebbero
+stavo
+stavi
+stava
+stavamo
+stavate
+stavano
+stetti
+stesti
+stette
+stemmo
+steste
+stettero
+stessi
+stesse
+stessimo
+stessero
+stando

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ja.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ja.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ja.txt
new file mode 100644
index 0000000..d4321be
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ja.txt
@@ -0,0 +1,127 @@
+#
+# This file defines a stopword set for Japanese.
+#
+# This set is made up of hand-picked frequent terms from segmented Japanese Wikipedia.
+# Punctuation characters and frequent kanji have mostly been left out.  See LUCENE-3745
+# for frequency lists, etc. that can be useful for making your own set (if desired)
+#
+# Note that there is an overlap between these stopwords and the terms stopped when used
+# in combination with the JapanesePartOfSpeechStopFilter.  When editing this file, note
+# that comments are not allowed on the same line as stopwords.
+#
+# Also note that stopping is done in a case-insensitive manner.  Change your StopFilter
+# configuration if you need case-sensitive stopping.  Lastly, note that stopping is done
+# using the same character width as the entries in this file.  Since this StopFilter is
+# normally done after a CJKWidthFilter in your chain, you would usually want your romaji
+# entries to be in half-width and your kana entries to be in full-width.
+#
+の
+に
+は
+を
+た
+が
+で
+て
+と
+し
+れ
+さ
+ある
+いる
+も
+する
+から
+な
+こと
+として
+い
+や
+れる
+など
+なっ
+ない
+この
+ため
+その
+あっ
+よう
+また
+もの
+という
+あり
+まで
+られ
+なる
+へ
+か
+だ
+これ
+によって
+により
+おり
+より
+による
+ず
+なり
+られる
+において
+ば
+なかっ
+なく
+しかし
+について
+せ
+だっ
+その後
+できる
+それ
+う
+ので
+なお
+のみ
+でき
+き
+つ
+における
+および
+いう
+さらに
+でも
+ら
+たり
+その他
+に関する
+たち
+ます
+ん
+なら
+に対して
+特に
+せる
+及び
+これら
+とき
+では
+にて
+ほか
+ながら
+うち
+そして
+とともに
+ただし
+かつて
+それぞれ
+または
+お
+ほど
+ものの
+に対する
+ほとんど
+と共に
+といった
+です
+とも
+ところ
+ここ
+##### End of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_lv.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_lv.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_lv.txt
new file mode 100644
index 0000000..e21a23c
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_lv.txt
@@ -0,0 +1,172 @@
+# Set of Latvian stopwords from A Stemming Algorithm for Latvian, Karlis Kreslins
+# the original list of over 800 forms was refined: 
+#   pronouns, adverbs, interjections were removed
+# 
+# prepositions
+aiz
+ap
+ar
+apakš
+ārpus
+augšpus
+bez
+caur
+dēļ
+gar
+iekš
+iz
+kopš
+labad
+lejpus
+līdz
+no
+otrpus
+pa
+par
+pār
+pēc
+pie
+pirms
+pret
+priekš
+starp
+šaipus
+uz
+viņpus
+virs
+virspus
+zem
+apakšpus
+# Conjunctions
+un
+bet
+jo
+ja
+ka
+lai
+tomēr
+tikko
+turpretī
+arī
+kaut
+gan
+tādēļ
+tā
+ne
+tikvien
+vien
+kā
+ir
+te
+vai
+kamēr
+# Particles
+ar
+diezin
+droši
+diemžēl
+nebūt
+ik
+it
+taču
+nu
+pat
+tiklab
+iekšpus
+nedz
+tik
+nevis
+turpretim
+jeb
+iekam
+iekām
+iekāms
+kolīdz
+līdzko
+tiklīdz
+jebšu
+tālab
+tāpēc
+nekā
+itin
+jā
+jau
+jel
+nē
+nezin
+tad
+tikai
+vis
+tak
+iekams
+vien
+# modal verbs
+būt  
+biju 
+biji
+bija
+bijām
+bijāt
+esmu
+esi
+esam
+esat 
+būšu     
+būsi
+būs
+būsim
+būsiet
+tikt
+tiku
+tiki
+tika
+tikām
+tikāt
+tieku
+tiec
+tiek
+tiekam
+tiekat
+tikšu
+tiks
+tiksim
+tiksiet
+tapt
+tapi
+tapāt
+topat
+tapšu
+tapsi
+taps
+tapsim
+tapsiet
+kļūt
+kļuvu
+kļuvi
+kļuva
+kļuvām
+kļuvāt
+kļūstu
+kļūsti
+kļūst
+kļūstam
+kļūstat
+kļūšu
+kļūsi
+kļūs
+kļūsim
+kļūsiet
+# verbs
+varēt
+varēju
+varējām
+varēšu
+varēsim
+var
+varēji
+varējāt
+varēsi
+varēsiet
+varat
+varēja
+varēs

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_nl.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_nl.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_nl.txt
new file mode 100644
index 0000000..47a2aea
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_nl.txt
@@ -0,0 +1,119 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/dutch/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Dutch stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ | This is a ranked list (commonest to rarest) of stopwords derived from
+ | a large sample of Dutch text.
+
+ | Dutch stop words frequently exhibit homonym clashes. These are indicated
+ | clearly below.
+
+de             |  the
+en             |  and
+van            |  of, from
+ik             |  I, the ego
+te             |  (1) chez, at etc, (2) to, (3) too
+dat            |  that, which
+die            |  that, those, who, which
+in             |  in, inside
+een            |  a, an, one
+hij            |  he
+het            |  the, it
+niet           |  not, nothing, naught
+zijn           |  (1) to be, being, (2) his, one's, its
+is             |  is
+was            |  (1) was, past tense of all persons sing. of 'zijn' (to be) (2) wax, (3) the washing, (4) rise of river
+op             |  on, upon, at, in, up, used up
+aan            |  on, upon, to (as dative)
+met            |  with, by
+als            |  like, such as, when
+voor           |  (1) before, in front of, (2) furrow
+had            |  had, past tense all persons sing. of 'hebben' (have)
+er             |  there
+maar           |  but, only
+om             |  round, about, for etc
+hem            |  him
+dan            |  then
+zou            |  should/would, past tense all persons sing. of 'zullen'
+of             |  or, whether, if
+wat            |  what, something, anything
+mijn           |  possessive and noun 'mine'
+men            |  people, 'one'
+dit            |  this
+zo             |  so, thus, in this way
+door           |  through by
+over           |  over, across
+ze             |  she, her, they, them
+zich           |  oneself
+bij            |  (1) a bee, (2) by, near, at
+ook            |  also, too
+tot            |  till, until
+je             |  you
+mij            |  me
+uit            |  out of, from
+der            |  Old Dutch form of 'van der' still found in surnames
+daar           |  (1) there, (2) because
+haar           |  (1) her, their, them, (2) hair
+naar           |  (1) unpleasant, unwell etc, (2) towards, (3) as
+heb            |  present first person sing. of 'to have'
+hoe            |  how, why
+heeft          |  present third person sing. of 'to have'
+hebben         |  'to have' and various parts thereof
+deze           |  this
+u              |  you
+want           |  (1) for, (2) mitten, (3) rigging
+nog            |  yet, still
+zal            |  'shall', first and third person sing. of verb 'zullen' (will)
+me             |  me
+zij            |  she, they
+nu             |  now
+ge             |  'thou', still used in Belgium and south Netherlands
+geen           |  none
+omdat          |  because
+iets           |  something, somewhat
+worden         |  to become, grow, get
+toch           |  yet, still
+al             |  all, every, each
+waren          |  (1) 'were' (2) to wander, (3) wares, (3)
+veel           |  much, many
+meer           |  (1) more, (2) lake
+doen           |  to do, to make
+toen           |  then, when
+moet           |  noun 'spot/mote' and present form of 'to must'
+ben            |  (1) am, (2) 'are' in interrogative second person singular of 'to be'
+zonder         |  without
+kan            |  noun 'can' and present form of 'to be able'
+hun            |  their, them
+dus            |  so, consequently
+alles          |  all, everything, anything
+onder          |  under, beneath
+ja             |  yes, of course
+eens           |  once, one day
+hier           |  here
+wie            |  who
+werd           |  imperfect third person sing. of 'become'
+altijd         |  always
+doch           |  yet, but etc
+wordt          |  present third person sing. of 'become'
+wezen          |  (1) to be, (2) 'been' as in 'been fishing', (3) orphans
+kunnen         |  to be able
+ons            |  us/our
+zelf           |  self
+tegen          |  against, towards, at
+na             |  after, near
+reeds          |  already
+wil            |  (1) present tense of 'want', (2) 'will', noun, (3) fender
+kon            |  could; past tense of 'to be able'
+niets          |  nothing
+uw             |  your
+iemand         |  somebody
+geweest        |  been; past participle of 'be'
+andere         |  other

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_no.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_no.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_no.txt
new file mode 100644
index 0000000..a7a2c28
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_no.txt
@@ -0,0 +1,194 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/norwegian/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Norwegian stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ | This stop word list is for the dominant bokmål dialect. Words unique
+ | to nynorsk are marked *.
+
+ | Revised by Jan Bruusgaard <Ja...@ssb.no>, Jan 2005
+
+og             | and
+i              | in
+jeg            | I
+det            | it/this/that
+at             | to (w. inf.)
+en             | a/an
+et             | a/an
+den            | it/this/that
+til            | to
+er             | is/am/are
+som            | who/that
+på             | on
+de             | they / you(formal)
+med            | with
+han            | he
+av             | of
+ikke           | not
+ikkje          | not *
+der            | there
+så             | so
+var            | was/were
+meg            | me
+seg            | you
+men            | but
+ett            | one
+har            | have
+om             | about
+vi             | we
+min            | my
+mitt           | my
+ha             | have
+hadde          | had
+hun            | she
+nå             | now
+over           | over
+da             | when/as
+ved            | by/know
+fra            | from
+du             | you
+ut             | out
+sin            | your
+dem            | them
+oss            | us
+opp            | up
+man            | you/one
+kan            | can
+hans           | his
+hvor           | where
+eller          | or
+hva            | what
+skal           | shall/must
+selv           | self (reflective)
+sjøl           | self (reflective)
+her            | here
+alle           | all
+vil            | will
+bli            | become
+ble            | became
+blei           | became *
+blitt          | have become
+kunne          | could
+inn            | in
+når            | when
+være           | be
+kom            | come
+noen           | some
+noe            | some
+ville          | would
+dere           | you
+som            | who/which/that
+deres          | their/theirs
+kun            | only/just
+ja             | yes
+etter          | after
+ned            | down
+skulle         | should
+denne          | this
+for            | for/because
+deg            | you
+si             | hers/his
+sine           | hers/his
+sitt           | hers/his
+mot            | against
+å              | to
+meget          | much
+hvorfor        | why
+dette          | this
+disse          | these/those
+uten           | without
+hvordan        | how
+ingen          | none
+din            | your
+ditt           | your
+blir           | become
+samme          | same
+hvilken        | which
+hvilke         | which (plural)
+sånn           | such a
+inni           | inside/within
+mellom         | between
+vår            | our
+hver           | each
+hvem           | who
+vors           | us/ours
+hvis           | whose
+både           | both
+bare           | only/just
+enn            | than
+fordi          | as/because
+før            | before
+mange          | many
+også           | also
+slik           | just
+vært           | been
+være           | to be
+båe            | both *
+begge          | both
+siden          | since
+dykk           | your *
+dykkar         | yours *
+dei            | they *
+deira          | them *
+deires         | theirs *
+deim           | them *
+di             | your (fem.) *
+då             | as/when *
+eg             | I *
+ein            | a/an *
+eit            | a/an *
+eitt           | a/an *
+elles          | or *
+honom          | he *
+hjå            | at *
+ho             | she *
+hoe            | she *
+henne          | her
+hennar         | her/hers
+hennes         | hers
+hoss           | how *
+hossen         | how *
+ikkje          | not *
+ingi           | noone *
+inkje          | noone *
+korleis        | how *
+korso          | how *
+kva            | what/which *
+kvar           | where *
+kvarhelst      | where *
+kven           | who/whom *
+kvi            | why *
+kvifor         | why *
+me             | we *
+medan          | while *
+mi             | my *
+mine           | my *
+mykje          | much *
+no             | now *
+nokon          | some (masc./neut.) *
+noka           | some (fem.) *
+nokor          | some *
+noko           | some *
+nokre          | some *
+si             | his/hers *
+sia            | since *
+sidan          | since *
+so             | so *
+somt           | some *
+somme          | some *
+um             | about*
+upp            | up *
+vere           | be *
+vore           | was *
+verte          | become *
+vort           | become *
+varte          | became *
+vart           | became *
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_pt.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_pt.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_pt.txt
new file mode 100644
index 0000000..acfeb01
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_pt.txt
@@ -0,0 +1,253 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/portuguese/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Portuguese stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+
+ | The following is a ranked list (commonest to rarest) of stopwords
+ | deriving from a large sample of text.
+
+ | Extra words have been added at the end.
+
+de             |  of, from
+a              |  the; to, at; her
+o              |  the; him
+que            |  who, that
+e              |  and
+do             |  de + o
+da             |  de + a
+em             |  in
+um             |  a
+para           |  for
+  | é          from SER
+com            |  with
+não            |  not, no
+uma            |  a
+os             |  the; them
+no             |  em + o
+se             |  himself etc
+na             |  em + a
+por            |  for
+mais           |  more
+as             |  the; them
+dos            |  de + os
+como           |  as, like
+mas            |  but
+  | foi        from SER
+ao             |  a + o
+ele            |  he
+das            |  de + as
+  | tem        from TER
+à              |  a + a
+seu            |  his
+sua            |  her
+ou             |  or
+  | ser        from SER
+quando         |  when
+muito          |  much
+  | há         from HAV
+nos            |  em + os; us
+já             |  already, now
+  | está       from EST
+eu             |  I
+também         |  also
+só             |  only, just
+pelo           |  per + o
+pela           |  per + a
+até            |  up to
+isso           |  that
+ela            |  he
+entre          |  between
+  | era        from SER
+depois         |  after
+sem            |  without
+mesmo          |  same
+aos            |  a + os
+  | ter        from TER
+seus           |  his
+quem           |  whom
+nas            |  em + as
+me             |  me
+esse           |  that
+eles           |  they
+  | estão      from EST
+você           |  you
+  | tinha      from TER
+  | foram      from SER
+essa           |  that
+num            |  em + um
+nem            |  nor
+suas           |  her
+meu            |  my
+às             |  a + as
+minha          |  my
+  | têm        from TER
+numa           |  em + uma
+pelos          |  per + os
+elas           |  they
+  | havia      from HAV
+  | seja       from SER
+qual           |  which
+  | será       from SER
+nós            |  we
+  | tenho      from TER
+lhe            |  to him, her
+deles          |  of them
+essas          |  those
+esses          |  those
+pelas          |  per + as
+este           |  this
+  | fosse      from SER
+dele           |  of him
+
+ | other words. There are many contractions such as naquele = em+aquele,
+ | mo = me+o, but they are rare.
+ | Indefinite article plural forms are also rare.
+
+tu             |  thou
+te             |  thee
+vocês          |  you (plural)
+vos            |  you
+lhes           |  to them
+meus           |  my
+minhas
+teu            |  thy
+tua
+teus
+tuas
+nosso          | our
+nossa
+nossos
+nossas
+
+dela           |  of her
+delas          |  of them
+
+esta           |  this
+estes          |  these
+estas          |  these
+aquele         |  that
+aquela         |  that
+aqueles        |  those
+aquelas        |  those
+isto           |  this
+aquilo         |  that
+
+               | forms of estar, to be (not including the infinitive):
+estou
+está
+estamos
+estão
+estive
+esteve
+estivemos
+estiveram
+estava
+estávamos
+estavam
+estivera
+estivéramos
+esteja
+estejamos
+estejam
+estivesse
+estivéssemos
+estivessem
+estiver
+estivermos
+estiverem
+
+               | forms of haver, to have (not including the infinitive):
+hei
+há
+havemos
+hão
+houve
+houvemos
+houveram
+houvera
+houvéramos
+haja
+hajamos
+hajam
+houvesse
+houvéssemos
+houvessem
+houver
+houvermos
+houverem
+houverei
+houverá
+houveremos
+houverão
+houveria
+houveríamos
+houveriam
+
+               | forms of ser, to be (not including the infinitive):
+sou
+somos
+são
+era
+éramos
+eram
+fui
+foi
+fomos
+foram
+fora
+fôramos
+seja
+sejamos
+sejam
+fosse
+fôssemos
+fossem
+for
+formos
+forem
+serei
+será
+seremos
+serão
+seria
+seríamos
+seriam
+
+               | forms of ter, to have (not including the infinitive):
+tenho
+tem
+temos
+tém
+tinha
+tínhamos
+tinham
+tive
+teve
+tivemos
+tiveram
+tivera
+tivéramos
+tenha
+tenhamos
+tenham
+tivesse
+tivéssemos
+tivessem
+tiver
+tivermos
+tiverem
+terei
+terá
+teremos
+terão
+teria
+teríamos
+teriam

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ro.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ro.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ro.txt
new file mode 100644
index 0000000..4fdee90
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ro.txt
@@ -0,0 +1,233 @@
+# This file was created by Jacques Savoy and is distributed under the BSD license.
+# See http://members.unine.ch/jacques.savoy/clef/index.html.
+# Also see http://www.opensource.org/licenses/bsd-license.html
+acea
+aceasta
+această
+aceea
+acei
+aceia
+acel
+acela
+acele
+acelea
+acest
+acesta
+aceste
+acestea
+aceşti
+aceştia
+acolo
+acum
+ai
+aia
+aibă
+aici
+al
+ăla
+ale
+alea
+ălea
+altceva
+altcineva
+am
+ar
+are
+aş
+aşadar
+asemenea
+asta
+ăsta
+astăzi
+astea
+ăstea
+ăştia
+asupra
+aţi
+au
+avea
+avem
+aveţi
+azi
+bine
+bucur
+bună
+ca
+că
+căci
+când
+care
+cărei
+căror
+cărui
+cât
+câte
+câţi
+către
+câtva
+ce
+cel
+ceva
+chiar
+cînd
+cine
+cineva
+cît
+cîte
+cîţi
+cîtva
+contra
+cu
+cum
+cumva
+curând
+curînd
+da
+dă
+dacă
+dar
+datorită
+de
+deci
+deja
+deoarece
+departe
+deşi
+din
+dinaintea
+dintr
+dintre
+drept
+după
+ea
+ei
+el
+ele
+eram
+este
+eşti
+eu
+face
+fără
+fi
+fie
+fiecare
+fii
+fim
+fiţi
+iar
+ieri
+îi
+îl
+îmi
+împotriva
+în 
+înainte
+înaintea
+încât
+încît
+încotro
+între
+întrucât
+întrucît
+îţi
+la
+lângă
+le
+li
+lîngă
+lor
+lui
+mă
+mâine
+mea
+mei
+mele
+mereu
+meu
+mi
+mine
+mult
+multă
+mulţi
+ne
+nicăieri
+nici
+nimeni
+nişte
+noastră
+noastre
+noi
+noştri
+nostru
+nu
+ori
+oricând
+oricare
+oricât
+orice
+oricînd
+oricine
+oricît
+oricum
+oriunde
+până
+pe
+pentru
+peste
+pînă
+poate
+pot
+prea
+prima
+primul
+prin
+printr
+sa
+să
+săi
+sale
+sau
+său
+se
+şi
+sînt
+sîntem
+sînteţi
+spre
+sub
+sunt
+suntem
+sunteţi
+ta
+tăi
+tale
+tău
+te
+ţi
+ţie
+tine
+toată
+toate
+tot
+toţi
+totuşi
+tu
+un
+una
+unde
+undeva
+unei
+unele
+uneori
+unor
+vă
+vi
+voastră
+voastre
+voi
+voştri
+vostru
+vouă
+vreo
+vreun

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ru.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ru.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ru.txt
new file mode 100644
index 0000000..5527140
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ru.txt
@@ -0,0 +1,243 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/russian/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | a russian stop word list. comments begin with vertical bar. each stop
+ | word is at the start of a line.
+
+ | this is a ranked list (commonest to rarest) of stopwords derived from
+ | a large text sample.
+
+ | letter `ё' is translated to `е'.
+
+и              | and
+в              | in/into
+во             | alternative form
+не             | not
+что            | what/that
+он             | he
+на             | on/onto
+я              | i
+с              | from
+со             | alternative form
+как            | how
+а              | milder form of `no' (but)
+то             | conjunction and form of `that'
+все            | all
+она            | she
+так            | so, thus
+его            | him
+но             | but
+да             | yes/and
+ты             | thou
+к              | towards, by
+у              | around, chez
+же             | intensifier particle
+вы             | you
+за             | beyond, behind
+бы             | conditional/subj. particle
+по             | up to, along
+только         | only
+ее             | her
+мне            | to me
+было           | it was
+вот            | here is/are, particle
+от             | away from
+меня           | me
+еще            | still, yet, more
+нет            | no, there isnt/arent
+о              | about
+из             | out of
+ему            | to him
+теперь         | now
+когда          | when
+даже           | even
+ну             | so, well
+вдруг          | suddenly
+ли             | interrogative particle
+если           | if
+уже            | already, but homonym of `narrower'
+или            | or
+ни             | neither
+быть           | to be
+был            | he was
+него           | prepositional form of его
+до             | up to
+вас            | you accusative
+нибудь         | indef. suffix preceded by hyphen
+опять          | again
+уж             | already, but homonym of `adder'
+вам            | to you
+сказал         | he said
+ведь           | particle `after all'
+там            | there
+потом          | then
+себя           | oneself
+ничего         | nothing
+ей             | to her
+может          | usually with `быть' as `maybe'
+они            | they
+тут            | here
+где            | where
+есть           | there is/are
+надо           | got to, must
+ней            | prepositional form of  ей
+для            | for
+мы             | we
+тебя           | thee
+их             | them, their
+чем            | than
+была           | she was
+сам            | self
+чтоб           | in order to
+без            | without
+будто          | as if
+человек        | man, person, one
+чего           | genitive form of `what'
+раз            | once
+тоже           | also
+себе           | to oneself
+под            | beneath
+жизнь          | life
+будет          | will be
+ж              | short form of intensifer particle `же'
+тогда          | then
+кто            | who
+этот           | this
+говорил        | was saying
+того           | genitive form of `that'
+потому         | for that reason
+этого          | genitive form of `this'
+какой          | which
+совсем         | altogether
+ним            | prepositional form of `его', `они'
+здесь          | here
+этом           | prepositional form of `этот'
+один           | one
+почти          | almost
+мой            | my
+тем            | instrumental/dative plural of `тот', `то'
+чтобы          | full form of `in order that'
+нее            | her (acc.)
+кажется        | it seems
+сейчас         | now
+были           | they were
+куда           | where to
+зачем          | why
+сказать        | to say
+всех           | all (acc., gen. preposn. plural)
+никогда        | never
+сегодня        | today
+можно          | possible, one can
+при            | by
+наконец        | finally
+два            | two
+об             | alternative form of `о', about
+другой         | another
+хоть           | even
+после          | after
+над            | above
+больше         | more
+тот            | that one (masc.)
+через          | across, in
+эти            | these
+нас            | us
+про            | about
+всего          | in all, only, of all
+них            | prepositional form of `они' (they)
+какая          | which, feminine
+много          | lots
+разве          | interrogative particle
+сказала        | she said
+три            | three
+эту            | this, acc. fem. sing.
+моя            | my, feminine
+впрочем        | moreover, besides
+хорошо         | good
+свою           | ones own, acc. fem. sing.
+этой           | oblique form of `эта', fem. `this'
+перед          | in front of
+иногда         | sometimes
+лучше          | better
+чуть           | a little
+том            | preposn. form of `that one'
+нельзя         | one must not
+такой          | such a one
+им             | to them
+более          | more
+всегда         | always
+конечно        | of course
+всю            | acc. fem. sing of `all'
+между          | between
+
+
+  | b: some paradigms
+  |
+  | personal pronouns
+  |
+  | я  меня  мне  мной  [мною]
+  | ты  тебя  тебе  тобой  [тобою]
+  | он  его  ему  им  [него, нему, ним]
+  | она  ее  эи  ею  [нее, нэи, нею]
+  | оно  его  ему  им  [него, нему, ним]
+  |
+  | мы  нас  нам  нами
+  | вы  вас  вам  вами
+  | они  их  им  ими  [них, ним, ними]
+  |
+  |   себя  себе  собой   [собою]
+  |
+  | demonstrative pronouns: этот (this), тот (that)
+  |
+  | этот  эта  это  эти
+  | этого  эты  это  эти
+  | этого  этой  этого  этих
+  | этому  этой  этому  этим
+  | этим  этой  этим  [этою]  этими
+  | этом  этой  этом  этих
+  |
+  | тот  та  то  те
+  | того  ту  то  те
+  | того  той  того  тех
+  | тому  той  тому  тем
+  | тем  той  тем  [тою]  теми
+  | том  той  том  тех
+  |
+  | determinative pronouns
+  |
+  | (a) весь (all)
+  |
+  | весь  вся  все  все
+  | всего  всю  все  все
+  | всего  всей  всего  всех
+  | всему  всей  всему  всем
+  | всем  всей  всем  [всею]  всеми
+  | всем  всей  всем  всех
+  |
+  | (b) сам (himself etc)
+  |
+  | сам  сама  само  сами
+  | самого саму  само  самих
+  | самого самой самого  самих
+  | самому самой самому  самим
+  | самим  самой  самим  [самою]  самими
+  | самом самой самом  самих
+  |
+  | stems of verbs `to be', `to have', `to do' and modal
+  |
+  | быть  бы  буд  быв  есть  суть
+  | име
+  | дел
+  | мог   мож  мочь
+  | уме
+  | хоч  хот
+  | долж
+  | можн
+  | нужн
+  | нельзя
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_sv.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_sv.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_sv.txt
new file mode 100644
index 0000000..096f87f
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_sv.txt
@@ -0,0 +1,133 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/swedish/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Swedish stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ | This is a ranked list (commonest to rarest) of stopwords derived from
+ | a large text sample.
+
+ | Swedish stop words occasionally exhibit homonym clashes. For example
+ |  så = so, but also seed. These are indicated clearly below.
+
+och            | and
+det            | it, this/that
+att            | to (with infinitive)
+i              | in, at
+en             | a
+jag            | I
+hon            | she
+som            | who, that
+han            | he
+på             | on
+den            | it, this/that
+med            | with
+var            | where, each
+sig            | him(self) etc
+för            | for
+så             | so (also: seed)
+till           | to
+är             | is
+men            | but
+ett            | a
+om             | if; around, about
+hade           | had
+de             | they, these/those
+av             | of
+icke           | not, no
+mig            | me
+du             | you
+henne          | her
+då             | then, when
+sin            | his
+nu             | now
+har            | have
+inte           | inte någon = no one
+hans           | his
+honom          | him
+skulle         | 'sake'
+hennes         | her
+där            | there
+min            | my
+man            | one (pronoun)
+ej             | nor
+vid            | at, by, on (also: vast)
+kunde          | could
+något          | some etc
+från           | from, off
+ut             | out
+när            | when
+efter          | after, behind
+upp            | up
+vi             | we
+dem            | them
+vara           | be
+vad            | what
+över           | over
+än             | than
+dig            | you
+kan            | can
+sina           | his
+här            | here
+ha             | have
+mot            | towards
+alla           | all
+under          | under (also: wonder)
+någon          | some etc
+eller          | or (else)
+allt           | all
+mycket         | much
+sedan          | since
+ju             | why
+denna          | this/that
+själv          | myself, yourself etc
+detta          | this/that
+åt             | to
+utan           | without
+varit          | was
+hur            | how
+ingen          | no
+mitt           | my
+ni             | you
+bli            | to be, become
+blev           | from bli
+oss            | us
+din            | thy
+dessa          | these/those
+några          | some etc
+deras          | their
+blir           | from bli
+mina           | my
+samma          | (the) same
+vilken         | who, that
+er             | you, your
+sådan          | such a
+vår            | our
+blivit         | from bli
+dess           | its
+inom           | within
+mellan         | between
+sådant         | such a
+varför         | why
+varje          | each
+vilka          | who, that
+ditt           | thy
+vem            | who
+vilket         | who, that
+sitta          | his
+sådana         | such a
+vart           | each
+dina           | thy
+vars           | whose
+vårt           | our
+våra           | our
+ert            | your
+era            | your
+vilkas         | whose
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_th.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_th.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_th.txt
new file mode 100644
index 0000000..07f0fab
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_th.txt
@@ -0,0 +1,119 @@
+# Thai stopwords from:
+# "Opinion Detection in Thai Political News Columns
+# Based on Subjectivity Analysis"
+# Khampol Sukhum, Supot Nitsuwat, and Choochart Haruechaiyasak
+ไว้
+ไม่
+ไป
+ได้
+ให้
+ใน
+โดย
+แห่ง
+แล้ว
+และ
+แรก
+แบบ
+แต่
+เอง
+เห็น
+เลย
+เริ่ม
+เรา
+เมื่อ
+เพื่อ
+เพราะ
+เป็นการ
+เป็น
+เปิดเผย
+เปิด
+เนื่องจาก
+เดียวกัน
+เดียว
+เช่น
+เฉพาะ
+เคย
+เข้า
+เขา
+อีก
+อาจ
+อะไร
+ออก
+อย่าง
+อยู่
+อยาก
+หาก
+หลาย
+หลังจาก
+หลัง
+หรือ
+หนึ่ง
+ส่วน
+ส่ง
+สุด
+สําหรับ
+ว่า
+วัน
+ลง
+ร่วม
+ราย
+รับ
+ระหว่าง
+รวม
+ยัง
+มี
+มาก
+มา
+พร้อม
+พบ
+ผ่าน
+ผล
+บาง
+น่า
+นี้
+นํา
+นั้น
+นัก
+นอกจาก
+ทุก
+ที่สุด
+ที่
+ทําให้
+ทํา
+ทาง
+ทั้งนี้
+ทั้ง
+ถ้า
+ถูก
+ถึง
+ต้อง
+ต่างๆ
+ต่าง
+ต่อ
+ตาม
+ตั้งแต่
+ตั้ง
+ด้าน
+ด้วย
+ดัง
+ซึ่ง
+ช่วง
+จึง
+จาก
+จัด
+จะ
+คือ
+ความ
+ครั้ง
+คง
+ขึ้น
+ของ
+ขอ
+ขณะ
+ก่อน
+ก็
+การ
+กับ
+กัน
+กว่า
+กล่าว

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_tr.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_tr.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_tr.txt
new file mode 100644
index 0000000..84d9408
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_tr.txt
@@ -0,0 +1,212 @@
+# Turkish stopwords from LUCENE-559
+# merged with the list from "Information Retrieval on Turkish Texts"
+#   (http://www.users.muohio.edu/canf/papers/JASIST2008offPrint.pdf)
+acaba
+altmış
+altı
+ama
+ancak
+arada
+aslında
+ayrıca
+bana
+bazı
+belki
+ben
+benden
+beni
+benim
+beri
+beş
+bile
+bin
+bir
+birçok
+biri
+birkaç
+birkez
+birşey
+birşeyi
+biz
+bize
+bizden
+bizi
+bizim
+böyle
+böylece
+bu
+buna
+bunda
+bundan
+bunlar
+bunları
+bunların
+bunu
+bunun
+burada
+çok
+çünkü
+da
+daha
+dahi
+de
+defa
+değil
+diğer
+diye
+doksan
+dokuz
+dolayı
+dolayısıyla
+dört
+edecek
+eden
+ederek
+edilecek
+ediliyor
+edilmesi
+ediyor
+eğer
+elli
+en
+etmesi
+etti
+ettiği
+ettiğini
+gibi
+göre
+halen
+hangi
+hatta
+hem
+henüz
+hep
+hepsi
+her
+herhangi
+herkesin
+hiç
+hiçbir
+için
+iki
+ile
+ilgili
+ise
+işte
+itibaren
+itibariyle
+kadar
+karşın
+katrilyon
+kendi
+kendilerine
+kendini
+kendisi
+kendisine
+kendisini
+kez
+ki
+kim
+kimden
+kime
+kimi
+kimse
+kırk
+milyar
+milyon
+mu
+mü
+mı
+nasıl
+ne
+neden
+nedenle
+nerde
+nerede
+nereye
+niye
+niçin
+o
+olan
+olarak
+oldu
+olduğu
+olduğunu
+olduklarını
+olmadı
+olmadığı
+olmak
+olması
+olmayan
+olmaz
+olsa
+olsun
+olup
+olur
+olursa
+oluyor
+on
+ona
+ondan
+onlar
+onlardan
+onları
+onların
+onu
+onun
+otuz
+oysa
+öyle
+pek
+rağmen
+sadece
+sanki
+sekiz
+seksen
+sen
+senden
+seni
+senin
+siz
+sizden
+sizi
+sizin
+şey
+şeyden
+şeyi
+şeyler
+şöyle
+şu
+şuna
+şunda
+şundan
+şunları
+şunu
+tarafından
+trilyon
+tüm
+üç
+üzere
+var
+vardı
+ve
+veya
+ya
+yani
+yapacak
+yapılan
+yapılması
+yapıyor
+yapmak
+yaptı
+yaptığı
+yaptığını
+yaptıkları
+yedi
+yerine
+yetmiş
+yine
+yirmi
+yoksa
+yüz
+zaten

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/userdict_ja.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/userdict_ja.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/userdict_ja.txt
new file mode 100644
index 0000000..6f0368e
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/userdict_ja.txt
@@ -0,0 +1,29 @@
+#
+# This is a sample user dictionary for Kuromoji (JapaneseTokenizer)
+#
+# Add entries to this file in order to override the statistical model in terms
+# of segmentation, readings and part-of-speech tags.  Notice that entries do
+# not have weights since they are always used when found.  This is by-design
+# in order to maximize ease-of-use.
+#
+# Entries are defined using the following CSV format:
+#  <text>,<token 1> ... <token n>,<reading 1> ... <reading n>,<part-of-speech tag>
+#
+# Notice that a single half-width space separates tokens and readings, and
+# that the number tokens and readings must match exactly.
+#
+# Also notice that multiple entries with the same <text> is undefined.
+#
+# Whitespace only lines are ignored.  Comments are not allowed on entry lines.
+#
+
+# Custom segmentation for kanji compounds
+日本経済新聞,日本 経済 新聞,ニホン ケイザイ シンブン,カスタム名詞
+関西国際空港,関西 国際 空港,カンサイ コクサイ クウコウ,カスタム名詞
+
+# Custom segmentation for compound katakana
+トートバッグ,トート バッグ,トート バッグ,かずカナ名詞
+ショルダーバッグ,ショルダー バッグ,ショルダー バッグ,かずカナ名詞
+
+# Custom reading for former sumo wrestler
+朝青龍,朝青龍,アサショウリュウ,カスタム人名


[20/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
SOLR-10123: Upgraded the Analytics Component to version 2.0


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

Branch: refs/heads/jira/solr-10879
Commit: d5963bebc43bdb712f2f1e9a29f944370f079b5f
Parents: 85a27a2
Author: Dennis Gove <dp...@gmail.com>
Authored: Wed Jun 28 09:39:47 2017 -0400
Committer: Dennis Gove <dp...@gmail.com>
Committed: Wed Jun 28 14:13:37 2017 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                |    8 +
 .../apache/solr/analytics/AnalyticsDriver.java  |   82 +
 .../solr/analytics/AnalyticsExpression.java     |   64 +
 .../analytics/AnalyticsGroupingManager.java     |  239 ++
 .../solr/analytics/AnalyticsRequestManager.java |  279 ++
 .../solr/analytics/AnalyticsRequestParser.java  |  549 +++
 .../solr/analytics/ExpressionFactory.java       |  821 +++++
 .../analytics/accumulator/BasicAccumulator.java |  173 -
 .../accumulator/FacetingAccumulator.java        |  730 ----
 .../analytics/accumulator/ValueAccumulator.java |   40 -
 .../facet/FacetValueAccumulator.java            |   35 -
 .../facet/FieldFacetAccumulator.java            |  153 -
 .../facet/QueryFacetAccumulator.java            |   72 -
 .../facet/RangeFacetAccumulator.java            |   49 -
 .../accumulator/facet/package-info.java         |   24 -
 .../analytics/accumulator/package-info.java     |   23 -
 .../analytics/expression/BaseExpression.java    |   88 -
 .../expression/DualDelegateExpression.java      |   99 -
 .../solr/analytics/expression/Expression.java   |   39 -
 .../analytics/expression/ExpressionFactory.java |  175 -
 .../expression/MultiDelegateExpression.java     |  131 -
 .../expression/SingleDelegateExpression.java    |   88 -
 .../solr/analytics/expression/package-info.java |   23 -
 .../analytics/facet/AbstractSolrQueryFacet.java |  104 +
 .../solr/analytics/facet/AnalyticsFacet.java    |  166 +
 .../apache/solr/analytics/facet/PivotFacet.java |  114 +
 .../apache/solr/analytics/facet/PivotNode.java  |  263 ++
 .../apache/solr/analytics/facet/QueryFacet.java |   64 +
 .../apache/solr/analytics/facet/RangeFacet.java |  119 +
 .../solr/analytics/facet/SortableFacet.java     |  178 +
 .../solr/analytics/facet/StreamingFacet.java    |   32 +
 .../apache/solr/analytics/facet/ValueFacet.java |   60 +
 .../facet/compare/ConstantComparator.java       |   30 +
 .../facet/compare/DelegatingComparator.java     |   62 +
 .../facet/compare/ExpressionComparator.java     |   46 +
 .../facet/compare/FacetResultsComparator.java   |   52 +
 .../facet/compare/FacetValueComparator.java     |   37 +
 .../analytics/facet/compare/package-info.java   |   23 +
 .../solr/analytics/facet/package-info.java      |   23 +
 .../function/ExpressionCalculator.java          |   71 +
 .../MergingReductionCollectionManager.java      |   46 +
 .../function/ReductionCollectionManager.java    |  320 ++
 .../analytics/function/ReductionFunction.java   |   37 +
 .../function/field/AnalyticsField.java          |   69 +
 .../analytics/function/field/BooleanField.java  |  111 +
 .../function/field/BooleanMultiField.java       |  101 +
 .../analytics/function/field/DateField.java     |  108 +
 .../function/field/DateMultiField.java          |   47 +
 .../function/field/DateMultiPointField.java     |   47 +
 .../analytics/function/field/DoubleField.java   |   97 +
 .../function/field/DoubleMultiField.java        |   85 +
 .../function/field/DoubleMultiPointField.java   |   81 +
 .../analytics/function/field/FloatField.java    |  108 +
 .../function/field/FloatMultiField.java         |   91 +
 .../function/field/FloatMultiPointField.java    |   87 +
 .../solr/analytics/function/field/IntField.java |  129 +
 .../analytics/function/field/IntMultiField.java |  100 +
 .../function/field/IntMultiPointField.java      |   96 +
 .../analytics/function/field/LongField.java     |  107 +
 .../function/field/LongMultiField.java          |   89 +
 .../function/field/LongMultiPointField.java     |   86 +
 .../analytics/function/field/StringField.java   |   85 +
 .../function/field/StringMultiField.java        |   66 +
 .../analytics/function/field/package-info.java  |   23 +
 .../function/mapping/AbsoluteValueFunction.java |   54 +
 .../analytics/function/mapping/AddFunction.java |   68 +
 .../function/mapping/BottomFunction.java        |  163 +
 .../function/mapping/CompareFunction.java       |  614 ++++
 .../function/mapping/ConcatFunction.java        |   78 +
 .../function/mapping/DateMathFunction.java      |  156 +
 .../function/mapping/DateParseFunction.java     |  210 ++
 .../function/mapping/DivideFunction.java        |   51 +
 .../function/mapping/FillMissingFunction.java   |  842 +++++
 .../function/mapping/FilterFunction.java        |  722 ++++
 .../analytics/function/mapping/IfFunction.java  |  892 +++++
 .../function/mapping/JoinFunction.java          |   57 +
 .../function/mapping/LambdaFunction.java        | 3220 ++++++++++++++++++
 .../analytics/function/mapping/LogFunction.java |   51 +
 .../function/mapping/LogicFunction.java         |   90 +
 .../function/mapping/MultFunction.java          |   68 +
 .../function/mapping/NegateFunction.java        |   58 +
 .../mapping/NumericConvertFunction.java         |  256 ++
 .../function/mapping/PowerFunction.java         |   51 +
 .../function/mapping/RemoveFunction.java        |  796 +++++
 .../function/mapping/ReplaceFunction.java       |  914 +++++
 .../function/mapping/StringCastFunction.java    |   42 +
 .../function/mapping/SubtractFunction.java      |   51 +
 .../analytics/function/mapping/TopFunction.java |  163 +
 .../function/mapping/package-info.java          |   23 +
 .../solr/analytics/function/package-info.java   |   23 +
 .../function/reduction/CountFunction.java       |   87 +
 .../function/reduction/DocCountFunction.java    |   87 +
 .../function/reduction/MaxFunction.java         |  298 ++
 .../function/reduction/MedianFunction.java      |  200 ++
 .../function/reduction/MinFunction.java         |  298 ++
 .../function/reduction/MissingFunction.java     |   76 +
 .../function/reduction/OrdinalFunction.java     |  386 +++
 .../function/reduction/PercentileFunction.java  |  337 ++
 .../function/reduction/SumFunction.java         |   92 +
 .../function/reduction/UniqueFunction.java      |  101 +
 .../function/reduction/data/CountCollector.java |  188 +
 .../function/reduction/data/MaxCollector.java   |  476 +++
 .../function/reduction/data/MinCollector.java   |  476 +++
 .../function/reduction/data/ReductionData.java  |   24 +
 .../reduction/data/ReductionDataCollector.java  |  183 +
 .../reduction/data/SortedListCollector.java     |  363 ++
 .../function/reduction/data/SumCollector.java   |  124 +
 .../reduction/data/UniqueCollector.java         |  241 ++
 .../function/reduction/data/package-info.java   |   24 +
 .../function/reduction/package-info.java        |   23 +
 .../org/apache/solr/analytics/package-info.java |   23 +
 .../request/AbstractFieldFacetRequest.java      |   42 -
 .../request/AnalyticsContentHandler.java        |  314 --
 .../analytics/request/AnalyticsRequest.java     |  114 -
 .../request/AnalyticsRequestFactory.java        |  308 --
 .../solr/analytics/request/AnalyticsStats.java  |  138 -
 .../analytics/request/ExpressionRequest.java    |   72 -
 .../solr/analytics/request/FacetRequest.java    |   26 -
 .../analytics/request/FieldFacetRequest.java    |  172 -
 .../analytics/request/QueryFacetRequest.java    |   74 -
 .../analytics/request/RangeFacetRequest.java    |  129 -
 .../solr/analytics/request/package-info.java    |   24 -
 .../AbstractDelegatingStatsCollector.java       |   74 -
 .../statistics/MedianStatsCollector.java        |   76 -
 .../statistics/MinMaxStatsCollector.java        |  114 -
 .../statistics/NumericStatsCollector.java       |   68 -
 .../statistics/PercentileStatsCollector.java    |   80 -
 .../analytics/statistics/StatsCollector.java    |   69 -
 .../StatsCollectorSupplierFactory.java          |  646 ----
 .../statistics/UniqueStatsCollector.java        |   53 -
 .../solr/analytics/statistics/package-info.java |   24 -
 .../stream/AnalyticsShardRequestManager.java    |  245 ++
 .../stream/AnalyticsShardResponseParser.java    |   89 +
 .../solr/analytics/stream/package-info.java     |   23 +
 .../reservation/BooleanArrayReservation.java    |   44 +
 .../reservation/BooleanCheckedReservation.java  |   42 +
 .../stream/reservation/BooleanReservation.java  |   42 +
 .../reservation/DoubleArrayReservation.java     |   44 +
 .../reservation/DoubleCheckedReservation.java   |   43 +
 .../stream/reservation/DoubleReservation.java   |   42 +
 .../reservation/FloatArrayReservation.java      |   44 +
 .../reservation/FloatCheckedReservation.java    |   43 +
 .../stream/reservation/FloatReservation.java    |   42 +
 .../stream/reservation/IntArrayReservation.java |   42 +
 .../reservation/IntCheckedReservation.java      |   43 +
 .../stream/reservation/IntReservation.java      |   42 +
 .../reservation/LongArrayReservation.java       |   45 +
 .../reservation/LongCheckedReservation.java     |   43 +
 .../stream/reservation/LongReservation.java     |   42 +
 .../ReductionCheckedDataReservation.java        |   35 +
 .../ReductionDataArrayReservation.java          |   36 +
 .../reservation/ReductionDataReservation.java   |   53 +
 .../reservation/StringArrayReservation.java     |   45 +
 .../reservation/StringCheckedReservation.java   |   44 +
 .../stream/reservation/StringReservation.java   |   43 +
 .../stream/reservation/package-info.java        |   24 +
 .../read/BooleanCheckedDataReader.java          |   33 +
 .../read/BooleanDataArrayReader.java            |   36 +
 .../reservation/read/BooleanDataReader.java     |   33 +
 .../read/DoubleCheckedDataReader.java           |   32 +
 .../reservation/read/DoubleDataArrayReader.java |   35 +
 .../reservation/read/DoubleDataReader.java      |   32 +
 .../read/FloatCheckedDataReader.java            |   33 +
 .../reservation/read/FloatDataArrayReader.java  |   36 +
 .../reservation/read/FloatDataReader.java       |   33 +
 .../reservation/read/IntCheckedDataReader.java  |   32 +
 .../reservation/read/IntDataArrayReader.java    |   34 +
 .../stream/reservation/read/IntDataReader.java  |   32 +
 .../reservation/read/LongCheckedDataReader.java |   32 +
 .../reservation/read/LongDataArrayReader.java   |   35 +
 .../stream/reservation/read/LongDataReader.java |   32 +
 .../read/ReductionCheckedDataReader.java        |   54 +
 .../read/ReductionDataArrayReader.java          |   54 +
 .../reservation/read/ReductionDataReader.java   |   40 +
 .../read/StringCheckedDataReader.java           |   32 +
 .../reservation/read/StringDataArrayReader.java |   35 +
 .../reservation/read/StringDataReader.java      |   34 +
 .../stream/reservation/read/package-info.java   |   24 +
 .../write/BooleanCheckedDataWriter.java         |   33 +
 .../write/BooleanDataArrayWriter.java           |   36 +
 .../reservation/write/BooleanDataWriter.java    |   33 +
 .../write/DoubleCheckedDataWriter.java          |   34 +
 .../write/DoubleDataArrayWriter.java            |   36 +
 .../reservation/write/DoubleDataWriter.java     |   33 +
 .../write/FloatCheckedDataWriter.java           |   35 +
 .../reservation/write/FloatDataArrayWriter.java |   37 +
 .../reservation/write/FloatDataWriter.java      |   34 +
 .../reservation/write/IntCheckedDataWriter.java |   34 +
 .../reservation/write/IntDataArrayWriter.java   |   35 +
 .../stream/reservation/write/IntDataWriter.java |   33 +
 .../write/LongCheckedDataWriter.java            |   34 +
 .../reservation/write/LongDataArrayWriter.java  |   36 +
 .../reservation/write/LongDataWriter.java       |   33 +
 .../write/ReductionCheckedDataWriter.java       |   60 +
 .../write/ReductionDataArrayWriter.java         |   53 +
 .../reservation/write/ReductionDataWriter.java  |   40 +
 .../write/StringCheckedDataWriter.java          |   34 +
 .../write/StringDataArrayWriter.java            |   36 +
 .../reservation/write/StringDataWriter.java     |   37 +
 .../stream/reservation/write/package-info.java  |   24 +
 .../solr/analytics/util/AnalyticsParams.java    |  114 -
 .../solr/analytics/util/AnalyticsParsers.java   |  171 -
 .../util/AnalyticsResponseHeadings.java         |   36 +
 .../analytics/util/FacetRangeGenerator.java     |  356 ++
 .../solr/analytics/util/MedianCalculator.java   |    4 +
 .../solr/analytics/util/OldAnalyticsParams.java |  177 +
 .../util/OldAnalyticsRequestConverter.java      |  177 +
 .../solr/analytics/util/OrdinalCalculator.java  |  173 +
 .../analytics/util/PercentileCalculator.java    |  176 -
 .../analytics/util/RangeEndpointCalculator.java |  354 --
 .../util/function/BooleanConsumer.java          |   59 +
 .../analytics/util/function/FloatConsumer.java  |   59 +
 .../analytics/util/function/FloatSupplier.java  |   41 +
 .../analytics/util/function/package-info.java   |   23 +
 .../solr/analytics/util/package-info.java       |    3 +-
 .../AbsoluteValueDoubleFunction.java            |   60 -
 .../util/valuesource/AddDoubleFunction.java     |   49 -
 .../util/valuesource/ConstDateSource.java       |  112 -
 .../util/valuesource/ConstDoubleSource.java     |  104 -
 .../util/valuesource/ConstStringSource.java     |   50 -
 .../util/valuesource/DateFieldSource.java       |  131 -
 .../util/valuesource/DateMathFunction.java      |   71 -
 .../util/valuesource/DivDoubleFunction.java     |   48 -
 .../util/valuesource/DualDoubleFunction.java    |   94 -
 .../util/valuesource/FilterFieldSource.java     |  154 -
 .../util/valuesource/LogDoubleFunction.java     |   43 -
 .../util/valuesource/MultiDateFunction.java     |  133 -
 .../util/valuesource/MultiDoubleFunction.java   |  119 -
 .../valuesource/MultiplyDoubleFunction.java     |   49 -
 .../util/valuesource/NegateDoubleFunction.java  |   55 -
 .../util/valuesource/PowDoubleFunction.java     |   48 -
 .../util/valuesource/ReverseStringFunction.java |   45 -
 .../util/valuesource/SingleDoubleFunction.java  |   79 -
 .../util/valuesource/SingleStringFunction.java  |  117 -
 .../util/valuesource/package-info.java          |   24 -
 .../solr/analytics/value/AnalyticsValue.java    |   55 +
 .../analytics/value/AnalyticsValueStream.java   |  133 +
 .../solr/analytics/value/BooleanValue.java      |   85 +
 .../analytics/value/BooleanValueStream.java     |   55 +
 .../solr/analytics/value/ComparableValue.java   |   32 +
 .../apache/solr/analytics/value/DateValue.java  |  102 +
 .../solr/analytics/value/DateValueStream.java   |   62 +
 .../solr/analytics/value/DoubleValue.java       |   86 +
 .../solr/analytics/value/DoubleValueStream.java |   54 +
 .../apache/solr/analytics/value/FloatValue.java |   97 +
 .../solr/analytics/value/FloatValueStream.java  |   60 +
 .../apache/solr/analytics/value/IntValue.java   |  121 +
 .../solr/analytics/value/IntValueStream.java    |   71 +
 .../apache/solr/analytics/value/LongValue.java  |   97 +
 .../solr/analytics/value/LongValueStream.java   |   60 +
 .../solr/analytics/value/StringValue.java       |   71 +
 .../solr/analytics/value/StringValueStream.java |   49 +
 .../value/constant/ConstantBooleanValue.java    |   91 +
 .../value/constant/ConstantDateValue.java       |  103 +
 .../value/constant/ConstantDoubleValue.java     |   90 +
 .../value/constant/ConstantFloatValue.java      |   99 +
 .../value/constant/ConstantIntValue.java        |  118 +
 .../value/constant/ConstantLongValue.java       |  100 +
 .../value/constant/ConstantStringValue.java     |   79 +
 .../analytics/value/constant/ConstantValue.java |  128 +
 .../analytics/value/constant/package-info.java  |   23 +
 .../solr/analytics/value/package-info.java      |   23 +
 .../apache/solr/handler/AnalyticsHandler.java   |  147 +
 .../handler/component/AnalyticsComponent.java   |  119 +-
 .../java/org/apache/solr/handler/package.html   |   28 +
 .../response/AnalyticsShardResponseWriter.java  |   91 +
 .../java/org/apache/solr/response/package.html  |   28 +
 .../analytics/requestFiles/expressions.txt      |   70 -
 .../analytics/requestFiles/fieldFacetExtras.txt |   66 -
 .../analytics/requestFiles/fieldFacets.txt      |  132 -
 .../analytics/requestFiles/functions.txt        |   62 -
 .../analytics/requestFiles/noFacets.txt         |   74 -
 .../analytics/requestFiles/queryFacets.txt      |   45 -
 .../analytics/requestFiles/rangeFacets.txt      |  170 -
 .../analytics/requestXMLFiles/expressions.xml   |  285 --
 .../requestXMLFiles/fieldFacetExtras.xml        |  101 -
 .../analytics/requestXMLFiles/fieldFacets.xml   |  496 ---
 .../analytics/requestXMLFiles/functions.xml     |  246 --
 .../analytics/requestXMLFiles/noFacets.xml      |  310 --
 .../analytics/requestXMLFiles/queryFacets.xml   |   94 -
 .../analytics/requestXMLFiles/rangeFacets.xml   |  319 --
 .../test-files/solr/analytics/expressions.txt   |   65 +
 .../test-files/solr/analytics/facetSorting.txt  |    4 +
 .../solr/analytics/fieldFacetExtras.txt         |   66 +
 .../test-files/solr/analytics/fieldFacets.txt   |  132 +
 .../src/test-files/solr/analytics/functions.txt |   57 +
 .../src/test-files/solr/analytics/noFacets.txt  |   74 +
 .../test-files/solr/analytics/queryFacets.txt   |   27 +
 .../test-files/solr/analytics/rangeFacets.txt   |  161 +
 .../solr/collection1/conf/schema-analytics.xml  |    7 +-
 .../collection1/conf/solrconfig-analytics.xml   |   42 +
 .../solr/collection1/conf/solrconfig-basic.xml  |   40 -
 .../configsets/cloud-analytics/conf/schema.xml  |   63 +
 .../cloud-analytics/conf/solrconfig.xml         |   59 +
 .../AbstractAnalyticsStatsCloudTest.java        |  187 +
 .../analytics/AbstractAnalyticsStatsTest.java   |   14 +-
 .../apache/solr/analytics/NoFacetCloudTest.java |  557 +++
 .../org/apache/solr/analytics/NoFacetTest.java  |   46 +-
 .../analytics/expression/ExpressionTest.java    |   70 +-
 .../solr/analytics/expression/FunctionTest.java |  221 ++
 .../facet/AbstractAnalyticsFacetCloudTest.java  |  284 ++
 .../facet/AbstractAnalyticsFacetTest.java       |   37 +-
 .../solr/analytics/facet/FacetSortingTest.java  |   53 +
 .../analytics/facet/FieldFacetCloudTest.java    | 1214 +++++++
 .../facet/FieldFacetExtrasCloudTest.java        |  253 ++
 .../analytics/facet/FieldFacetExtrasTest.java   |    6 +-
 .../solr/analytics/facet/FieldFacetTest.java    |   63 +-
 .../analytics/facet/QueryFacetCloudTest.java    |  159 +
 .../solr/analytics/facet/QueryFacetTest.java    |   10 +-
 .../analytics/facet/RangeFacetCloudTest.java    |  588 ++++
 .../solr/analytics/facet/RangeFacetTest.java    |   43 +-
 .../util/valuesource/FunctionTest.java          |  233 --
 .../solr/handler/component/ResponseBuilder.java |    3 +
 313 files changed, 30374 insertions(+), 9933 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 208512c..9578698 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -116,6 +116,10 @@ Upgrading from Solr 6.x
      curl http://host:8983/solr/mycollection/config -d '{"set-user-property": {"update.autoCreateFields":"false"}}'
   Please see SOLR-10574 for details.
 
+* SOLR-10123: The Analytics Component has been upgraded to support distributed collections, expressions over multivalued
+  fields, a new JSON request language, and more. DocValues are now required for any field used in the analytics expression
+  whereas previously docValues was not required. Please see SOLR-10123 for details.
+
 New Features
 ----------------------
 * SOLR-9857, SOLR-9858: Collect aggregated metrics from nodes and shard leaders in overseer. (ab)
@@ -175,6 +179,10 @@ New Features
 
 * SOLR-10272: Use _default config set if no collection.configName is specified with CREATE (Ishan Chattopadhyaya)
 
+* SOLR-10123: Upgraded the Analytics Component to version 2.0 which now supports distributed collections, expressions over 
+  multivalued fields, a new JSON request language, and more. DocValues are now required for any field used in the analytics 
+  expression  whereas previously docValues was not required. Please see SOLR-10123 for details. (Houston Putman)
+
 Bug Fixes
 ----------------------
 * SOLR-9262: Connection and read timeouts are being ignored by UpdateShardHandler after SOLR-4509.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsDriver.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsDriver.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsDriver.java
new file mode 100644
index 0000000..21b053f
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsDriver.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.search.DocIdSet;
+import org.apache.lucene.search.DocIdSetIterator;
+import org.apache.solr.analytics.AnalyticsRequestManager.StreamingInfo;
+import org.apache.solr.analytics.facet.AbstractSolrQueryFacet.FacetValueQueryExecuter;
+import org.apache.solr.analytics.facet.StreamingFacet;
+import org.apache.solr.analytics.function.ReductionCollectionManager;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.search.Filter;
+import org.apache.solr.search.SolrIndexSearcher;
+
+public class AnalyticsDriver {
+  
+  /**
+   * Drive the collection of reduction data. This includes overall data as well as faceted data.
+   * 
+   * @param manager of the request to drive
+   * @param searcher the results of the query
+   * @param filter that represents the overall query
+   * @param queryRequest used for the search request
+   * @throws IOException if an error occurs while reading from Solr
+   */
+  public static void drive(AnalyticsRequestManager manager, SolrIndexSearcher searcher, Filter filter, SolrQueryRequest queryRequest) throws IOException {
+    StreamingInfo streamingInfo = manager.getStreamingFacetInfo();
+    Iterable<StreamingFacet> streamingFacets = streamingInfo.streamingFacets;
+    ReductionCollectionManager collectionManager = streamingInfo.streamingCollectionManager;
+    
+    Iterable<FacetValueQueryExecuter> facetExecuters = manager.getFacetExecuters(filter, queryRequest);
+    
+    // Streaming phase (Overall results & Value/Pivot Facets)
+    // Loop through all documents and collect reduction data for streaming facets and overall results
+    if (collectionManager.needsCollection()) {
+      List<LeafReaderContext> contexts = searcher.getTopReaderContext().leaves();
+      for (int leafNum = 0; leafNum < contexts.size(); leafNum++) {
+        LeafReaderContext context = contexts.get(leafNum);
+        DocIdSet dis = filter.getDocIdSet(context, null); // solr docsets already exclude any deleted docs
+        if (dis == null) {
+          continue;
+        }
+        DocIdSetIterator disi = dis.iterator();
+        if (disi != null) {
+          collectionManager.doSetNextReader(context);
+          int doc = disi.nextDoc();
+          while( doc != DocIdSetIterator.NO_MORE_DOCS){
+            // Add a document to the statistics being generated
+            collectionManager.collect(doc);
+            streamingFacets.forEach( facet -> facet.addFacetValueCollectionTargets() );
+            collectionManager.apply();
+            doc = disi.nextDoc();
+          }
+        }
+      }
+    }
+    
+    // Executing phase (Query/Range Facets)
+    // Send additional Solr Queries to compute facet values
+    for (FacetValueQueryExecuter executer : facetExecuters) {
+      executer.execute(searcher);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsExpression.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsExpression.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsExpression.java
new file mode 100644
index 0000000..044e371
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsExpression.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics;
+
+import org.apache.solr.analytics.function.ReductionCollectionManager;
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+import org.apache.solr.analytics.value.AnalyticsValue;
+
+/**
+ * A wrapper for a top-level analytics expression.
+ * The expression must have a name and be single valued.
+ */
+public class AnalyticsExpression {
+  private final AnalyticsValue expression;
+  private final String name;
+  
+  public AnalyticsExpression(String name, AnalyticsValue expression) {
+    this.name = name;
+    this.expression = expression;
+  }
+  
+  public String getName() {
+    return name;
+  }
+  
+  public AnalyticsValue getExpression() {
+    return expression;
+  }
+  
+  /**
+   * Get the current value of the expression.
+   * This method can, and will, be called multiple times to return different values.
+   * The value returned is based on the {@link ReductionDataCollection} given
+   * to the {@link ReductionCollectionManager#setData} method.
+   * 
+   * @return the current value of the expression
+   */
+  public Object toObject() {
+    return expression.getObject();
+  }
+  
+  /**
+   * NOTE: Must be called after {@link #toObject()} is called, otherwise the value is not guaranteed to be correct.
+   * 
+   * @return whether the current value of the expression exists.
+   */
+  public boolean exists() {
+    return expression.exists();
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsGroupingManager.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsGroupingManager.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsGroupingManager.java
new file mode 100644
index 0000000..a95a451
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsGroupingManager.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file inputtributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * inputtributed under the License is inputtributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.facet.AnalyticsFacet;
+import org.apache.solr.analytics.facet.PivotFacet;
+import org.apache.solr.analytics.facet.AbstractSolrQueryFacet;
+import org.apache.solr.analytics.facet.QueryFacet;
+import org.apache.solr.analytics.facet.RangeFacet;
+import org.apache.solr.analytics.facet.StreamingFacet;
+import org.apache.solr.analytics.facet.ValueFacet;
+import org.apache.solr.analytics.facet.AbstractSolrQueryFacet.FacetValueQueryExecuter;
+import org.apache.solr.analytics.function.ExpressionCalculator;
+import org.apache.solr.analytics.function.ReductionCollectionManager;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.search.Filter;
+
+/**
+ * The manager for faceted analytics. This class manages one grouping of facets and expressions to compute
+ * over those facets.
+ * 
+ * <p>
+ * This class will only manage generating faceted results, not overall results.
+ */
+public class AnalyticsGroupingManager {
+  private final String name;
+  private final ReductionCollectionManager reductionCollectionManager;
+
+  private final Collection<AnalyticsExpression> topLevelExpressions;
+  private final ExpressionCalculator expressionCalculator;
+  
+  private final Map<String, AnalyticsFacet> facets;
+  
+  public AnalyticsGroupingManager(String name,
+                                  ReductionCollectionManager reductionCollectionManager,
+                                  Collection<AnalyticsExpression> topLevelExpressions) {
+    this.name = name;
+    this.reductionCollectionManager = reductionCollectionManager;
+
+    this.topLevelExpressions = topLevelExpressions;
+    this.expressionCalculator = new ExpressionCalculator(topLevelExpressions);
+
+    this.facets = new HashMap<>();
+  }
+
+  // This is outside of the method, since it is used in the lambda and cannot be a local non-final variable
+  private boolean hasStreamingFacets;
+  
+  /**
+   * Get the {@link StreamingFacet}s (e.g. {@link ValueFacet} and {@link PivotFacet}) contained within this grouping,
+   * returning them through the given consumer.
+   * 
+   * @param cons where the streaming facets are passed to
+   * @return whether the grouping contains streaming facets
+   */
+  public boolean getStreamingFacets(Consumer<StreamingFacet> cons) {
+    hasStreamingFacets = false;
+    facets.forEach( (name, facet) -> {
+      if (facet instanceof StreamingFacet) {
+        cons.accept((StreamingFacet)facet);
+        hasStreamingFacets = true;
+      }
+    });
+    return hasStreamingFacets;
+  }
+
+  /**
+   * Create the {@link FacetValueQueryExecuter}s for all {@link AbstractSolrQueryFacet}s
+   * (e.g. {@link QueryFacet} and {@link RangeFacet}) contained within this grouping.
+   * The executers are returned through the given consumer.
+   * 
+   * <p>
+   * One {@link FacetValueQueryExecuter} is created for each facet value to be returned for a facet.
+   * Since every {@link AbstractSolrQueryFacet} has discrete and user-defined facet values,
+   * unlike {@link StreamingFacet}s, a discrete number of {@link FacetValueQueryExecuter}s are created and returned.
+   * 
+   * @param filter representing the overall Solr Query of the request,
+   * will be combined with the facet value queries
+   * @param queryRequest from the overall search request
+   * @param cons where the executers are passed to
+   */
+  public void getFacetExecuters(Filter filter, SolrQueryRequest queryRequest, Consumer<FacetValueQueryExecuter> cons) {
+    facets.forEach( (name, facet) -> {
+      if (facet instanceof AbstractSolrQueryFacet) {
+        ((AbstractSolrQueryFacet)facet).createFacetValueExecuters(filter, queryRequest, cons);
+      }
+    });
+  }
+  
+  /**
+   * Add a facet to the grouping. All expressions in this grouping will be computed over the facet.
+   * 
+   * @param facet to compute expressions over
+   */
+  public void addFacet(AnalyticsFacet facet) {
+    facet.setExpressionCalculator(expressionCalculator);
+    facet.setReductionCollectionManager(reductionCollectionManager);
+    facets.put(facet.getName(), facet);
+  }
+  
+  /**
+   * Import the shard data for this grouping from a bit-stream,
+   * exported by the {@link #exportShardData} method in the each of the collection's shards.
+   * 
+   * @param input The bit-stream to import the grouping data from
+   * @throws IOException if an exception occurs while reading from the {@link DataInput}
+   */
+  public void importShardData(DataInput input) throws IOException {
+    // This allows mergeData() to import from the same input everytime it is called
+    // while the facets are importing.
+    reductionCollectionManager.setShardInput(input);
+    
+    int sz = input.readInt();
+    for (int i = 0; i < sz; ++i) {
+      facets.get(input.readUTF()).importShardData(input);
+    }
+  }
+  
+  /**
+   * Export the shard data for this grouping through a bit-stream,
+   * to be imported by the {@link #importShardData} method in the originating shard.
+   * 
+   * @param output The bit-stream to output the grouping data through
+   * @throws IOException if an exception occurs while writing to the {@link DataOutput}
+   */
+  public void exportShardData(DataOutput output) throws IOException {
+    // This allows exportData() to export to the same output everytime it is called
+    // while the facets are exporting.
+    reductionCollectionManager.setShardOutput(output);
+    
+    output.writeInt(facets.size());
+    for (Entry<String,AnalyticsFacet> facet : facets.entrySet()) {
+      output.writeUTF(facet.getKey());
+      facet.getValue().exportShardData(output);
+    }
+  }
+  
+  /**
+   * Get the {@link ReductionCollectionManager} that manages the collection of reduction data for the expressions
+   * contained within this grouping. 
+   * 
+   * @return the grouping's reduction manager
+   */
+  public ReductionCollectionManager getReductionManager() {
+    return reductionCollectionManager;
+  }
+
+  /**
+   * Create the response for this grouping, a mapping from each of it's facets' names to the facet's response.
+   * 
+   * @return the named list representation of the response
+   */
+  public Map<String,Object> createResponse() {
+    Map<String,Object> response = new HashMap<>();
+    
+    // Add the value facet buckets to the output
+    facets.forEach( (name, facet) -> response.put(name, facet.createResponse()) );
+
+    return response;
+  }
+  
+  /**
+   * Create the response for this grouping, but in the old style of response.
+   * This response has a bucket for the following if they are contained in the grouping:
+   * FieldFacets, RangeFacets and QueryFacets.
+   * Each facet's name and response are put into the bucket corresponding to its type.
+   * <p>
+   * Since groupings in the old notation must also return overall results, the overall results are
+   * passed in and the values are used to populate the grouping response.
+   * 
+   * @param overallResults of the expressions to add to the grouping response
+   * @return the named list representation of the response
+   */
+  public NamedList<Object> createOldResponse(Map<String,Object> overallResults) {
+    NamedList<Object> response = new NamedList<>();
+    
+    topLevelExpressions.forEach( expression -> response.add(expression.getName(), overallResults.get(name + expression.getName())));
+
+    NamedList<Object> fieldFacetResults = new NamedList<>();
+    NamedList<Object> rangeFacetResults = new NamedList<>();
+    NamedList<Object> queryFacetResults = new NamedList<>();
+    // Add the field facet buckets to the output
+    facets.forEach( (name, facet) -> {
+      // The old style of request only accepts field facets
+      // So we can assume that all value facets are field facets
+      if (facet instanceof ValueFacet) {
+        fieldFacetResults.add(name, facet.createOldResponse());
+      } else if (facet instanceof RangeFacet) {
+        rangeFacetResults.add(name, facet.createOldResponse());
+      } else if (facet instanceof QueryFacet) {
+        queryFacetResults.add(name, facet.createOldResponse());
+      }
+    });
+    if (fieldFacetResults.size() > 0) {
+      response.add(AnalyticsResponseHeadings.FIELD_FACETS, fieldFacetResults);
+    }
+    if (rangeFacetResults.size() > 0) {
+      response.add(AnalyticsResponseHeadings.RANGE_FACETS, rangeFacetResults);
+    }
+    if (queryFacetResults.size() > 0) {
+      response.add(AnalyticsResponseHeadings.QUERY_FACETS, queryFacetResults);
+    }
+    return response;
+  }
+
+  /**
+   * Get the name of the grouping.
+   * 
+   * @return the grouping name
+   */
+  public String getName() {
+    return name;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsRequestManager.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsRequestManager.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsRequestManager.java
new file mode 100644
index 0000000..45b958f
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsRequestManager.java
@@ -0,0 +1,279 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.analytics.facet.AbstractSolrQueryFacet;
+import org.apache.solr.analytics.facet.AbstractSolrQueryFacet.FacetValueQueryExecuter;
+import org.apache.solr.analytics.facet.StreamingFacet;
+import org.apache.solr.analytics.function.ExpressionCalculator;
+import org.apache.solr.analytics.function.ReductionCollectionManager;
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+import org.apache.solr.analytics.stream.AnalyticsShardRequestManager;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.search.Filter;
+
+/**
+ * The manager of an entire analytics request.
+ */
+public class AnalyticsRequestManager {
+  private final ReductionCollectionManager ungroupedReductionManager;
+  private ReductionDataCollection ungroupedData;
+  
+  private final Map<String, AnalyticsGroupingManager> groupingManagers;
+  
+  private final Collection<AnalyticsExpression> ungroupedExpressions;
+  private final ExpressionCalculator ungroupedExpressionCalculator;
+  
+  /**
+   * If the request is distributed, the manager for shard requests.
+   */
+  public String analyticsRequest;
+  public AnalyticsShardRequestManager shardStream;
+  public boolean sendShards; 
+  
+  /**
+   * Create an manager with the given ungrouped expressions. This is straightforward in the new
+   * style of request, however in the old olap-style requests all groupings' expressions are expected
+   * to be ungrouped as well.
+   * 
+   * 
+   * @param ungroupedReductionManager to manage the reduction collection for all ungrouped expressions
+   * @param ungroupedExpressions to compute overall results for
+   */
+  public AnalyticsRequestManager(ReductionCollectionManager ungroupedReductionManager,
+                                 Collection<AnalyticsExpression> ungroupedExpressions) {
+    this.ungroupedReductionManager = ungroupedReductionManager;
+    this.ungroupedData = ungroupedReductionManager.newDataCollection();
+    this.ungroupedReductionManager.addLastingCollectTarget(ungroupedData);
+    
+    this.ungroupedExpressions = ungroupedExpressions;
+    this.ungroupedExpressionCalculator = new ExpressionCalculator(ungroupedExpressions);
+    this.groupingManagers = new HashMap<>();
+  }
+  
+  /**
+   * Get the collection manager for ungrouped expressions, including grouped expressions if
+   * the old request notation is used.
+   * 
+   * @return the collection manager for the ungrouped expressions
+   */
+  public ReductionCollectionManager getUngroupedCollectionManager() {
+    return ungroupedReductionManager;
+  }
+  
+  /**
+   * Get the collection manager for all ungrouped expressions, including grouped expressions if
+   * the old request notation is used.
+   * 
+   * @return the collection manager for the ungrouped expressions
+   */
+  public ReductionDataCollection getUngroupedData() {
+    return ungroupedData;
+  }
+  
+  /**
+   * Return all ungrouped expressions, including grouped expressions if
+   * the old request notation is used.
+   * 
+   * @return an {@link Iterable} of the ungrouped expressions
+   */
+  public Iterable<AnalyticsExpression> getUngroupedExpressions() {
+    return ungroupedExpressions;
+  }
+  
+  /**
+   * Generate the results of all ungrouped expressions, including grouped expressions if
+   * the old request notation is used.
+   * 
+   * @param response the response to add the ungrouped results to.
+   */
+  public void addUngroupedResults(Map<String,Object> response) {
+    ungroupedReductionManager.setData(ungroupedData);
+    ungroupedExpressionCalculator.addResults(response);
+  }
+  
+  /**
+   * Generate the results of all ungrouped expressions, including grouped expressions if
+   * the old request notation is used.
+   * 
+   * @return the map containing the ungrouped results
+   */
+  public Map<String,Object> getUngroupedResults() {
+    ungroupedReductionManager.setData(ungroupedData);
+    return ungroupedExpressionCalculator.getResults();
+  }
+  
+  /**
+   * Add a grouping to the request.
+   * 
+   * @param groupingManager that manages the grouping
+   */
+  public void addGrouping(AnalyticsGroupingManager groupingManager) {
+    groupingManagers.put(groupingManager.getName(), groupingManager);
+  }
+  
+  /**
+   * Import the shard data for this request from a bit-stream,
+   * exported by the {@link #exportShardData} method in the each of the collection's shards.
+   * <p>
+   * First the overall data is imported, then the grouping data is imported.
+   * 
+   * @param input The bit-stream to import the shard data from
+   * @throws IOException if an exception occurs while reading from the {@link DataInput}
+   */
+  public synchronized void importShardData(DataInput input) throws IOException {
+    ungroupedReductionManager.setShardInput(input);
+    
+    // The ungroupedData will not exist for the first shard imported
+    if (ungroupedData == null) {
+      ungroupedData = ungroupedReductionManager.newDataCollectionIO();
+    } else {
+      ungroupedReductionManager.prepareReductionDataIO(ungroupedData);
+    }
+    ungroupedReductionManager.mergeData();
+    
+    int size = input.readInt();
+    while (--size >= 0) {
+      String groupingName = input.readUTF();
+      groupingManagers.get(groupingName).importShardData(input);
+    }
+  }
+  
+  /**
+   * Export the shard data for this request through a bit-stream,
+   * to be imported by the {@link #importShardData} method in the originating shard.
+   * <p>
+   * First the overall data is exported, then the grouping data is exported.
+   * 
+   * @param output The bit-stream to output the shard data through
+   * @throws IOException if an exception occurs while writing to the {@link DataOutput}
+   */
+  public void exportShardData(DataOutput output) throws IOException {
+    ungroupedReductionManager.setShardOutput(output);
+    
+    ungroupedReductionManager.prepareReductionDataIO(ungroupedData);
+    ungroupedReductionManager.exportData();
+    
+    output.writeInt(groupingManagers.size());
+    for (String groupingName : groupingManagers.keySet()) {
+      output.writeUTF(groupingName);
+      groupingManagers.get(groupingName).exportShardData(output);
+    }
+  }
+
+  /**
+   * Consolidate the information of all {@link StreamingFacet}s contained within the request, since
+   * they need to be collected along with the overall results during the streaming phase of the 
+   * {@link AnalyticsDriver}.
+   * 
+   * @return the info for all {@link StreamingFacet}s
+   */
+  public StreamingInfo getStreamingFacetInfo() {
+    StreamingInfo streamingInfo = new StreamingInfo();
+    ArrayList<ReductionCollectionManager> groupingCollectors = new ArrayList<>();
+    groupingManagers.values().forEach( grouping -> {
+      // If a grouping has streaming facets, then that groupings expressions
+      // must be collected during the streaming phase. 
+      if (grouping.getStreamingFacets( facet -> streamingInfo.streamingFacets.add(facet) )) {
+        groupingCollectors.add(grouping.getReductionManager());
+      }
+    });
+    
+    // Create an streaming collection manager to manage the collection of all ungrouped expressions and
+    // grouped expressions that are calculated over streaming facets.
+    streamingInfo.streamingCollectionManager = ungroupedReductionManager.merge(groupingCollectors);
+    return streamingInfo;
+  }
+  
+  /**
+   * Class to encapsulate all necessary data for collecting {@link StreamingFacet}s.
+   */
+  public static class StreamingInfo {
+    Collection<StreamingFacet> streamingFacets = new ArrayList<>();
+    /**
+     * Manages the collection of all expressions needed for streaming facets
+     */
+    ReductionCollectionManager streamingCollectionManager;
+  }
+
+  /**
+   * Create the {@link FacetValueQueryExecuter}s for all {@link AbstractSolrQueryFacet}s contained in the request.
+   * 
+   * @param filter representing the overall search query
+   * @param queryRequest of the overall search query
+   * @return an {@link Iterable} of executers
+   */
+  public Iterable<FacetValueQueryExecuter> getFacetExecuters(Filter filter, SolrQueryRequest queryRequest) {
+    ArrayList<FacetValueQueryExecuter> facetExecutors = new ArrayList<>();
+    groupingManagers.values().forEach( grouping -> {
+      grouping.getFacetExecuters(filter, queryRequest, executor -> facetExecutors.add(executor));
+    });
+    return facetExecutors;
+  }
+  
+  /**
+   * Create the response for a request given in the old olap-style format.
+   * The old response returned overall expressions within groupings.
+   * 
+   * @return a {@link NamedList} representation of the response
+   */
+  public NamedList<Object> createOldResponse() {
+    NamedList<Object> analyticsResponse = new NamedList<>();
+    Map<String,Object> ungroupedResults = getUngroupedResults();
+    groupingManagers.forEach( (name, groupingManager) -> {
+      analyticsResponse.add(name, groupingManager.createOldResponse(ungroupedResults));
+    });
+    
+    return analyticsResponse;
+  }
+  
+  /**
+   * Create the response for a request.
+   * 
+   * <p>
+   * NOTE: Analytics requests specified in the old olap-style format
+   * have their responses generated by {@link #createOldResponse()}.
+   * 
+   * @return a {@link Map} representation of the response
+   */
+  public Map<String,Object> createResponse() {
+    Map<String,Object> analyticsResponse = new HashMap<>();
+    if (ungroupedExpressions.size() > 0) {
+      addUngroupedResults(analyticsResponse);
+    }
+
+    Map<String,Object> groupingsResponse = new HashMap<>();
+    groupingManagers.forEach( (name, groupingManager) -> {
+      groupingsResponse.put(name, groupingManager.createResponse());
+    });
+    
+    if (groupingsResponse.size() > 0) {
+      analyticsResponse.put(AnalyticsResponseHeadings.GROUPINGS, groupingsResponse);
+    }
+    return analyticsResponse;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsRequestParser.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsRequestParser.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsRequestParser.java
new file mode 100644
index 0000000..bfa62e2
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/AnalyticsRequestParser.java
@@ -0,0 +1,549 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+import org.apache.solr.analytics.facet.PivotFacet;
+import org.apache.solr.analytics.facet.PivotNode;
+import org.apache.solr.analytics.facet.QueryFacet;
+import org.apache.solr.analytics.facet.RangeFacet;
+import org.apache.solr.analytics.facet.ValueFacet;
+import org.apache.solr.analytics.facet.SortableFacet.FacetSortSpecification;
+import org.apache.solr.analytics.facet.compare.DelegatingComparator;
+import org.apache.solr.analytics.facet.compare.FacetValueComparator;
+import org.apache.solr.analytics.facet.compare.FacetResultsComparator;
+import org.apache.solr.analytics.value.AnalyticsValue;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.ComparableValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.common.params.FacetParams.FacetRangeInclude;
+import org.apache.solr.common.params.FacetParams.FacetRangeOther;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.schema.SchemaField;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * Class to manage the parsing of new-style analytics requests.
+ */
+public class AnalyticsRequestParser {
+  
+  private static ObjectMapper mapper = new ObjectMapper();
+  
+  public static void init() {
+    mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
+    mapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, true);
+  }
+  
+  public static final String analyticsParamName = "analytics";
+
+  private static Predicate<String> request         = acceptNames("request", "req");
+  private static Predicate<String> functions       = acceptNames("functions", "funcs", "f");
+  private static Predicate<String> expressions     = acceptNames("expressions", "exprs", "e");
+
+  private static Predicate<String> grouping        = acceptNames("grouping", "group", "g");
+  
+  private static Predicate<String> valueFacet      = acceptNames("valuefacet", "vf");
+  
+  private static Predicate<String> pivotFacet      = acceptNames("pivotfacet", "pf");
+  private static Predicate<String> pivot           = acceptNames("pivot", "p");
+  
+  private static Predicate<String> sort            = acceptNames("sort", "s");
+  private static Predicate<String> sortExpression  = acceptNames("expression", "expr");
+  private static Predicate<String> sortFacetValue  = acceptNames("facetvalue", "fv");
+  private static Predicate<String> sortDirection   = acceptNames("direction", "dir");
+  private static Predicate<String> sortAscending   = acceptNames("ascending", "asc", "a");
+  private static Predicate<String> sortDescending  = acceptNames("descending", "desc", "d");
+  private static Predicate<String> sortLimit       = acceptNames("limit", "l");
+  private static Predicate<String> sortOffset      = acceptNames("offset", "o");
+  
+  private static Predicate<String> rangeFacet      = acceptNames("rangefacet", "rf");
+  private static Predicate<String> rangeGaps       = acceptNames("gaps", "g");
+  private static Predicate<String> rangeHardEnd    = acceptNames("hardend", "he");
+  private static Predicate<String> rangeInclude    = acceptNames("include", "i");
+  private static Predicate<String> rangeOthers     = acceptNames("others", "o");
+  
+  private static Predicate<String> queryFacet      = acceptNames("queryfacet", "qf");
+  private static Predicate<String> query           = acceptNames("query", "q");
+  
+  private static Predicate<String> acceptNames(String... names) {
+    return Pattern.compile("^(?:" + Arrays.stream(names).reduce((a,b) -> a + "|" + b).orElse("") + ")$", Pattern.CASE_INSENSITIVE).asPredicate();
+  }
+  
+  // Defaults
+  public static final String DEFAULT_SORT_DIRECTION = "ascending";
+  public static final int DEFAULT_OFFSET = 0;
+  public static final int DEFAULT_LIMIT = -1;
+  public static final boolean DEFAULT_HARDEND = false;
+  
+  @JsonInclude(Include.NON_EMPTY)
+  public static class AnalyticsRequest {
+    public Map<String, String> functions;
+    public Map<String, String> expressions;
+    
+    public Map<String, AnalyticsGroupingRequest> groupings;
+  }
+  
+  public static class AnalyticsGroupingRequest {
+    public Map<String, String> expressions;
+    
+    public Map<String, AnalyticsFacetRequest> facets;
+  }
+  
+  @JsonTypeInfo(
+      use = JsonTypeInfo.Id.NAME,
+      include = JsonTypeInfo.As.PROPERTY,
+      property = "type"
+  )
+  @JsonSubTypes({
+    @Type(value = AnalyticsValueFacetRequest.class, name = "value"),
+    @Type(value = AnalyticsPivotFacetRequest.class, name = "pivot"),
+    @Type(value = AnalyticsRangeFacetRequest.class, name = "range"),
+    @Type(value = AnalyticsQueryFacetRequest.class, name = "query") }
+  )
+  @JsonInclude(Include.NON_EMPTY)
+  public static interface AnalyticsFacetRequest { }
+  
+  @JsonTypeName("value")
+  public static class AnalyticsValueFacetRequest implements AnalyticsFacetRequest {
+    public String expression;
+    public AnalyticsSortRequest sort;
+  }
+
+  @JsonTypeName("pivot")
+  public static class AnalyticsPivotFacetRequest implements AnalyticsFacetRequest {
+    public List<AnalyticsPivotRequest> pivots;
+  }
+  
+  public static class AnalyticsPivotRequest {
+    public String name;
+    public String expression;
+    public AnalyticsSortRequest sort;
+  }
+
+  @JsonInclude(Include.NON_EMPTY)
+  public static class AnalyticsSortRequest {
+    public List<AnalyticsSortCriteriaRequest> criteria;
+    public int limit = DEFAULT_LIMIT;
+    public int offset = DEFAULT_OFFSET;
+  }
+
+  @JsonTypeInfo(
+      use = JsonTypeInfo.Id.NAME,
+      include = JsonTypeInfo.As.PROPERTY,
+      property = "type"
+  )
+  @JsonSubTypes({
+    @Type(value = AnalyticsExpressionSortRequest.class, name = "expression"),
+    @Type(value = AnalyticsFacetValueSortRequest.class, name = "facetvalue") }
+  )
+  @JsonInclude(Include.NON_EMPTY)
+  public static abstract class AnalyticsSortCriteriaRequest {
+    public String direction;
+  }
+
+  @JsonTypeName("expression")
+  public static class AnalyticsExpressionSortRequest extends AnalyticsSortCriteriaRequest {
+    public String expression;
+  }
+
+  @JsonTypeName("facetvalue")
+  public static class AnalyticsFacetValueSortRequest extends AnalyticsSortCriteriaRequest { }
+
+  @JsonTypeName("range")
+  public static class AnalyticsRangeFacetRequest implements AnalyticsFacetRequest {
+    public String field;
+    public String start;
+    public String end;
+    public List<String> gaps;
+    public boolean hardend = DEFAULT_HARDEND;
+    public List<String> include;
+    public List<String> others;
+  }
+
+  @JsonTypeName("query")
+  public static class AnalyticsQueryFacetRequest implements AnalyticsFacetRequest {
+    public Map<String, String> queries;
+  }
+  
+  /* ***************
+   * Request & Groupings 
+   * ***************/
+  
+  public static AnalyticsRequestManager parse(AnalyticsRequest request, ExpressionFactory expressionFactory, boolean isDistribRequest) throws SolrException {
+    AnalyticsRequestManager manager = constructRequest(request, expressionFactory, isDistribRequest);
+    if (isDistribRequest) {
+      try {
+        manager.analyticsRequest = mapper.writeValueAsString(request);
+      } catch (JsonProcessingException e) {
+        throw new RuntimeException(e);
+      }
+    }
+    return manager;
+  }
+  
+  public static AnalyticsRequestManager parse(String rawRequest, ExpressionFactory expressionFactory, boolean isDistribRequest) throws SolrException {
+    JsonParser parser;
+    try {
+      parser = new JsonFactory().createParser(rawRequest)
+          .configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true)
+          .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
+    } catch (IOException e1) {
+      throw new RuntimeException(e1);
+    }
+    AnalyticsRequest request;
+    try {
+      request = mapper.readValue(parser, AnalyticsRequest.class);
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+
+    AnalyticsRequestManager manager = constructRequest(request, expressionFactory, isDistribRequest);
+    if (isDistribRequest) {
+      manager.analyticsRequest = rawRequest;
+    }
+    return manager;
+  }
+  
+  private static AnalyticsRequestManager constructRequest(AnalyticsRequest request, ExpressionFactory expressionFactory, boolean isDistribRequest) throws SolrException {
+    expressionFactory.startRequest();
+    
+    // Functions
+    if (request.functions != null) {
+      request.functions.forEach( (funcSig, retSig) -> expressionFactory.addUserDefinedVariableFunction(funcSig, retSig));
+    }
+    
+    // Expressions
+    Map<String,AnalyticsExpression> topLevelExpressions;
+    if (request.expressions != null) {
+      topLevelExpressions = constructExpressions(request.expressions, expressionFactory);
+    } else {
+      topLevelExpressions = new HashMap<>();
+    }
+    AnalyticsRequestManager manager = new AnalyticsRequestManager(expressionFactory.createReductionManager(isDistribRequest), topLevelExpressions.values());
+    
+    // Groupings
+    if (request.groupings != null) {
+      request.groupings.forEach( (name, grouping) -> {
+        manager.addGrouping(constructGrouping(name, grouping, expressionFactory, isDistribRequest));
+      });
+    }
+    return manager;
+  }
+  
+  private static AnalyticsGroupingManager constructGrouping(String name, AnalyticsGroupingRequest grouping, ExpressionFactory expressionFactory, boolean isDistribRequest) throws SolrException {
+    expressionFactory.startGrouping();
+    
+    // Expressions
+    if (grouping.expressions == null || grouping.expressions.size() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"Groupings must contain at least one expression, '" + name + "' has none.");
+    }
+    
+    Map<String,AnalyticsExpression> expressions = constructExpressions(grouping.expressions, expressionFactory);
+    AnalyticsGroupingManager manager = new AnalyticsGroupingManager(name, 
+                                                                    expressionFactory.createGroupingReductionManager(isDistribRequest), 
+                                                                    expressions.values());
+    
+    if (grouping.facets == null) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"Groupings must contain at least one facet, '" + name + "' has none.");
+    }
+    // Parse the facets
+    grouping.facets.forEach( (facetName, facet) -> {
+      if (facet instanceof AnalyticsValueFacetRequest) {
+        manager.addFacet(constructValueFacet(facetName, (AnalyticsValueFacetRequest) facet, expressionFactory, expressions));
+      } else if (facet instanceof AnalyticsPivotFacetRequest) {
+        manager.addFacet(constructPivotFacet(facetName, (AnalyticsPivotFacetRequest) facet, expressionFactory, expressions));
+      } else if (facet instanceof AnalyticsRangeFacetRequest) {
+        manager.addFacet(constructRangeFacet(facetName, (AnalyticsRangeFacetRequest) facet, expressionFactory.getSchema()));
+      } else if (facet instanceof AnalyticsQueryFacetRequest) {
+        manager.addFacet(constructQueryFacet(facetName, (AnalyticsQueryFacetRequest) facet));
+      } else {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The facet type, '" + facet.getClass().toString() + "' in "
+            + "grouping '" + name + "' is not a valid type of facet"); 
+      }
+    });
+    
+    return manager;
+  }
+  
+  /* ***************
+   * Expression & Functions 
+   * ***************/
+  
+  private static Map<String, AnalyticsExpression> constructExpressions(Map<String, String> rawExpressions, ExpressionFactory expressionFactory) throws SolrException {
+    Map<String, AnalyticsExpression> expressions = new HashMap<>();
+    rawExpressions.forEach( (name, expression) -> {
+      AnalyticsValueStream exprVal = expressionFactory.createExpression(expression);
+      if (exprVal instanceof AnalyticsValue) {
+        if (exprVal.getExpressionType().isReduced()) {
+          expressions.put(name, (new AnalyticsExpression(name, (AnalyticsValue)exprVal)));
+        } else {
+          throw new SolrException(ErrorCode.BAD_REQUEST,"Top-level expressions must be reduced, the '" + name + "' expression is not.");
+        }
+      } else {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"Top-level expressions must be single-valued, the '" + name + "' expression is not.");
+      }
+    });
+    return expressions;
+  }
+  
+  /* ***************
+   * FACETS 
+   * ***************/
+  
+  /*
+   * Value Facets
+   */
+  
+  private static ValueFacet constructValueFacet(String name, AnalyticsValueFacetRequest facetRequest, ExpressionFactory expressionFactory, Map<String, AnalyticsExpression> expressions) throws SolrException {
+    if (facetRequest.expression == null) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Value Facets must contain a mapping expression to facet over, '" + name + "' has none.");
+    }
+    
+    // The second parameter must be a mapping expression
+    AnalyticsValueStream expr = expressionFactory.createExpression(facetRequest.expression);
+    if (!expr.getExpressionType().isUnreduced()) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Value Facet expressions must be mapping expressions, "
+          + "the following expression in value facet '" + name + "' contains a reduction: " + facetRequest.expression);
+    }
+    if (!(expr instanceof StringValueStream)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Value Facet expressions must be castable to string expressions, "
+          + "the following expression in value facet '" + name + "' is not: " + facetRequest.expression);
+    }
+    
+    ValueFacet facet = new ValueFacet(name, (StringValueStream)expr);
+    
+    // Check if the value facet is sorted
+    if (facetRequest.sort != null) {
+      facet.setSort(constructSort(facetRequest.sort, expressions));
+    }
+    return facet;
+  }
+
+  /*
+   * Pivot Facets
+   */
+  
+  private static PivotFacet constructPivotFacet(String name, AnalyticsPivotFacetRequest facetRequest, ExpressionFactory expressionFactory, Map<String, AnalyticsExpression> expressions) throws SolrException {
+    PivotNode<?> topPivot = null;
+    
+    // Pivots
+    if (facetRequest.pivots == null || facetRequest.pivots.size() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Pivot Facets must contain at least one pivot to facet over, '" + name + "' has none.");
+    }
+    
+    ListIterator<AnalyticsPivotRequest> iter = facetRequest.pivots.listIterator(facetRequest.pivots.size());
+    while (iter.hasPrevious()) {
+      topPivot = constructPivot(iter.previous(), topPivot, expressionFactory, expressions);
+    }
+    
+    return new PivotFacet(name, topPivot);
+  }
+  
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  private static PivotNode<?> constructPivot(AnalyticsPivotRequest pivotRequest,
+                                      PivotNode<?> childPivot,
+                                      ExpressionFactory expressionFactory,
+                                      Map<String, AnalyticsExpression> expressions) throws SolrException {
+    if (pivotRequest.name == null || pivotRequest.name.length() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Pivots must have a name.");
+    }
+    if (pivotRequest.expression == null) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Pivots must have an expression to facet over, '" + pivotRequest.name + "' does not.");
+    }
+    
+    // The second parameter must be a mapping expression
+    AnalyticsValueStream expr = expressionFactory.createExpression(pivotRequest.expression);
+    if (!expr.getExpressionType().isUnreduced()) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Pivot expressions must be mapping expressions, "
+          + "the following expression in pivot '" + pivotRequest.name + "' contains a reduction: " + pivotRequest.expression);
+    }
+    if (!(expr instanceof StringValueStream)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Pivot expressions must be castable to string expressions, "
+          + "the following expression in pivot '" + pivotRequest.name + "' is not: '" + pivotRequest.expression);
+    }
+    
+    PivotNode<?> pivot;
+    if (childPivot == null) {
+      pivot = new PivotNode.PivotLeaf(pivotRequest.name, (StringValueStream)expr);
+    } else {
+      pivot = new PivotNode.PivotBranch(pivotRequest.name, (StringValueStream)expr, childPivot);
+    }
+    
+    // Check if the pivot is sorted
+    if (pivotRequest.sort != null) {
+      pivot.setSort(constructSort(pivotRequest.sort, expressions));
+    }
+    return pivot;
+  }
+  
+  /*
+   * Range Facets
+   */
+
+  private static RangeFacet constructRangeFacet(String name, AnalyticsRangeFacetRequest facetRequest, IndexSchema schema) throws SolrException {
+    if (facetRequest.field == null || facetRequest.field.length() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Range Facets must specify a field to facet over, '" +name + "' does not.");
+    }
+    SchemaField field = schema.getFieldOrNull(facetRequest.field);
+    if (field == null) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Range Facets must have a valid field as the second parameter. The '" + name + "' facet "
+          + "tries to facet over the non-existent field: " + facetRequest.field);
+    }
+
+    if (facetRequest.start == null || facetRequest.start.length() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Range Facets must specify a start value, '" +name + "' does not.");
+    }
+    if (facetRequest.end == null || facetRequest.end.length() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Range Facets must specify a end value, '" +name + "' does not.");
+    }
+    if (facetRequest.gaps == null || facetRequest.gaps.size() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Range Facets must specify a gap or list of gaps to determine facet buckets, '" +name + "' does not.");
+    }
+    RangeFacet facet = new RangeFacet(name, field, facetRequest.start, facetRequest.end, facetRequest.gaps);
+
+    facet.setHardEnd(facetRequest.hardend);
+
+    if (facetRequest.include != null && facetRequest.include.size() > 0) {
+      facet.setInclude(constructInclude(facetRequest.include));
+    }
+    if (facetRequest.others != null && facetRequest.others.size() > 0) {
+      facet.setOthers(constructOthers(facetRequest.others, name));
+    }
+    return facet;
+  }
+
+  private static EnumSet<FacetRangeInclude> constructInclude(List<String> includes) throws SolrException {
+    return FacetRangeInclude.parseParam(includes.toArray(new String[includes.size()]));
+  }
+
+  private static EnumSet<FacetRangeOther> constructOthers(List<String> othersRequest, String facetName) throws SolrException {
+    EnumSet<FacetRangeOther> others = EnumSet.noneOf(FacetRangeOther.class);
+    for (String rawOther : othersRequest) {
+      if (!others.add(FacetRangeOther.get(rawOther))) {
+        throw new SolrException(ErrorCode.BAD_REQUEST, "Duplicate include value '" + rawOther + "' found in range facet '" + facetName + "'");
+      }
+    }
+    if (others.contains(FacetRangeOther.NONE)) {
+      if (others.size() > 1) {
+        throw new SolrException(ErrorCode.BAD_REQUEST, "Include value 'NONE' is used with other includes in a range facet '" + facetName + "'. "
+            + "If 'NONE' is used, it must be the only include.");
+      }
+      return EnumSet.noneOf(FacetRangeOther.class);
+    }
+    if (others.contains(FacetRangeOther.ALL)) {
+      if (others.size() > 1) {
+        throw new SolrException(ErrorCode.BAD_REQUEST, "Include value 'ALL' is used with other includes in a range facet '" + facetName + "'. "
+            + "If 'ALL' is used, it must be the only include.");
+      }
+      return EnumSet.of(FacetRangeOther.BEFORE, FacetRangeOther.BETWEEN, FacetRangeOther.AFTER);
+    }
+    return others;
+  }
+
+  /*
+   * Query Facets
+   */
+  
+  private static QueryFacet constructQueryFacet(String name, AnalyticsQueryFacetRequest facetRequest) throws SolrException {
+    if (facetRequest.queries == null || facetRequest.queries.size() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Query Facets must be contain at least 1 query to facet over, '" + name + "' does not.");
+    }
+    
+    // The first param must be the facet name
+    return new QueryFacet(name, facetRequest.queries);
+  }
+  
+  /*
+   * Facet Sorting
+   */
+  
+  private static FacetSortSpecification constructSort(AnalyticsSortRequest sortRequest, Map<String, AnalyticsExpression> expressions) throws SolrException {
+    if (sortRequest.criteria == null || sortRequest.criteria.size() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Sorts must be given at least 1 criteria.");
+    }
+
+    return new FacetSortSpecification(constructSortCriteria(sortRequest.criteria, expressions), sortRequest.limit, sortRequest.offset);
+  }
+
+  private static FacetResultsComparator constructSortCriteria(List<AnalyticsSortCriteriaRequest> criteria, Map<String, AnalyticsExpression> expressions) {
+    ArrayList<FacetResultsComparator> comparators = new ArrayList<>();
+    for (AnalyticsSortCriteriaRequest criterion : criteria) {
+      FacetResultsComparator comparator;
+      if (criterion instanceof AnalyticsExpressionSortRequest) {
+        comparator = constructExpressionSortCriteria((AnalyticsExpressionSortRequest) criterion, expressions);
+      } else if (criterion instanceof AnalyticsFacetValueSortRequest) {
+        comparator = constructFacetValueSortCriteria((AnalyticsFacetValueSortRequest) criterion);
+      } else {
+        // Shouldn't happen
+        throw new SolrException(ErrorCode.BAD_REQUEST,"Sort Criteria must either be expressions or facetValues, '" + criterion.getClass().getName() + "' given.");
+      }
+      if (criterion.direction != null && criterion.direction.length() > 0) {
+        if (sortAscending.test(criterion.direction)) {
+          comparator.setDirection(true);
+        } else if (sortDescending.test(criterion.direction)) {
+          comparator.setDirection(false);
+        } else {
+          throw new SolrException(ErrorCode.BAD_REQUEST,"Sort direction '" + criterion.direction + " is not a recognized direction.");
+        }
+      }
+      comparators.add(comparator);
+    }
+    return DelegatingComparator.joinComparators(comparators);
+  }
+  
+  private static FacetResultsComparator constructExpressionSortCriteria(AnalyticsExpressionSortRequest criterion, Map<String, AnalyticsExpression> expressions) {
+    if (criterion.expression == null || criterion.expression.length() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"Expression Sorts must contain an expression parameter, none given.");
+    }
+
+    AnalyticsExpression expression = expressions.get(criterion.expression);
+    if (expression == null) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"Sort Expression not defined within the grouping: " + criterion.expression);
+    }
+    if (!(expression.getExpression() instanceof ComparableValue)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"Expression Sorts must be comparable, the following is not: " + criterion.expression);
+    }
+    return ((ComparableValue)expression.getExpression()).getObjectComparator(expression.getName());
+  }
+  
+  private static FacetResultsComparator constructFacetValueSortCriteria(AnalyticsFacetValueSortRequest criterion) {
+    return new FacetValueComparator();
+  }
+}


[21/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-6807: requestDispatcher/@handleSelect now defaults to false; stop using it. Deprecated StandardRequestHandler; stop using it.

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/spelling/WordBreakSolrSpellCheckerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/spelling/WordBreakSolrSpellCheckerTest.java b/solr/core/src/test/org/apache/solr/spelling/WordBreakSolrSpellCheckerTest.java
index f24bcba..258594a 100644
--- a/solr/core/src/test/org/apache/solr/spelling/WordBreakSolrSpellCheckerTest.java
+++ b/solr/core/src/test/org/apache/solr/spelling/WordBreakSolrSpellCheckerTest.java
@@ -158,7 +158,7 @@ public class WordBreakSolrSpellCheckerTest extends SolrTestCaseJ4 {
   public void testInConjunction() throws Exception {
     assertQ(req(
         "q", "lowerfilt:(paintable pine apple good ness)", 
-        "qt", "spellCheckWithWordbreak", 
+        "qt", "/spellCheckWithWordbreak",
         "indent", "true",
         SpellCheckComponent.SPELLCHECK_BUILD, "true",
         SpellCheckComponent.COMPONENT_NAME, "true", 
@@ -222,7 +222,7 @@ public class WordBreakSolrSpellCheckerTest extends SolrTestCaseJ4 {
   public void testCollate() throws Exception {
    assertQ(req(
         "q", "lowerfilt:(paintable pine apple godness)", 
-        "qt", "spellCheckWithWordbreak", 
+        "qt", "/spellCheckWithWordbreak",
         "indent", "true",
         SpellCheckComponent.SPELLCHECK_BUILD, "true",
         SpellCheckComponent.COMPONENT_NAME, "true", 
@@ -248,7 +248,7 @@ public class WordBreakSolrSpellCheckerTest extends SolrTestCaseJ4 {
     );
     assertQ(req(
         "q", "lowerfilt:(pine AND apple)", 
-        "qt", "spellCheckWithWordbreak", 
+        "qt", "/spellCheckWithWordbreak",
         "indent", "true",
         SpellCheckComponent.COMPONENT_NAME, "true", 
         SpellCheckComponent.SPELLCHECK_ACCURACY, ".75", 
@@ -262,7 +262,7 @@ public class WordBreakSolrSpellCheckerTest extends SolrTestCaseJ4 {
     );
     assertQ(req(
         "q", "lowerfilt:pine AND NOT lowerfilt:apple", 
-        "qt", "spellCheckWithWordbreak", 
+        "qt", "/spellCheckWithWordbreak",
         "indent", "true",
         SpellCheckComponent.COMPONENT_NAME, "true", 
         SpellCheckComponent.SPELLCHECK_ACCURACY, ".75", 
@@ -275,7 +275,7 @@ public class WordBreakSolrSpellCheckerTest extends SolrTestCaseJ4 {
     );
     assertQ(req(
         "q", "lowerfilt:pine NOT lowerfilt:apple", 
-        "qt", "spellCheckWithWordbreak", 
+        "qt", "/spellCheckWithWordbreak",
         "indent", "true",
         SpellCheckComponent.COMPONENT_NAME, "true", 
         SpellCheckComponent.SPELLCHECK_ACCURACY, ".75", 
@@ -288,7 +288,7 @@ public class WordBreakSolrSpellCheckerTest extends SolrTestCaseJ4 {
     );
     assertQ(req(
         "q", "lowerfilt:(+pine -apple)", 
-        "qt", "spellCheckWithWordbreak", 
+        "qt", "/spellCheckWithWordbreak",
         "indent", "true",
         SpellCheckComponent.COMPONENT_NAME, "true", 
         SpellCheckComponent.SPELLCHECK_ACCURACY, ".75", 
@@ -301,7 +301,7 @@ public class WordBreakSolrSpellCheckerTest extends SolrTestCaseJ4 {
     );
     assertQ(req(
         "q", "lowerfilt:(+printableinpuntableplantable)", 
-        "qt", "spellCheckWithWordbreak", 
+        "qt", "/spellCheckWithWordbreak",
         "indent", "true",
         SpellCheckComponent.COMPONENT_NAME, "true", 
         SpellCheckComponent.SPELLCHECK_ACCURACY, "1", 
@@ -313,7 +313,7 @@ public class WordBreakSolrSpellCheckerTest extends SolrTestCaseJ4 {
     );
     assertQ(req(
         "q", "zxcv AND qwtp AND fghj", 
-        "qt", "spellCheckWithWordbreak",
+        "qt", "/spellCheckWithWordbreak",
         "defType", "edismax",
         "qf", "lowerfilt",
         "indent", "true",

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/example/example-DIH/solr/db/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/example/example-DIH/solr/db/conf/solrconfig.xml b/solr/example/example-DIH/solr/db/conf/solrconfig.xml
index 46e7b87..c03529e 100644
--- a/solr/example/example-DIH/solr/db/conf/solrconfig.xml
+++ b/solr/example/example-DIH/solr/db/conf/solrconfig.xml
@@ -587,22 +587,8 @@
 
        This section contains instructions for how the SolrDispatchFilter
        should behave when processing requests for this SolrCore.
-
-       handleSelect is a legacy option that affects the behavior of requests
-       such as /select?qt=XXX
-
-       handleSelect="true" will cause the SolrDispatchFilter to process
-       the request and dispatch the query to a handler specified by the 
-       "qt" param, assuming "/select" isn't already registered.
-
-       handleSelect="false" will cause the SolrDispatchFilter to
-       ignore "/select" requests, resulting in a 404 unless a handler
-       is explicitly registered with the name "/select"
-
-       handleSelect="true" is not recommended for new users, but is the default
-       for backwards compatibility
     -->
-  <requestDispatcher handleSelect="false" >
+  <requestDispatcher>
     <!-- Request Parsing
 
          These settings indicate how Solr Requests may be parsed, and
@@ -699,14 +685,6 @@
        Incoming queries will be dispatched to a specific handler by name
        based on the path specified in the request.
 
-       Legacy behavior: If the request path uses "/select" but no Request
-       Handler has that name, and if handleSelect="true" has been specified in
-       the requestDispatcher, then the Request Handler is dispatched based on
-       the qt parameter.  Handlers without a leading '/' are accessed this way
-       like so: http://host/app/[core/]select?qt=name  If no qt is
-       given, then the requestHandler that declares default="true" will be
-       used or the one named "standard".
-
        If a Request Handler is declared with startup="lazy", then it will
        not be initialized until the first request that uses it.
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/example/example-DIH/solr/mail/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/example/example-DIH/solr/mail/conf/solrconfig.xml b/solr/example/example-DIH/solr/mail/conf/solrconfig.xml
index 950a891..28f415c 100644
--- a/solr/example/example-DIH/solr/mail/conf/solrconfig.xml
+++ b/solr/example/example-DIH/solr/mail/conf/solrconfig.xml
@@ -590,22 +590,8 @@
 
        This section contains instructions for how the SolrDispatchFilter
        should behave when processing requests for this SolrCore.
-
-       handleSelect is a legacy option that affects the behavior of requests
-       such as /select?qt=XXX
-
-       handleSelect="true" will cause the SolrDispatchFilter to process
-       the request and dispatch the query to a handler specified by the 
-       "qt" param, assuming "/select" isn't already registered.
-
-       handleSelect="false" will cause the SolrDispatchFilter to
-       ignore "/select" requests, resulting in a 404 unless a handler
-       is explicitly registered with the name "/select"
-
-       handleSelect="true" is not recommended for new users, but is the default
-       for backwards compatibility
     -->
-  <requestDispatcher handleSelect="false" >
+  <requestDispatcher>
     <!-- Request Parsing
 
          These settings indicate how Solr Requests may be parsed, and
@@ -702,14 +688,6 @@
        Incoming queries will be dispatched to a specific handler by name
        based on the path specified in the request.
 
-       Legacy behavior: If the request path uses "/select" but no Request
-       Handler has that name, and if handleSelect="true" has been specified in
-       the requestDispatcher, then the Request Handler is dispatched based on
-       the qt parameter.  Handlers without a leading '/' are accessed this way
-       like so: http://host/app/[core/]select?qt=name  If no qt is
-       given, then the requestHandler that declares default="true" will be
-       used or the one named "standard".
-
        If a Request Handler is declared with startup="lazy", then it will
        not be initialized until the first request that uses it.
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/example/example-DIH/solr/solr/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/example/example-DIH/solr/solr/conf/solrconfig.xml b/solr/example/example-DIH/solr/solr/conf/solrconfig.xml
index 0fd689f..7019be7 100644
--- a/solr/example/example-DIH/solr/solr/conf/solrconfig.xml
+++ b/solr/example/example-DIH/solr/solr/conf/solrconfig.xml
@@ -587,22 +587,8 @@
 
        This section contains instructions for how the SolrDispatchFilter
        should behave when processing requests for this SolrCore.
-
-       handleSelect is a legacy option that affects the behavior of requests
-       such as /select?qt=XXX
-
-       handleSelect="true" will cause the SolrDispatchFilter to process
-       the request and dispatch the query to a handler specified by the 
-       "qt" param, assuming "/select" isn't already registered.
-
-       handleSelect="false" will cause the SolrDispatchFilter to
-       ignore "/select" requests, resulting in a 404 unless a handler
-       is explicitly registered with the name "/select"
-
-       handleSelect="true" is not recommended for new users, but is the default
-       for backwards compatibility
     -->
-  <requestDispatcher handleSelect="false" >
+  <requestDispatcher>
     <!-- Request Parsing
 
          These settings indicate how Solr Requests may be parsed, and
@@ -699,14 +685,6 @@
        Incoming queries will be dispatched to a specific handler by name
        based on the path specified in the request.
 
-       Legacy behavior: If the request path uses "/select" but no Request
-       Handler has that name, and if handleSelect="true" has been specified in
-       the requestDispatcher, then the Request Handler is dispatched based on
-       the qt parameter.  Handlers without a leading '/' are accessed this way
-       like so: http://host/app/[core/]select?qt=name  If no qt is
-       given, then the requestHandler that declares default="true" will be
-       used or the one named "standard".
-
        If a Request Handler is declared with startup="lazy", then it will
        not be initialized until the first request that uses it.
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/example/files/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/example/files/conf/solrconfig.xml b/solr/example/files/conf/solrconfig.xml
index d16ddb1..71fdd47 100644
--- a/solr/example/files/conf/solrconfig.xml
+++ b/solr/example/files/conf/solrconfig.xml
@@ -585,22 +585,8 @@
 
        This section contains instructions for how the SolrDispatchFilter
        should behave when processing requests for this SolrCore.
-
-       handleSelect is a legacy option that affects the behavior of requests
-       such as /select?qt=XXX
-
-       handleSelect="true" will cause the SolrDispatchFilter to process
-       the request and dispatch the query to a handler specified by the 
-       "qt" param, assuming "/select" isn't already registered.
-
-       handleSelect="false" will cause the SolrDispatchFilter to
-       ignore "/select" requests, resulting in a 404 unless a handler
-       is explicitly registered with the name "/select"
-
-       handleSelect="true" is not recommended for new users, but is the default
-       for backwards compatibility
     -->
-  <requestDispatcher handleSelect="false" >
+  <requestDispatcher>
     <!-- Request Parsing
 
          These settings indicate how Solr Requests may be parsed, and
@@ -697,14 +683,6 @@
        Incoming queries will be dispatched to a specific handler by name
        based on the path specified in the request.
 
-       Legacy behavior: If the request path uses "/select" but no Request
-       Handler has that name, and if handleSelect="true" has been specified in
-       the requestDispatcher, then the Request Handler is dispatched based on
-       the qt parameter.  Handlers without a leading '/' are accessed this way
-       like so: http://host/app/[core/]select?qt=name  If no qt is
-       given, then the requestHandler that declares default="true" will be
-       used or the one named "standard".
-
        If a Request Handler is declared with startup="lazy", then it will
        not be initialized until the first request that uses it.
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/server/solr/configsets/_default/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/server/solr/configsets/_default/conf/solrconfig.xml b/solr/server/solr/configsets/_default/conf/solrconfig.xml
index e524dbf..f75303f 100644
--- a/solr/server/solr/configsets/_default/conf/solrconfig.xml
+++ b/solr/server/solr/configsets/_default/conf/solrconfig.xml
@@ -598,21 +598,8 @@
        This section contains instructions for how the SolrDispatchFilter
        should behave when processing requests for this SolrCore.
 
-       handleSelect is a legacy option that affects the behavior of requests
-       such as /select?qt=XXX
-
-       handleSelect="true" will cause the SolrDispatchFilter to process
-       the request and dispatch the query to a handler specified by the 
-       "qt" param, assuming "/select" isn't already registered.
-
-       handleSelect="false" will cause the SolrDispatchFilter to
-       ignore "/select" requests, resulting in a 404 unless a handler
-       is explicitly registered with the name "/select"
-
-       handleSelect="true" is not recommended for new users, but is the default
-       for backwards compatibility
     -->
-  <requestDispatcher handleSelect="false" >
+  <requestDispatcher>
     <!-- Request Parsing
 
          These settings indicate how Solr Requests may be parsed, and
@@ -709,14 +696,6 @@
        Incoming queries will be dispatched to a specific handler by name
        based on the path specified in the request.
 
-       Legacy behavior: If the request path uses "/select" but no Request
-       Handler has that name, and if handleSelect="true" has been specified in
-       the requestDispatcher, then the Request Handler is dispatched based on
-       the qt parameter.  Handlers without a leading '/' are accessed this way
-       like so: http://host/app/[core/]select?qt=name  If no qt is
-       given, then the requestHandler that declares default="true" will be
-       used or the one named "standard".
-
        If a Request Handler is declared with startup="lazy", then it will
        not be initialized until the first request that uses it.
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml b/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml
index 73899a6..6d0ce68 100644
--- a/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml
+++ b/solr/server/solr/configsets/sample_techproducts_configs/conf/solrconfig.xml
@@ -631,21 +631,8 @@
        This section contains instructions for how the SolrDispatchFilter
        should behave when processing requests for this SolrCore.
 
-       handleSelect is a legacy option that affects the behavior of requests
-       such as /select?qt=XXX
-
-       handleSelect="true" will cause the SolrDispatchFilter to process
-       the request and dispatch the query to a handler specified by the 
-       "qt" param, assuming "/select" isn't already registered.
-
-       handleSelect="false" will cause the SolrDispatchFilter to
-       ignore "/select" requests, resulting in a 404 unless a handler
-       is explicitly registered with the name "/select"
-
-       handleSelect="true" is not recommended for new users, but is the default
-       for backwards compatibility
     -->
-  <requestDispatcher handleSelect="false" >
+  <requestDispatcher>
     <!-- Request Parsing
 
          These settings indicate how Solr Requests may be parsed, and
@@ -742,14 +729,6 @@
        Incoming queries will be dispatched to a specific handler by name
        based on the path specified in the request.
 
-       Legacy behavior: If the request path uses "/select" but no Request
-       Handler has that name, and if handleSelect="true" has been specified in
-       the requestDispatcher, then the Request Handler is dispatched based on
-       the qt parameter.  Handlers without a leading '/' are accessed this way
-       like so: http://host/app/[core/]select?qt=name  If no qt is
-       given, then the requestHandler that declares default="true" will be
-       used or the one named "standard".
-
        If a Request Handler is declared with startup="lazy", then it will
        not be initialized until the first request that uses it.
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solr-ref-guide/src/distributed-requests.adoc
----------------------------------------------------------------------
diff --git a/solr/solr-ref-guide/src/distributed-requests.adoc b/solr/solr-ref-guide/src/distributed-requests.adoc
index b89878f..6d2c585 100644
--- a/solr/solr-ref-guide/src/distributed-requests.adoc
+++ b/solr/solr-ref-guide/src/distributed-requests.adoc
@@ -76,11 +76,11 @@ http://localhost:8983/solr/gettingstarted/select?q=*:*&shards=shard1,localhost:7
 
 You can directly configure aspects of the concurrency and thread-pooling used within distributed search in Solr. This allows for finer grained control and you can tune it to target your own specific requirements. The default configuration favors throughput over latency.
 
-To configure the standard handler, provide a configuration like this in `solrconfig.xml`:
+To configure the standard search handler, provide a configuration like this in `solrconfig.xml`:
 
 [source,xml]
 ----
-<requestHandler name="standard" class="solr.SearchHandler" default="true">
+<requestHandler name="/select" class="solr.SearchHandler">
   <!-- other params go here -->
   <shardHandler class="HttpShardHandlerFactory">
     <int name="socketTimeOut">1000</int>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solr-ref-guide/src/the-dismax-query-parser.adoc
----------------------------------------------------------------------
diff --git a/solr/solr-ref-guide/src/the-dismax-query-parser.adoc b/solr/solr-ref-guide/src/the-dismax-query-parser.adoc
index d624d7c..378fd93 100644
--- a/solr/solr-ref-guide/src/the-dismax-query-parser.adoc
+++ b/solr/solr-ref-guide/src/the-dismax-query-parser.adoc
@@ -20,9 +20,9 @@
 
 The DisMax query parser is designed to process simple phrases (without complex syntax) entered by users and to search for individual terms across several fields using different weighting (boosts) based on the significance of each field. Additional options enable users to influence the score based on rules specific to each use case (independent of user input).
 
-In general, the DisMax query parser's interface is more like that of Google than the interface of the 'standard' Solr request handler. This similarity makes DisMax the appropriate query parser for many consumer applications. It accepts a simple syntax, and it rarely produces error messages.
+In general, the DisMax query parser's interface is more like that of Google than the interface of the 'lucene' Solr query parser. This similarity makes DisMax the appropriate query parser for many consumer applications. It accepts a simple syntax, and it rarely produces error messages.
 
-The DisMax query parser supports an extremely simplified subset of the Lucene QueryParser syntax. As in Lucene, quotes can be used to group phrases, and +/- can be used to denote mandatory and optional clauses. All other Lucene query parser special characters (except AND and OR) are escaped to simplify the user experience. The DisMax query parser takes responsibility for building a good query from the user's input using Boolean clauses containing DisMax queries across fields and boosts specified by the user. It also lets the Solr administrator provide additional boosting queries, boosting functions, and filtering queries to artificially affect the outcome of all searches. These options can all be specified as default parameters for the handler in the `solrconfig.xml` file or overridden in the Solr query URL.
+The DisMax query parser supports an extremely simplified subset of the Lucene QueryParser syntax. As in Lucene, quotes can be used to group phrases, and +/- can be used to denote mandatory and optional clauses. All other Lucene query parser special characters (except AND and OR) are escaped to simplify the user experience. The DisMax query parser takes responsibility for building a good query from the user's input using Boolean clauses containing DisMax queries across fields and boosts specified by the user. It also lets the Solr administrator provide additional boosting queries, boosting functions, and filtering queries to artificially affect the outcome of all searches. These options can all be specified as default parameters for the request handler in the `solrconfig.xml` file or overridden in the Solr query URL.
 
 Interested in the technical concept behind the DisMax name? DisMax stands for Maximum Disjunction. Here's a definition of a Maximum Disjunction or "DisMax" query:
 
@@ -190,11 +190,11 @@ All of the sample URLs in this section assume you are running Solr's "techproduc
 bin/solr -e techproducts
 ----
 
-Normal results for the word "video" using the StandardRequestHandler with the default search field:
+Results for the word "video" using the standard query parser, and we assume "df" is pointing to a field to search:
 
 `\http://localhost:8983/solr/techproducts/select?q=video&fl=name+score`
 
-The "dismax" handler is configured to search across the text, features, name, sku, id, manu, and cat fields all with varying boosts designed to ensure that "better" matches appear first, specifically: documents which match on the name and cat fields get higher scores.
+The "dismax" parser is configured to search across the text, features, name, sku, id, manu, and cat fields all with varying boosts designed to ensure that "better" matches appear first, specifically: documents which match on the name and cat fields get higher scores.
 
 `\http://localhost:8983/solr/techproducts/select?defType=dismax&q=video`
 
@@ -210,13 +210,13 @@ You can boost results that have a field that matches a specific value.
 
 `\http://localhost:8983/solr/techproducts/select?defType=dismax&q=video&bq=cat:electronics^5.0`
 
-Another instance of the handler is registered using the `qt` "instock" and has slightly different configuration options, notably: a filter for (you guessed it) `inStock:true)`.
+Another request handler is registered at "/instock" and has slightly different configuration options, notably: a filter for (you guessed it) `inStock:true)`.
 
 `\http://localhost:8983/solr/techproducts/select?defType=dismax&q=video&fl=name,score,inStock`
 
-`\http://localhost:8983/solr/techproducts/select?defType=dismax&q=video&qt=instock&fl=name,score,inStock`
+`\http://localhost:8983/solr/techproducts/instock?defType=dismax&q=video&fl=name,score,inStock`
 
-One of the other really cool features in this handler is robust support for specifying the "BooleanQuery.minimumNumberShouldMatch" you want to be used based on how many terms are in your user's query. These allows flexibility for typos and partial matches. For the dismax handler, one and two word queries require that all of the optional clauses match, but for three to five word queries one missing word is allowed.
+One of the other really cool features in this parser is robust support for specifying the "BooleanQuery.minimumNumberShouldMatch" you want to be used based on how many terms are in your user's query. These allows flexibility for typos and partial matches. For the dismax parser, one and two word queries require that all of the optional clauses match, but for three to five word queries one missing word is allowed.
 
 `\http://localhost:8983/solr/techproducts/select?defType=dismax&q=belkin+ipod`
 
@@ -224,7 +224,7 @@ One of the other really cool features in this handler is robust support for spec
 
 `\http://localhost:8983/solr/techproducts/select?defType=dismax&q=belkin+ipod+apple`
 
-Just like the StandardRequestHandler, it supports the debugQuery option to viewing the parsed query, and the score explanations for each document.
+Use the debugQuery option to see the parsed query, and the score explanations for each document.
 
 `\http://localhost:8983/solr/techproducts/select?defType=dismax&q=belkin+ipod+gibberish&debugQuery=true`
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solrj/src/java/org/apache/solr/common/params/MoreLikeThisParams.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/common/params/MoreLikeThisParams.java b/solr/solrj/src/java/org/apache/solr/common/params/MoreLikeThisParams.java
index 919f786..882a32e 100644
--- a/solr/solrj/src/java/org/apache/solr/common/params/MoreLikeThisParams.java
+++ b/solr/solrj/src/java/org/apache/solr/common/params/MoreLikeThisParams.java
@@ -19,11 +19,10 @@ package org.apache.solr.common.params;
 import java.util.Locale;
 
 /**
- * @since solr 1.3
+ * Params for {@code MoreLikeThisHandler}.
  */
 public interface MoreLikeThisParams 
 {
-  // enable more like this -- this only applies to 'StandardRequestHandler' maybe DismaxRequestHandler
   public final static String MLT = "mlt";
   
   public final static String PREFIX = "mlt.";

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig-slave1.xml
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig-slave1.xml b/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig-slave1.xml
index 9114cfd..a68ac11 100644
--- a/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig-slave1.xml
+++ b/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig-slave1.xml
@@ -29,17 +29,17 @@
   <updateHandler class="solr.DirectUpdateHandler2">
   </updateHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
+  <requestHandler name="/defaults" class="solr.SearchHandler">
 
   </requestHandler>
 
   <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
+  <requestHandler name="/lazy" class="solr.SearchHandler" startup="lazy">
   </requestHandler>
 
   <requestHandler name="/replication" class="solr.ReplicationHandler">
@@ -47,7 +47,7 @@
   </requestHandler>
 
 
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1"/>
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig-sql.xml
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig-sql.xml b/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig-sql.xml
index 6a0c5b5..af659ad 100644
--- a/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig-sql.xml
+++ b/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig-sql.xml
@@ -44,13 +44,13 @@
     </lst>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
   </requestDispatcher>
 
   <requestHandler name="/replication" class="solr.ReplicationHandler" startup="lazy" />
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
+  <requestHandler name="/select" class="solr.SearchHandler"/>
   <requestHandler name="/update" class="solr.UpdateRequestHandler"  />
 
   <requestHandler name="/admin/ping" class="solr.PingRequestHandler">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig.xml b/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig.xml
index a2db090..78bba01 100644
--- a/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig.xml
+++ b/solr/solrj/src/test-files/solrj/solr/collection1/conf/solrconfig.xml
@@ -35,11 +35,11 @@
     </updateLog>
   </updateHandler>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
   </requestDispatcher>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
   <requestHandler name="/admin/ping" class="solr.PingRequestHandler">
     <lst name="invariants">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solrj/src/test-files/solrj/solr/configsets/ml/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test-files/solrj/solr/configsets/ml/conf/solrconfig.xml b/solr/solrj/src/test-files/solrj/solr/configsets/ml/conf/solrconfig.xml
index b404e87..b002a30 100644
--- a/solr/solrj/src/test-files/solrj/solr/configsets/ml/conf/solrconfig.xml
+++ b/solr/solrj/src/test-files/solrj/solr/configsets/ml/conf/solrconfig.xml
@@ -36,11 +36,11 @@
   </updateHandler>
 
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
   </requestDispatcher>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
   <!-- config for the admin interface -->
   <admin>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solrj/src/test-files/solrj/solr/configsets/shared/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test-files/solrj/solr/configsets/shared/conf/solrconfig.xml b/solr/solrj/src/test-files/solrj/solr/configsets/shared/conf/solrconfig.xml
index 6beb0b7..fbfa82b 100644
--- a/solr/solrj/src/test-files/solrj/solr/configsets/shared/conf/solrconfig.xml
+++ b/solr/solrj/src/test-files/solrj/solr/configsets/shared/conf/solrconfig.xml
@@ -35,18 +35,18 @@
     </updateLog>
   </updateHandler>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
   </requestDispatcher>
-  
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
+
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
   <!-- config for the admin interface --> 
   <admin>
     <defaultQuery>solr</defaultQuery>
   </admin>
 
-  <initParams path="standard">
+  <initParams path="/select">
     <lst name="defaults">
       <str name="df">name</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solrj/src/test-files/solrj/solr/configsets/streaming/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test-files/solrj/solr/configsets/streaming/conf/solrconfig.xml b/solr/solrj/src/test-files/solrj/solr/configsets/streaming/conf/solrconfig.xml
index c7985d2..70e9403 100644
--- a/solr/solrj/src/test-files/solrj/solr/configsets/streaming/conf/solrconfig.xml
+++ b/solr/solrj/src/test-files/solrj/solr/configsets/streaming/conf/solrconfig.xml
@@ -36,18 +36,18 @@
   </updateHandler>
 
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
   </requestDispatcher>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true"/>
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
   <!-- config for the admin interface -->
   <admin>
     <defaultQuery>solr</defaultQuery>
   </admin>
 
-  <initParams path="standard">
+  <initParams path="/select">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solrj/src/test-files/solrj/solr/multicore/core0/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test-files/solrj/solr/multicore/core0/conf/solrconfig.xml b/solr/solrj/src/test-files/solrj/solr/multicore/core0/conf/solrconfig.xml
index 58a7892..633f9d6 100644
--- a/solr/solrj/src/test-files/solrj/solr/multicore/core0/conf/solrconfig.xml
+++ b/solr/solrj/src/test-files/solrj/solr/multicore/core0/conf/solrconfig.xml
@@ -57,18 +57,18 @@
     </updateLog>
   </updateHandler>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" formdataUploadLimitInKB="-1" />
   </requestDispatcher>
-  
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
+
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
   <!-- config for the admin interface --> 
   <admin>
     <defaultQuery>solr</defaultQuery>
   </admin>
 
-  <initParams path="standard">
+  <initParams path="/select">
     <lst name="defaults">
       <str name="df">name</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solrj/src/test-files/solrj/solr/multicore/core1/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test-files/solrj/solr/multicore/core1/conf/solrconfig.xml b/solr/solrj/src/test-files/solrj/solr/multicore/core1/conf/solrconfig.xml
index 81ee32a..097b705 100644
--- a/solr/solrj/src/test-files/solrj/solr/multicore/core1/conf/solrconfig.xml
+++ b/solr/solrj/src/test-files/solrj/solr/multicore/core1/conf/solrconfig.xml
@@ -57,18 +57,18 @@
     </updateLog>
   </updateHandler>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" formdataUploadLimitInKB="-1" />
   </requestDispatcher>
-  
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
+
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
   <!-- config for the admin interface --> 
   <admin>
     <defaultQuery>solr</defaultQuery>
   </admin>
 
-  <initParams path="standard">
+  <initParams path="/select">
     <lst name="defaults">
       <str name="df">name</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
index c91cb67..49cec5d 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
@@ -456,7 +456,7 @@ public class CloudSolrClientTest extends SolrCloudTestCase {
 
   private Long getNumRequests(String baseUrl, String collectionName) throws
       SolrServerException, IOException {
-    return getNumRequests(baseUrl, collectionName, "QUERY", "standard", null, false);
+    return getNumRequests(baseUrl, collectionName, "QUERY", "/select", null, false);
   }
 
   private Long getNumRequests(String baseUrl, String collectionName, String category, String key, String scope, boolean returnNumErrors) throws

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
index c8ec6c0..f9a93f7 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -489,7 +489,7 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
       xmlStr = "<solr></solr>";
     Files.write(solrHome.resolve(SolrXmlConfig.SOLR_XML_FILE), xmlStr.getBytes(StandardCharsets.UTF_8));
     h = new TestHarness(SolrXmlConfig.fromSolrHome(solrHome));
-    lrf = h.getRequestFactory("standard", 0, 20, CommonParams.VERSION, "2.2");
+    lrf = h.getRequestFactory("/select", 0, 20, CommonParams.VERSION, "2.2");
   }
   
   /** 
@@ -687,20 +687,20 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
             solrConfig,
             getSchemaFile());
     lrf = h.getRequestFactory
-            ("standard",0,20,CommonParams.VERSION,"2.2");
+            ("",0,20,CommonParams.VERSION,"2.2");
   }
 
   public static CoreContainer createCoreContainer(Path solrHome, String solrXML) {
     testSolrHome = requireNonNull(solrHome);
     h = new TestHarness(solrHome, solrXML);
-    lrf = h.getRequestFactory("standard", 0, 20, CommonParams.VERSION, "2.2");
+    lrf = h.getRequestFactory("", 0, 20, CommonParams.VERSION, "2.2");
     return h.getCoreContainer();
   }
 
   public static CoreContainer createCoreContainer(NodeConfig config, CoresLocator locator) {
     testSolrHome = config.getSolrResourceLoader().getInstancePath();
     h = new TestHarness(config, locator);
-    lrf = h.getRequestFactory("standard", 0, 20, CommonParams.VERSION, "2.2");
+    lrf = h.getRequestFactory("", 0, 20, CommonParams.VERSION, "2.2");
     return h.getCoreContainer();
   }
 
@@ -715,7 +715,7 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
   public static CoreContainer createDefaultCoreContainer(Path solrHome) {
     testSolrHome = requireNonNull(solrHome);
     h = new TestHarness("collection1", initCoreDataDir.getAbsolutePath(), "solrconfig.xml", "schema.xml");
-    lrf = h.getRequestFactory("standard", 0, 20, CommonParams.VERSION, "2.2");
+    lrf = h.getRequestFactory("", 0, 20, CommonParams.VERSION, "2.2");
     return h.getCoreContainer();
   }
 


[51/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-6671: Fix tests on Windows

Posted by ab...@apache.org.
SOLR-6671: Fix tests on Windows


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/8000b25c
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/8000b25c
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/8000b25c

Branch: refs/heads/jira/solr-10879
Commit: 8000b25cabef69bc31e64dee2c3ef619b77f84f7
Parents: 5b48480
Author: Jan Høydahl <ja...@apache.org>
Authored: Sun Jul 2 01:36:09 2017 +0200
Committer: Jan Høydahl <ja...@apache.org>
Committed: Sun Jul 2 01:36:09 2017 +0200

----------------------------------------------------------------------
 .../apache/solr/core/DirectoryFactoryTest.java  | 21 +++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/8000b25c/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java b/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
index 35198b7..35bb09b 100755
--- a/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
+++ b/solr/core/src/test/org/apache/solr/core/DirectoryFactoryTest.java
@@ -20,16 +20,19 @@ import java.io.IOException;
 import java.nio.file.Paths;
 import java.util.Properties;
 
+import org.apache.commons.exec.OS;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.handler.admin.CoreAdminHandler;
 import org.apache.solr.handler.component.HttpShardHandlerFactory;
+import org.apache.solr.util.MockCoreContainer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
 public class DirectoryFactoryTest extends LuceneTestCase {
 
+  private static boolean IS_WINDOWS = (OS.isFamilyDOS() || OS.isFamilyWin9x() || OS.isFamilyWindows());
   public void testLockTypesUnchanged() throws Exception {
     assertEquals("simple", DirectoryFactory.LOCK_TYPE_SIMPLE);
     assertEquals("native", DirectoryFactory.LOCK_TYPE_NATIVE);
@@ -55,20 +58,28 @@ public class DirectoryFactoryTest extends LuceneTestCase {
     rdf.init(new NamedList());
 
     // No solr.data.home property set. Absolute instanceDir
-    assertEquals("/tmp/inst1/data", rdf.getDataHome(new CoreDescriptor("core_name", Paths.get("/tmp/inst1"), cp, zkAware)));
+    assertDataHome("/tmp/inst1/data", "/tmp/inst1", rdf, cc);
 
     // Simulate solr.data.home set in solrconfig.xml <directoryFactory> tag
     NamedList args = new NamedList();
     args.add("solr.data.home", "/solrdata/");
     rdf.init(args);
-    assertEquals("/solrdata/inst_dir/data", rdf.getDataHome(new CoreDescriptor("core_name", Paths.get("inst_dir"), cp, zkAware)));
-
+    assertDataHome("/solrdata/inst_dir/data", "inst_dir", rdf, cc);
+    
     // solr.data.home set with System property, and relative path
     System.setProperty("solr.data.home", "solrdata");
     rdf.init(new NamedList());
-    assertEquals("/solr/home/solrdata/inst_dir/data", rdf.getDataHome(new CoreDescriptor("core_name", Paths.get("inst_dir"), cp, zkAware)));
+    assertDataHome("/solr/home/solrdata/inst_dir/data", "inst_dir", rdf, cc);
     // Test parsing last component of instanceDir, and using custom dataDir
-    assertEquals("/solr/home/solrdata/myinst/mydata", rdf.getDataHome(new CoreDescriptor("core_name", Paths.get("/path/to/myinst"), cp, zkAware, "dataDir", "mydata")));
+    assertDataHome("/solr/home/solrdata/myinst/mydata", "/path/to/myinst", rdf, cc, "dataDir", "mydata");
+  }
+
+  private void assertDataHome(String expected, String instanceDir, RAMDirectoryFactory rdf, MockCoreContainer cc, String... properties) throws IOException {
+    String dataHome = rdf.getDataHome(new CoreDescriptor("core_name", Paths.get(instanceDir), cc.containerProperties, cc.isZooKeeperAware(), properties));
+    if (IS_WINDOWS) {
+      dataHome = dataHome.replaceFirst("^C:", "").replaceAll("\\\\","/");
+    }
+    assertEquals(expected, dataHome);
   }
 
 


[16/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongField.java
new file mode 100644
index 0000000..ac4da2e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongField.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.value.LongValue.CastingLongValue;
+import org.apache.solr.schema.LongPointField;
+import org.apache.solr.schema.TrieLongField;
+
+/**
+ * An analytics wrapper for a single-valued {@link TrieLongField} or {@link LongPointField} with DocValues enabled.
+ */
+public class LongField extends AnalyticsField implements CastingLongValue {
+  private NumericDocValues docValues;
+  private long value;
+  private boolean exists;
+
+  public LongField(String fieldName) {
+    super(fieldName);
+  }
+
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getNumeric(context.reader(), fieldName);
+  }
+
+  @Override
+  public void collect(int doc) throws IOException {
+    exists = docValues.advanceExact(doc);
+    if (exists) {
+      value = docValues.longValue();
+    }
+  }
+
+  @Override
+  public long getLong() {
+    return value;
+  }
+  @Override
+  public double getDouble() {
+    return (double)value;
+  }
+  @Override
+  public String getString() {
+    return exists ? Long.toString(value) : null;
+  }
+  @Override
+  public Object getObject() {
+    return exists ? value : null;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    if (exists) {
+      cons.accept((double)value);
+    }
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    if (exists) {
+      cons.accept(Long.toString(value));
+    }
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+
+  @Override
+  public ExpressionComparator<Long> getObjectComparator(String expression) {
+    return new ExpressionComparator<>(expression);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiField.java
new file mode 100644
index 0000000..dc2a953
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiField.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.solr.analytics.value.LongValueStream.CastingLongValueStream;
+import org.apache.solr.legacy.LegacyNumericUtils;
+import org.apache.solr.schema.TrieLongField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link TrieLongField} with DocValues enabled.
+ */
+public class LongMultiField extends AnalyticsField implements CastingLongValueStream {
+  private SortedSetDocValues docValues;
+  private int count;
+  private long[] values;
+
+  public LongMultiField(String fieldName) {
+    super(fieldName);
+    count = 0;
+    values = new long[initialArrayLength];
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSortedSet(context.reader(), fieldName);
+  }
+  @Override
+  public void collect(int doc) throws IOException {
+    count = 0;
+    if (docValues.advanceExact(doc)) {
+      int term;
+      while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+        if (count == values.length) {
+          resizeValues();
+        }
+        values[count++] = LegacyNumericUtils.prefixCodedToLong(docValues.lookupOrd(term));
+      }
+    }
+  }
+  
+  private void resizeValues() {
+    long[] newValues = new long[values.length*2];
+    for (int i = 0; i < count; ++i) {
+      newValues[i] = values[i];
+    }
+    values = newValues;
+  }
+  
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    for (int i = 0; i < count; ++i) {
+      cons.accept(values[i]);
+    }
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    streamLongs(value -> cons.accept((double)value));
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamLongs(value -> cons.accept(Long.toString(value)));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamLongs(value -> cons.accept(value));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiPointField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiPointField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiPointField.java
new file mode 100644
index 0000000..31d14ae
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiPointField.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedNumericDocValues;
+import org.apache.solr.analytics.value.LongValueStream.CastingLongValueStream;
+import org.apache.solr.schema.LongPointField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link LongPointField} with DocValues enabled.
+ */
+public class LongMultiPointField extends AnalyticsField implements CastingLongValueStream {
+  private SortedNumericDocValues docValues;
+  private int count;
+  private long[] values;
+
+  public LongMultiPointField(String fieldName) {
+    super(fieldName);
+    count = 0;
+    values = new long[initialArrayLength];
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSortedNumeric(context.reader(), fieldName);
+  }
+  
+  @Override
+  public void collect(int doc) throws IOException {
+    if (docValues.advanceExact(doc)) {
+      count = docValues.docValueCount();
+      resizeEmptyValues(count);
+      for (int i = 0; i < count; ++i) {
+        values[i] = docValues.nextValue();
+      }
+    } else {
+      count = 0;
+    }
+  }
+  
+  private void resizeEmptyValues(int count) {
+    if (count > values.length) {
+      values = new long[count];
+    }
+  }
+  
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    for (int i = 0; i < count; ++i) {
+      cons.accept(values[i]);
+    }
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    streamLongs(value -> cons.accept((double)value));
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamLongs(value -> cons.accept(Long.toString(value)));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamLongs(value -> cons.accept(value));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringField.java
new file mode 100644
index 0000000..207a95a
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringField.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+
+import org.apache.lucene.index.BinaryDocValues;
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.value.StringValue.CastingStringValue;
+import org.apache.solr.schema.StrField;
+
+/**
+ * An analytics wrapper for a single-valued {@link StrField} with DocValues enabled.
+ */
+public class StringField extends AnalyticsField implements CastingStringValue {
+  private BinaryDocValues docValues;
+  String value;
+  boolean exists;
+
+  public StringField(String fieldName) {
+    super(fieldName);
+    exists = false;
+  }
+
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getBinary(context.reader(), fieldName);
+  }
+
+  @Override
+  public void collect(int doc) throws IOException {
+    exists = docValues.advanceExact(doc);
+    if (exists) {
+      value = docValues.binaryValue().utf8ToString();
+    }
+  }
+
+  @Override
+  public String getString() {
+    return exists ? value : null;
+  }
+  @Override
+  public Object getObject() {
+    return exists ? value : null;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+
+  @Override
+  public ExpressionComparator<String> getObjectComparator(String expression) {
+    return new ExpressionComparator<>(expression);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringMultiField.java
new file mode 100644
index 0000000..39c60f0
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringMultiField.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.solr.analytics.value.StringValueStream.CastingStringValueStream;
+import org.apache.solr.schema.StrField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link StrField} with DocValues enabled.
+ */
+public class StringMultiField extends AnalyticsField implements CastingStringValueStream {
+  private SortedSetDocValues docValues;
+  private ArrayList<String> values;
+
+  public StringMultiField(String fieldName) {
+    super(fieldName);
+    values = new ArrayList<>(initialArrayLength);
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSortedSet(context.reader(), fieldName);
+  }
+  @Override
+  public void collect(int doc) throws IOException {
+    values.clear();
+    if (docValues.advanceExact(doc)) {
+      int term;
+      while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+        values.add(docValues.lookupOrd(term).utf8ToString());
+      }
+    }
+  }
+  
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    values.forEach(value -> cons.accept(value));
+  }
+
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    values.forEach(value -> cons.accept(value));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/package-info.java
new file mode 100644
index 0000000..a0e5421
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Fields to use for analytics expressions.
+ */
+package org.apache.solr.analytics.function.field;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AbsoluteValueFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AbsoluteValueFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AbsoluteValueFunction.java
new file mode 100644
index 0000000..d52810f
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AbsoluteValueFunction.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * An absolute value mapping function.
+ * <p>
+ * Takes a numeric ValueStream or Value and returns a ValueStream or Value of the same numeric type.
+ */
+public class AbsoluteValueFunction {
+  public static final String name = "abs";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramaters, " + params.length + " found.");
+    }
+    AnalyticsValueStream param = params[0];
+    if (param instanceof IntValueStream) {
+      return LambdaFunction.createIntLambdaFunction(name, x -> (x<0)? x*-1:x, (IntValueStream)param);
+    }
+    if (param instanceof LongValueStream) {
+      return LambdaFunction.createLongLambdaFunction(name, x -> (x<0)? x*-1:x, (LongValueStream)param);
+    }
+    if (param instanceof FloatValueStream) {
+      return LambdaFunction.createFloatLambdaFunction(name, x -> (x<0)? x*-1:x, (FloatValueStream)param);
+    }
+    if (param instanceof DoubleValueStream) {
+      return LambdaFunction.createDoubleLambdaFunction(name, x -> (x<0)? x*-1:x, (DoubleValueStream)param);
+      }
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a numeric parameter, "+param.getExpressionStr()+" found.");
+  });
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AddFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AddFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AddFunction.java
new file mode 100644
index 0000000..d66f84e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AddFunction.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+
+/**
+ * An addition mapping function.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If a single numeric ValueStream is passed in, a {@link DoubleValue} representing the sum of the values for each document is returned.
+ * <li>If a numeric ValueStream and a numeric Value are passed in, a {@link DoubleValueStream} representing the sum of 
+ * the Value and each of the values of the ValueStream for a document is returned.
+ * (Or the other way, since the Value and ValueStream can be used in either order)
+ * <li>If multiple numeric Values are passed in, a {@link DoubleValue} representing the sum of all values is returned.
+ * </ul>
+ */
+public class AddFunction {
+  public static final String name = "add";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires parameters.");
+    } 
+    else if (params.length == 1) {
+      if (params[0] instanceof DoubleValueStream) {
+        return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a+b, (DoubleValueStream)params[0]);
+      }
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters. Incorrect param: "+params[0].getExpressionStr());
+    } 
+    else if (params.length == 2) {
+      AnalyticsValueStream param1 = params[0];
+      AnalyticsValueStream param2 = params[1];
+      if (param1 instanceof DoubleValueStream && param2 instanceof DoubleValueStream) {
+        return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a+b, (DoubleValueStream)param1, (DoubleValueStream)param2);
+      }
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters.");
+    }
+    DoubleValue[] castedParams = new DoubleValue[params.length];
+    for (int i = 0; i < params.length; i++) {
+      if (params[i] instanceof DoubleValue) {
+        castedParams[i] = (DoubleValue) params[i];
+      } else {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that all parameters be single-valued if more than 2 are given.");
+      }
+    }
+    return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a+b, castedParams);
+  });
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/BottomFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/BottomFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/BottomFunction.java
new file mode 100644
index 0000000..f896da4
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/BottomFunction.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A bottom mapping function, returning the lowest value found.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If a single comparable ValueStream is passed in, a Value (of the same type) representing the minimum of the values for each document is returned.
+ * <li>If multiple comparable Values are passed in, a Value (of the same type) representing the minimum of all values is returned.
+ * </ul>
+ */
+public class BottomFunction {
+  public static final String name = "bottom";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires paramaters.");
+    }
+    AnalyticsValueStream param = params[0];
+    if (param instanceof DateValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createDateLambdaFunction(name, (a,b) -> (a<b)? a:b, (DateValueStream)param);
+      }
+      DateValue[] castedParams = new DateValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof DateValue) {
+          castedParams[i] = (DateValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createDateLambdaFunction(name, (a,b) -> (a<b)? a:b, castedParams, false);
+      }
+    }
+    if (param instanceof IntValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createIntLambdaFunction(name, (a,b) -> (a<b)? a:b, (IntValueStream)param);
+      }
+      IntValue[] castedParams = new IntValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof IntValue) {
+          castedParams[i] = (IntValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createIntLambdaFunction(name, (a,b) -> (a<b)? a:b, castedParams, false);
+      }
+    }
+    if (param instanceof LongValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createLongLambdaFunction(name, (a,b) -> (a<b)? a:b, (LongValueStream)param);
+      }
+      LongValue[] castedParams = new LongValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof LongValue) {
+          castedParams[i] = (LongValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createLongLambdaFunction(name, (a,b) -> (a<b)? a:b, castedParams, false);
+      }
+    }
+    if (param instanceof FloatValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createFloatLambdaFunction(name, (a,b) -> (a<b)? a:b, (FloatValueStream)param);
+      }
+      FloatValue[] castedParams = new FloatValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof FloatValue) {
+          castedParams[i] = (FloatValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createFloatLambdaFunction(name, (a,b) -> (a<b)? a:b, castedParams, false);
+      }
+    }
+    if (param instanceof DoubleValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> (a<b)? a:b, (DoubleValueStream)param);
+      }
+      DoubleValue[] castedParams = new DoubleValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof DoubleValue) {
+          castedParams[i] = (DoubleValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> (a<b)? a:b, castedParams, false);
+      }
+    }
+    if (param instanceof StringValueStream) {
+      if (params.length == 1) {
+        return LambdaFunction.createStringLambdaFunction(name, (a,b) -> (a.compareTo(b)<=0)? a:b, (StringValueStream)param);
+      }
+      StringValue[] castedParams = new StringValue[params.length];
+      boolean tryNextType = false;
+      for (int i = 0; i < params.length; i++) {
+        if (params[i] instanceof StringValue) {
+          castedParams[i] = (StringValue) params[i];
+        } else {
+          tryNextType = true;
+          break;
+        }
+      }
+      if (!tryNextType) {
+        return LambdaFunction.createStringLambdaFunction(name, (a,b) -> (a.compareTo(b)<=0)? a:b, castedParams, false);
+      }
+    }
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter. " + 
+          "Incorrect parameter: "+params[0].getExpressionStr());
+  });
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/CompareFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/CompareFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/CompareFunction.java
new file mode 100644
index 0000000..a06f7b8
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/CompareFunction.java
@@ -0,0 +1,614 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.value.AnalyticsValue;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.BooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.BooleanValue.AbstractBooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream.AbstractBooleanValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * Contains all comparable functions. Comparable functions accept two parameters and return a BooleanValueStream.
+ * The two parameters must be able to be cast to the same type.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If a two comparable {@link AnalyticsValue}s are passed in, a {@link BooleanValue} representing the comparison of the two values for each document is returned.
+ * <li>If a comparable {@link AnalyticsValue} and a comparable {@link AnalyticsValueStream} are passed in, 
+ * a {@link BooleanValueStream} representing the comparison of the Value and each of the values of the ValueStream for the document is returned.
+ * </ul>
+ */
+public class CompareFunction {
+  
+  private static BooleanValueStream createCompareFunction(String name, CompResultFunction comp, AnalyticsValueStream... params) {
+    if (params.length != 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramaters, " + params.length + " found.");
+    }
+    AnalyticsValueStream paramA = params[0];
+    AnalyticsValueStream paramB = params[1];
+    if (paramA instanceof DateValueStream && paramB instanceof DateValueStream) {
+      if (paramA instanceof DateValue) {
+        if (paramB instanceof DateValue) {
+          return new CompareDateValueFunction(name,(DateValue)paramA,(DateValue)paramB,comp);
+        }
+        return new CompareDateStreamFunction(name,(DateValue)paramA,(DateValueStream)paramB,comp);
+      }
+      if (paramB instanceof DateValue) {
+        return new CompareDateStreamFunction(name,(DateValue)paramB,(DateValueStream)paramA,reverse(comp));
+      }
+    } else if (paramA instanceof DoubleValueStream && paramB instanceof DoubleValueStream) {
+      if (paramA instanceof DoubleValue) {
+        if (paramB instanceof DoubleValue) {
+          return new CompareDoubleValueFunction(name,(DoubleValue)paramA,(DoubleValue)paramB,comp);
+        }
+        return new CompareDoubleStreamFunction(name,(DoubleValue)paramA,(DoubleValueStream)paramB,comp);
+      }
+      if (paramB instanceof DoubleValue) {
+        return new CompareDoubleStreamFunction(name,(DoubleValue)paramB,(DoubleValueStream)paramA,reverse(comp));
+      }
+    } else if (paramA instanceof StringValueStream && paramB instanceof StringValueStream) {
+      if (paramA instanceof StringValue) {
+        if (paramB instanceof StringValue) {
+          return new CompareStringValueFunction(name,(StringValue)paramA,(StringValue)paramB,comp);
+        }
+        return new CompareStringStreamFunction(name,(StringValue)paramA,(StringValueStream)paramB,comp);
+      }
+      if (paramB instanceof StringValue) {
+        return new CompareStringStreamFunction(name,(StringValue)paramB,(StringValueStream)paramA,reverse(comp));
+      }
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires comparable parameters.");
+    }
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that at least 1 parameter be single-valued.");
+  }
+  
+  /**
+   * A comparison function that tests equality.
+   */
+  public static class EqualFunction {
+    public static final String name = "equal";
+    public static final CreatorFunction creatorFunction = (params -> {
+      try {
+        return CompareFunction.createCompareFunction(name, val -> {
+          return val == 0;
+        }, params);
+      } catch (SolrException e) {
+        if (params.length != 2) {
+          throw e;
+        }
+        
+        AnalyticsValueStream paramA = params[0];
+        AnalyticsValueStream paramB = params[1];
+        
+        // Booleans aren't really comparable, so just enable the equal function
+        if (paramA instanceof BooleanValueStream && paramB instanceof BooleanValueStream) {
+          if (paramA instanceof BooleanValue) {
+            if (paramB instanceof BooleanValue) {
+              return new BooleanValueEqualFunction((BooleanValue)paramA,(BooleanValue)paramB);
+            }
+            return new BooleanStreamEqualFunction((BooleanValue)paramA,(BooleanValueStream)paramB);
+          } else if (paramB instanceof BooleanValue) {
+            return new BooleanStreamEqualFunction((BooleanValue)paramB,(BooleanValueStream)paramA);
+          }
+        }
+        
+        // This means that the Objects created by the AnalyticsValueStreams are not comparable, so use the .equals() method instead
+        else if (paramA instanceof AnalyticsValue) {
+          if (paramB instanceof AnalyticsValue) {
+            return new ValueEqualFunction((AnalyticsValue)paramA,(AnalyticsValue)paramB);
+          }
+          return new StreamEqualFunction((AnalyticsValue)paramA,paramB);
+        }
+        if (paramB instanceof AnalyticsValue) {
+          return new StreamEqualFunction((AnalyticsValue)paramB,paramA);
+        }
+      }
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that at least 1 parameter be single-valued.");
+    });
+  }
+  
+  /**
+   * A comparison function that tests whether the first parameter is greater than the second parameter
+   */
+  public static class GTFunction {
+    public static final String name = "gt";
+    public static final CreatorFunction creatorFunction = (params -> {
+      return CompareFunction.createCompareFunction(name, val -> {
+        return val > 0;
+      }, params);
+    });
+  }
+
+  /**
+   * A comparison function that tests whether the first parameter is greater than or equal to the second parameter
+   */
+  public static class GTEFunction {
+    public static final String name = "gte";
+    public static final CreatorFunction creatorFunction = (params -> {
+      return CompareFunction.createCompareFunction(name, val -> {
+        return val >= 0;
+      }, params);
+    });
+  }
+
+  /**
+   * A comparison function that tests whether the first parameter is less than the second parameter
+   */
+  public static class LTFunction {
+    public static final String name = "lt";
+    public static final CreatorFunction creatorFunction = (params -> {
+      return CompareFunction.createCompareFunction(name, val -> {
+        return val < 0;
+      }, params);
+    });
+  }
+
+  /**
+   * A comparison function that tests whether the first parameter is less than or equal to the second parameter
+   */
+  public static class LTEFunction {
+    public static final String name = "lte";
+    public static final CreatorFunction creatorFunction = (params -> {
+      return CompareFunction.createCompareFunction(name, val -> {
+        return val <= 0;
+      }, params);
+    });
+  }
+  
+  private static CompResultFunction reverse(CompResultFunction original) {
+    return val -> original.apply(val*-1);
+  }
+}
+@FunctionalInterface
+interface CompResultFunction {
+  public boolean apply(int compResult);
+}
+/**
+ * A comparison function for two {@link DoubleValue}s.
+ */
+class CompareDoubleValueFunction extends AbstractBooleanValue {
+  private final DoubleValue exprA;
+  private final DoubleValue exprB;
+  private final CompResultFunction comp;
+  private final String name;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public CompareDoubleValueFunction(String name, DoubleValue exprA, DoubleValue exprB, CompResultFunction comp) {
+    this.name = name;
+    this.exprA = exprA;
+    this.exprB = exprB;
+    this.comp = comp;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,exprA,exprB);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,exprA,exprB);
+  }
+
+  private boolean exists = false;
+  @Override
+  public boolean getBoolean() {
+    double valueA = exprA.getDouble();
+    double valueB = exprB.getDouble();
+    exists = exprA.exists() && exprB.exists();
+    return exists ? comp.apply(Double.compare(valueA,valueB)) : false;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * A comparison function for a {@link DoubleValue} and a {@link DoubleValueStream}.
+ */
+class CompareDoubleStreamFunction extends AbstractBooleanValueStream {
+  private final DoubleValue baseExpr;
+  private final DoubleValueStream compExpr;
+  private final CompResultFunction comp;
+  private final String name;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public CompareDoubleStreamFunction(String name, DoubleValue baseExpr, DoubleValueStream compExpr, CompResultFunction comp) throws SolrException {
+    this.name = name;
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.comp = comp;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,baseExpr,compExpr);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    double baseValue = baseExpr.getDouble();
+    if (baseExpr.exists()) {
+      compExpr.streamDoubles(compValue -> cons.accept(comp.apply(Double.compare(baseValue,compValue))));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * A comparison function for two {@link DateValue}s.
+ */
+class CompareDateValueFunction extends AbstractBooleanValue {
+  private final DateValue exprA;
+  private final DateValue exprB;
+  private final CompResultFunction comp;
+  private final String name;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public CompareDateValueFunction(String name, DateValue exprA, DateValue exprB, CompResultFunction comp) {
+    this.name = name;
+    this.exprA = exprA;
+    this.exprB = exprB;
+    this.comp = comp;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,exprA,exprB);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,exprA,exprB);
+  }
+
+  private boolean exists = false;
+  @Override
+  public boolean getBoolean() {
+    long valueA = exprA.getLong();
+    long valueB = exprB.getLong();
+    exists = exprA.exists() && exprB.exists();
+    return exists ? comp.apply(Long.compare(valueA,valueB)) : false;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * A comparison function for a {@link DateValue} and a {@link DateValueStream}.
+ */
+class CompareDateStreamFunction extends AbstractBooleanValueStream {
+  private final DateValue baseExpr;
+  private final DateValueStream compExpr;
+  private final CompResultFunction comp;
+  private final String name;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public CompareDateStreamFunction(String name, DateValue baseExpr, DateValueStream compExpr, CompResultFunction comp) throws SolrException {
+    this.name = name;
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.comp = comp;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,baseExpr,compExpr);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    long baseValue = baseExpr.getLong();
+    if (baseExpr.exists()) {
+      compExpr.streamLongs(compValue -> cons.accept(comp.apply(Long.compare(baseValue,compValue))));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * A comparison function for two {@link StringValue}s.
+ */
+class CompareStringValueFunction extends AbstractBooleanValue {
+  private final StringValue exprA;
+  private final StringValue exprB;
+  private final CompResultFunction comp;
+  private final String name;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public CompareStringValueFunction(String name, StringValue exprA, StringValue exprB, CompResultFunction comp) {
+    this.name = name;
+    this.exprA = exprA;
+    this.exprB = exprB;
+    this.comp = comp;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,exprA,exprB);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,exprA,exprB);
+  }
+
+  private boolean exists = false;
+  @Override
+  public boolean getBoolean() {
+    String valueA = exprA.toString();
+    String valueB = exprB.toString();
+    exists = exprA.exists() && exprB.exists();
+    return exists ? comp.apply(valueA.compareTo(valueB)) : false;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * A comparison function for a {@link StringValue} and a {@link StringValueStream}.
+ */
+class CompareStringStreamFunction extends AbstractBooleanValueStream {
+  private final StringValue baseExpr;
+  private final StringValueStream compExpr;
+  private final CompResultFunction comp;
+  private final String name;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public CompareStringStreamFunction(String name, StringValue baseExpr, StringValueStream compExpr, CompResultFunction comp) throws SolrException {
+    this.name = name;
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.comp = comp;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,baseExpr,compExpr);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    String baseValue = baseExpr.toString();
+    if (baseExpr.exists()) {
+      compExpr.streamStrings(compValue -> cons.accept(comp.apply(baseValue.compareTo(compValue))));
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * An equal function for two {@link BooleanValue}s.
+ */
+class BooleanValueEqualFunction extends AbstractBooleanValue {
+  private final BooleanValue exprA;
+  private final BooleanValue exprB;
+  public static final String name = CompareFunction.EqualFunction.name;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public BooleanValueEqualFunction(BooleanValue exprA, BooleanValue exprB) {
+    this.exprA = exprA;
+    this.exprB = exprB;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,exprA,exprB);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,exprA,exprB);
+  }
+
+  private boolean exists = false;
+  @Override
+  public boolean getBoolean() {
+    boolean valueA = exprA.getBoolean();
+    boolean valueB = exprB.getBoolean();
+    exists = exprA.exists() && exprB.exists();
+    return exists ? valueA == valueB : false;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * An equal function for a {@link BooleanValue} and a {@link BooleanValueStream}.
+ */
+class BooleanStreamEqualFunction extends AbstractBooleanValueStream {
+  private final BooleanValue baseExpr;
+  private final BooleanValueStream compExpr;
+  public static final String name = CompareFunction.EqualFunction.name;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public BooleanStreamEqualFunction(BooleanValue baseExpr, BooleanValueStream compExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,baseExpr,compExpr);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    boolean baseValue = baseExpr.getBoolean();
+    if (baseExpr.exists()) {
+      compExpr.streamBooleans(compValue -> cons.accept(baseValue == compValue));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * A catch-all equal function for two {@link AnalyticsValue}s.
+ */
+class ValueEqualFunction extends AbstractBooleanValue {
+  private final AnalyticsValue exprA;
+  private final AnalyticsValue exprB;
+  public static final String name = CompareFunction.EqualFunction.name;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public ValueEqualFunction(AnalyticsValue exprA, AnalyticsValue exprB) {
+    this.exprA = exprA;
+    this.exprB = exprB;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,exprA,exprB);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,exprA,exprB);
+  }
+
+  private boolean exists = false;
+  @Override
+  public boolean getBoolean() {
+    Object valueA = exprA.getObject();
+    Object valueB = exprB.getObject();
+    exists = exprA.exists() && exprB.exists();
+    return exists ? valueA.equals(valueB) : false;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * A catch-all equal function for an {@link AnalyticsValue} and an {@link AnalyticsValueStream}.
+ */
+class StreamEqualFunction extends AbstractBooleanValueStream {
+  private final AnalyticsValue baseExpr;
+  private final AnalyticsValueStream compExpr;
+  public static final String name = CompareFunction.EqualFunction.name;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public StreamEqualFunction(AnalyticsValue baseExpr, AnalyticsValueStream compExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,baseExpr,compExpr);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    Object baseValue = baseExpr.getObject();
+    if (baseExpr.exists()) {
+      compExpr.streamObjects(compValue -> cons.accept(baseValue.equals(compValue)));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ConcatFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ConcatFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ConcatFunction.java
new file mode 100644
index 0000000..e54e8c5
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ConcatFunction.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.constant.ConstantStringValue;
+
+/**
+ * A concatenation mapping function, combining the string values of the given parameters. (At least 1 parameter is required)
+ * <p>
+ * Multiple comparable {@link StringValue}s are passed in and a {@link StringValue} representing the concatenation of all values is returned. 
+ */
+public class ConcatFunction {
+  public static final String name = "concat";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires parameters.");
+    } 
+    else if (params.length == 1 && params[0] instanceof StringValue) {
+      return params[0];
+    } 
+    StringValue[] castedParams = new StringValue[params.length];
+    for (int i = 0; i < params.length; i++) {
+      if (params[i] instanceof StringValue) {
+        castedParams[i] = (StringValue) params[i];
+      } else {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that all parameters be single-valued and convertible to string values.");
+      }
+    }
+    return LambdaFunction.createStringLambdaFunction(name, (a,b) -> a+b, castedParams, false);
+  });
+  
+  /**
+   * A concatenation mapping function, combining the string values of the given parameters with a given separating string.
+   * <br>
+   * Multiple comparable {@link StringValue}s are passed in and a {@link StringValue} representing the separated concatenation of all values is returned.
+   * <p>
+   * The first parameter must be a constant string (e.g. ",").
+   * The remaining parameters are the {@link StringValue} expressions to concatenate. (At least 1 expression is required)
+   */
+  public static class ConcatSeparatedFunction {
+    public static final String name = "concatsep";
+    public static final CreatorFunction creatorFunction = (params -> {
+      if (params.length < 2) {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 2 parameters.");
+      } else if (!(params[0] instanceof ConstantStringValue)) {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that the first parameter to be a constant string.");
+      }
+      final String sep = ((ConstantStringValue)params[0]).getString();
+      StringValue[] castedParams = new StringValue[params.length - 1];
+      for (int i = 0; i < castedParams.length; i++) {
+        if (params[i + 1] instanceof StringValue) {
+          castedParams[i] = (StringValue) params[i + 1];
+        } else {
+          throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that all non-separator parameters be single-valued and convertible to string values.");
+        }
+      }
+      return LambdaFunction.createStringLambdaFunction(name, (a,b) -> a + sep + b, castedParams, false);
+    });
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateMathFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateMathFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateMathFunction.java
new file mode 100644
index 0000000..9901625
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateMathFunction.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import java.util.Date;
+import java.util.function.Consumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DateValueStream.AbstractDateValueStream;
+import org.apache.solr.analytics.value.constant.ConstantStringValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.util.DateMathParser;
+
+/**
+ * A mapping function that computes date math.
+ * <p>
+ * The first parameter is the {@link DateValue} or {@link DateValueStream} to compute date math on. (Required)
+ * <br>
+ * The trailing parameters must be constant date math strings (e.g. "+1DAY"). (At least 1 required)
+ */
+public class DateMathFunction {
+  public static final String name = "date_math";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length < 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 2 paramaters, " + params.length + " found.");
+    }
+    StringBuilder mathParam = new StringBuilder();
+    for (int i = 1; i < params.length; ++i) {
+      if (params[i] instanceof ConstantStringValue) {
+        mathParam.append(((ConstantStringValue) params[i]).getString());
+      } else {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires all math parameters to be a constant strings.");
+      }
+    }
+    if (params[0] instanceof DateValue) {
+      return new DateMathValueFunction((DateValue)params[0], new ConstantStringValue(mathParam.toString()));
+    } else if (params[0] instanceof DateValueStream) {
+      return new DateMathStreamFunction((DateValueStream)params[0], new ConstantStringValue(mathParam.toString()));
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a date as the first parameter.");
+    }
+  });
+}
+/**
+ * DateMath function that supports {@link DateValue}s.
+ */
+class DateMathValueFunction extends AbstractDateValue {
+  private final DateValue dateParam;
+  private final String mathParam;
+  DateMathParser parser = new DateMathParser();
+  public static final String name = DateMathFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateMathValueFunction(DateValue dateParam, ConstantStringValue mathParam) throws SolrException {
+    this.dateParam = dateParam;
+    this.mathParam = "NOW" + mathParam.getString();
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,dateParam,mathParam);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,dateParam);
+  }
+
+  private boolean exists = false;
+  
+  @Override
+  public long getLong() {
+    Date date = getDate();
+    return (date == null) ? 0 : date.getTime();
+  }
+  @Override
+  public Date getDate() {
+    Date date = dateParam.getDate();
+    if (dateParam.exists()) {
+      exists = true;
+      return DateMathParser.parseMath(date,mathParam);
+    } else {
+      exists = false;
+      return null;
+    }
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * DateMath function that supports {@link DateValueStream}s.
+ */
+class DateMathStreamFunction extends AbstractDateValueStream {
+  private final DateValueStream dateParam;
+  private final String mathParam;
+  public static final String name = DateMathFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateMathStreamFunction(DateValueStream dateParam, ConstantStringValue mathParam) throws SolrException {
+    this.dateParam = dateParam;
+    this.mathParam = "NOW" + mathParam.getString();
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,dateParam,mathParam);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,dateParam);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    streamDates(value -> cons.accept(value.getTime()));
+  }
+  @Override
+  public void streamDates(Consumer<Date> cons) {
+    dateParam.streamDates(value -> cons.accept(DateMathParser.parseMath(value, mathParam)));
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateParseFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateParseFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateParseFunction.java
new file mode 100644
index 0000000..5929b88
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateParseFunction.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DateValueStream.AbstractDateValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A mapping function that converts long or string representations of dates to actual date objects.
+ * <p>
+ * The only parameter is the {@link LongValue}, {@link LongValueStream}, {@link DateValue}, or {@link DateValueStream} to convert. (Required)
+ */
+public class DateParseFunction {
+  public static final String name = "date";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+    }
+    if (params[0] instanceof LongValue) {
+      return new LongToDateParseFunction((LongValue)params[0]);
+    }
+    else if (params[0] instanceof LongValueStream) {
+      return new LongStreamToDateParseFunction((LongValueStream)params[0]);
+    }
+    else if (params[0] instanceof StringValue) {
+      return new StringToDateParseFunction((StringValue)params[0]);
+    }
+    else if (params[0] instanceof StringValueStream) {
+      return new StringStreamToDateParseFunction((StringValueStream)params[0]);
+    }
+    else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a string or long parameter. " + 
+          "Incorrect parameter: "+params[0].getExpressionStr());
+    }
+  });
+}
+class LongToDateParseFunction extends AbstractDateValue {
+  private final LongValue param;
+  public static final String name = DateParseFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongToDateParseFunction(LongValue param) throws SolrException {
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  @Override
+  public long getLong() {
+    return param.getLong();
+  }
+  @Override
+  public boolean exists() {
+    return param.exists();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongStreamToDateParseFunction extends AbstractDateValueStream {
+  private final LongValueStream param;
+  public static final String name = DateParseFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  public static final DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS", Locale.ROOT);
+  
+  public LongStreamToDateParseFunction(LongValueStream param) throws SolrException {
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    param.streamLongs(cons);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringToDateParseFunction extends AbstractDateValue {
+  private final StringValue param;
+  public static final String name = DateParseFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  public static final DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS", Locale.ROOT);
+  
+  public StringToDateParseFunction(StringValue param) throws SolrException {
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  private boolean exists = false;
+  @Override
+  public long getLong() {
+    long value = 0;
+    try {
+      value = formatter.parse(param.toString()).getTime();
+      exists = param.exists();
+    } catch (ParseException e) {
+      exists = false;
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringStreamToDateParseFunction extends AbstractDateValueStream {
+  private final StringValueStream param;
+  public static final String name = DateParseFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  public static final DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS", Locale.ROOT);
+  
+  public StringStreamToDateParseFunction(StringValueStream param) throws SolrException {
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    param.streamStrings(value -> {
+      try {
+        cons.accept(formatter.parse(value).getTime());
+      } catch (ParseException e) {
+      }
+    });
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DivideFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DivideFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DivideFunction.java
new file mode 100644
index 0000000..e644812
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DivideFunction.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A division mapping function. No checking on divisor value is done. An error will occur if a zero divisor is used.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If two numeric Values are passed in, a {@link DoubleValue} representing the divison of the two values is returned.
+ * <li>If a numeric ValueStream and a numeric Value are passed in, a {@link DoubleValueStream} representing the division of 
+ * the Value and each of the values of the ValueStream for a document is returned. 
+ * (Or the other way, since the Value and ValueStream can be used in either order)
+ * </ul>
+ */
+public class DivideFunction {
+  public static final String name = "div";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramaters, " + params.length + " found.");
+    }
+    AnalyticsValueStream param1 = params[0];
+    AnalyticsValueStream param2 = params[1];
+    if (param1 instanceof DoubleValueStream && param2 instanceof DoubleValueStream) {
+      return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a/b, (DoubleValueStream)param1, (DoubleValueStream)param2);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters.");
+    }
+  });
+}
\ No newline at end of file


[22/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-6807: requestDispatcher/@handleSelect now defaults to false; stop using it. Deprecated StandardRequestHandler; stop using it.

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/ConvertedLegacyTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/ConvertedLegacyTest.java b/solr/core/src/test/org/apache/solr/ConvertedLegacyTest.java
index bf7925a..35bd107 100644
--- a/solr/core/src/test/org/apache/solr/ConvertedLegacyTest.java
+++ b/solr/core/src/test/org/apache/solr/ConvertedLegacyTest.java
@@ -134,7 +134,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 2, 5 , args);
+                                    "/select", 2, 5 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=1] "
@@ -143,28 +143,28 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 3, 5 , args);
+                                    "/select", 3, 5 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=0]"
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 4, 5 , args);
+                                    "/select", 4, 5 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=0]"
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 25, 5 , args);
+                                    "/select", 25, 5 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=0]"
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 0, 1 , args);
+                                    "/select", 0, 1 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=1] "
@@ -172,7 +172,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 0, 2 , args);
+                                    "/select", 0, 2 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=2] "
@@ -180,7 +180,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 1, 1 , args);
+                                    "/select", 1, 1 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=1] "
@@ -188,28 +188,28 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 3, 1 , args);
+                                    "/select", 3, 1 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=0]"
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 4, 1 , args);
+                                    "/select", 4, 1 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=0]"
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 1, 0 , args);
+                                    "/select", 1, 0 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=0]"
             );
     args = new HashMap<>();
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z]",
-                                    "standard", 0, 0 , args);
+                                    "/select", 0, 0 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=0]"
@@ -217,7 +217,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args = new HashMap<>();
     args.put("defType","lucenePlusSort");
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z];val_s1 asc",
-                                    "standard", 0, 0 , args);
+                                    "/select", 0, 0 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=0]"
@@ -225,7 +225,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args = new HashMap<>();
     args.put("defType","lucenePlusSort");
     req = new LocalSolrQueryRequest(h.getCore(), "val_s:[a TO z];val_s1 desc",
-                                    "standard", 0, 0 , args);
+                                    "/select", 0, 0 , args);
     assertQ(req
             ,"//*[@numFound='3'] "
             ,"*[count(//doc)=0]"
@@ -1109,7 +1109,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args = new HashMap<>();
     args.put("fl","fname_s,arr_f  ");
     req = new LocalSolrQueryRequest(h.getCore(), "id:44",
-                                    "standard", 0, 10, args);
+                                    "/select", 0, 10, args);
     assertQ(req
             ,"//str[.='Yonik']  "
             ,"//float[.='1.4142135']"
@@ -1117,7 +1117,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args = new HashMap<>();
     args.put("fl","fname_s,score");
     req = new LocalSolrQueryRequest(h.getCore(), "id:44",
-                                    "standard", 0, 10, args);
+                                    "/select", 0, 10, args);
     assertQ(req
             ,"//str[.='Yonik']"
             ,"//float[@name='score' and . > 0]"
@@ -1128,7 +1128,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args = new HashMap<>();
     args.put("fl","score,* ");
     req = new LocalSolrQueryRequest(h.getCore(), "id:44",
-                                    "standard", 0, 10, args);
+                                    "/select", 0, 10, args);
     assertQ(req
             ,"//str[.='Yonik']  "
             ,"//float[.='1.4142135'] "
@@ -1138,7 +1138,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args = new HashMap<>();
     args.put("fl","*,score ");
     req = new LocalSolrQueryRequest(h.getCore(), "id:44",
-                                    "standard", 0, 10, args);
+                                    "/select", 0, 10, args);
     assertQ(req
             ,"//str[.='Yonik']  "
             ,"//float[.='1.4142135'] "
@@ -1148,7 +1148,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args = new HashMap<>();
     args.put("fl","* ");
     req = new LocalSolrQueryRequest(h.getCore(), "id:44",
-                                    "standard", 0, 10, args);
+                                    "/select", 0, 10, args);
     assertQ(req
             ,"//str[.='Yonik']  "
             ,"//float[.='1.4142135'] "
@@ -1160,7 +1160,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args = new HashMap<>();
     args.put("fl","score ");
     req = new LocalSolrQueryRequest(h.getCore(), "id:44",
-                                    "standard", 0, 10, args);
+                                    "/select", 0, 10, args);
     assertQ(req
             ,"//result[@maxScore>0]"
             );
@@ -1168,7 +1168,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args.put("fl","score ");
     args.put("defType","lucenePlusSort");
     req = new LocalSolrQueryRequest(h.getCore(), "id:44;id desc;",
-                                    "standard", 0, 10, args);
+                                    "/select", 0, 10, args);
     assertQ(req
             ,"//result[@maxScore>0]"
             );
@@ -1176,7 +1176,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args.put("fl","score ");
     args.put("defType","lucenePlusSort");
     req = new LocalSolrQueryRequest(h.getCore(), "id:44;",
-                                    "standard", 0, 10, args);
+                                    "/select", 0, 10, args);
     assertQ(req
             ,"//@maxScore = //doc/float[@name='score']"
             );
@@ -1184,7 +1184,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args.put("fl","score ");
     args.put("defType","lucenePlusSort");
     req = new LocalSolrQueryRequest(h.getCore(), "id:44;id desc;",
-                                    "standard", 0, 10, args);
+                                    "/select", 0, 10, args);
     assertQ(req
             ,"//@maxScore = //doc/float[@name='score']"
             );
@@ -1192,7 +1192,7 @@ public class ConvertedLegacyTest extends SolrTestCaseJ4 {
     args.put("fl","*,score");
     args.put("defType","lucenePlusSort");
     req = new LocalSolrQueryRequest(h.getCore(), "id:44;id desc;",
-                                    "standard", 0, 0 , args);
+                                    "/select", 0, 0 , args);
     assertQ(req
             ,"//result[@maxScore>0]"
             );

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/DisMaxRequestHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/DisMaxRequestHandlerTest.java b/solr/core/src/test/org/apache/solr/DisMaxRequestHandlerTest.java
index bdeeb40..386f690 100644
--- a/solr/core/src/test/org/apache/solr/DisMaxRequestHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/DisMaxRequestHandlerTest.java
@@ -30,7 +30,7 @@ public class DisMaxRequestHandlerTest extends SolrTestCaseJ4 {
   public static void beforeClass() throws Exception {
     initCore("solrconfig.xml","schema.xml");
     lrf = h.getRequestFactory
-      ("dismax", 0, 20,
+      ("/dismax", 0, 20,
        CommonParams.VERSION,"2.2",
        "facet", "true",
        "facet.field","t_s"
@@ -69,7 +69,7 @@ public class DisMaxRequestHandlerTest extends SolrTestCaseJ4 {
 
   @Test
   public void testSomeStuff() throws Exception {
-    doTestSomeStuff("dismax");
+    doTestSomeStuff("/dismax");
   }
   public void doTestSomeStuff(final String qt) throws Exception {
 
@@ -179,7 +179,7 @@ public class DisMaxRequestHandlerTest extends SolrTestCaseJ4 {
     Pattern p = Pattern.compile("subject:hell\\s*subject:cool");
     Pattern p_bool = Pattern.compile("\\(subject:hell\\s*subject:cool\\)");
     String resp = h.query(req("q", "cool stuff"
-                ,"qt", "dismax"
+                ,"qt", "/dismax"
                 ,CommonParams.VERSION, "2.2"
                 ,"bq", "subject:hell OR subject:cool"
                 ,CommonParams.DEBUG_QUERY, "true"
@@ -188,7 +188,7 @@ public class DisMaxRequestHandlerTest extends SolrTestCaseJ4 {
     assertFalse(p_bool.matcher(resp).find());
 
     resp = h.query(req("q", "cool stuff"
-                ,"qt", "dismax"
+                ,"qt", "/dismax"
                 ,CommonParams.VERSION, "2.2"
                 ,"bq", "subject:hell OR subject:cool"
                 ,"bq",""

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/EchoParamsTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/EchoParamsTest.java b/solr/core/src/test/org/apache/solr/EchoParamsTest.java
index a89a512..44699e8 100644
--- a/solr/core/src/test/org/apache/solr/EchoParamsTest.java
+++ b/solr/core/src/test/org/apache/solr/EchoParamsTest.java
@@ -66,7 +66,7 @@ public class EchoParamsTest extends SolrTestCaseJ4 {
 
   private void allEchoParams() {
     lrf = h.getRequestFactory
-      ("crazy_custom_qt", 0, 20,
+      ("/crazy_custom_qt", 0, 20,
        CommonParams.VERSION,"2.2",
        "wt","xml",
        "echoParams", "all",
@@ -74,7 +74,7 @@ public class EchoParamsTest extends SolrTestCaseJ4 {
        );
 
     assertQ(req("foo"),HEADER_XPATH + "/lst[@name='params']/str[@name='fl'][.='implicit']");
-    assertQ(req("foo"),HEADER_XPATH + "/str[@name='handler'][.='org.apache.solr.handler.StandardRequestHandler']");
+    assertQ(req("foo"),HEADER_XPATH + "/str[@name='handler'][.='org.apache.solr.handler.component.SearchHandler']");
   }
 
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/SampleTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/SampleTest.java b/solr/core/src/test/org/apache/solr/SampleTest.java
index 244272f..407a483 100644
--- a/solr/core/src/test/org/apache/solr/SampleTest.java
+++ b/solr/core/src/test/org/apache/solr/SampleTest.java
@@ -102,7 +102,7 @@ public class SampleTest extends SolrTestCaseJ4 {
      * Note: the qt proves we are using our custom config...
      */
     TestHarness.LocalRequestFactory l = h.getRequestFactory
-      ("crazy_custom_qt",100,200,CommonParams.VERSION,"2.2");
+      ("/crazy_custom_qt",100,200,CommonParams.VERSION,"2.2");
     assertQ("how did i find Mack Daddy? ",
             l.makeRequest( "Mack Daddy" )
             ,"//result[@numFound=0]"

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/SolrInfoBeanTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/SolrInfoBeanTest.java b/solr/core/src/test/org/apache/solr/SolrInfoBeanTest.java
index d39c87f..72fdf25 100644
--- a/solr/core/src/test/org/apache/solr/SolrInfoBeanTest.java
+++ b/solr/core/src/test/org/apache/solr/SolrInfoBeanTest.java
@@ -18,9 +18,9 @@ package org.apache.solr;
 
 import org.apache.lucene.util.TestUtil;
 import org.apache.solr.core.SolrInfoBean;
-import org.apache.solr.handler.StandardRequestHandler;
 import org.apache.solr.handler.admin.LukeRequestHandler;
 import org.apache.solr.handler.component.SearchComponent;
+import org.apache.solr.handler.component.SearchHandler;
 import org.apache.solr.highlight.DefaultSolrHighlighter;
 import org.apache.solr.metrics.SolrMetricManager;
 import org.apache.solr.metrics.SolrMetricProducer;
@@ -49,7 +49,7 @@ public class SolrInfoBeanTest extends SolrTestCaseJ4
    */
   public void testCallMBeanInfo() throws Exception {
     List<Class> classes = new ArrayList<>();
-    classes.addAll(getClassesForPackage(StandardRequestHandler.class.getPackage().getName()));
+    classes.addAll(getClassesForPackage(SearchHandler.class.getPackage().getName()));
     classes.addAll(getClassesForPackage(SearchComponent.class.getPackage().getName()));
     classes.addAll(getClassesForPackage(LukeRequestHandler.class.getPackage().getName()));
     classes.addAll(getClassesForPackage(DefaultSolrHighlighter.class.getPackage().getName()));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/TestDistributedSearch.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/TestDistributedSearch.java b/solr/core/src/test/org/apache/solr/TestDistributedSearch.java
index 9a821aa..02754f0 100644
--- a/solr/core/src/test/org/apache/solr/TestDistributedSearch.java
+++ b/solr/core/src/test/org/apache/solr/TestDistributedSearch.java
@@ -386,7 +386,7 @@ public class TestDistributedSearch extends BaseDistributedSearchTestCase {
     query("q","*:*", "fl","n_*","sort",i1 + " desc");
 
     // basic spellcheck testing
-    query("q", "toyata", "fl", "id,lowerfilt", "spellcheck", true, "spellcheck.q", "toyata", "qt", "spellCheckCompRH_Direct", "shards.qt", "spellCheckCompRH_Direct");
+    query("q", "toyata", "fl", "id,lowerfilt", "spellcheck", true, "spellcheck.q", "toyata", "qt", "/spellCheckCompRH_Direct", "shards.qt", "/spellCheckCompRH_Direct");
 
     stress=0;  // turn off stress... we want to tex max combos in min time
     for (int i=0; i<25*RANDOM_MULTIPLIER; i++) {
@@ -1012,8 +1012,8 @@ public class TestDistributedSearch extends BaseDistributedSearchTestCase {
           "q", "toyata",
           "spellcheck", "true",
           "spellcheck.q", "toyata",
-          "qt", "spellCheckCompRH_Direct",
-          "shards.qt", "spellCheckCompRH_Direct",
+          "qt", "/spellCheckCompRH_Direct",
+          "shards.qt", "/spellCheckCompRH_Direct",
           ShardParams.SHARDS_INFO, "true",
           ShardParams.SHARDS_TOLERANT, "true");
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/cloud/BasicZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/BasicZkTest.java b/solr/core/src/test/org/apache/solr/cloud/BasicZkTest.java
index 7a9dbdb..79b49dc 100644
--- a/solr/core/src/test/org/apache/solr/cloud/BasicZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/BasicZkTest.java
@@ -58,7 +58,7 @@ public class BasicZkTest extends AbstractZkTestCase {
     SolrCore core = h.getCore();
 
     // test that we got the expected config, not just hardcoded defaults
-    assertNotNull(core.getRequestHandler("mock"));
+    assertNotNull(core.getRequestHandler("/mock"));
 
     lrf.args.put(CommonParams.VERSION, "2.2");
     assertQ("test query on empty index", request("qlkciyopsbgzyvkylsjhchghjrdf"),

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java b/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
index 30898b9..55cdee8 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
@@ -108,7 +108,7 @@ public class TestRandomRequestDistribution extends AbstractFullDistribZkTestBase
       SolrMetricManager metricManager = container.getMetricManager();
       for (SolrCore core : container.getCores()) {
         String registry = core.getCoreMetricManager().getRegistryName();
-        Counter cnt = metricManager.counter(null, registry, "requests", "QUERY.standard");
+        Counter cnt = metricManager.counter(null, registry, "requests", "QUERY./select");
         SolrRequestHandler select = core.getRequestHandler("");
 //        long c = (long) select.getStatistics().get("requests");
         shardVsCount.put(core.getName(), (int) cnt.getCount());
@@ -188,7 +188,7 @@ public class TestRandomRequestDistribution extends AbstractFullDistribZkTestBase
 
       SolrMetricManager leaderMetricManager = leaderCore.getCoreContainer().getMetricManager();
       String leaderRegistry = leaderCore.getCoreMetricManager().getRegistryName();
-      Counter cnt = leaderMetricManager.counter(null, leaderRegistry, "requests", "QUERY.standard");
+      Counter cnt = leaderMetricManager.counter(null, leaderRegistry, "requests", "QUERY./select");
 
       // All queries should be served by the active replica
       // To make sure that's true we keep querying the down replica

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/core/AlternateDirectoryTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/AlternateDirectoryTest.java b/solr/core/src/test/org/apache/solr/core/AlternateDirectoryTest.java
index cf8d7c6..9bf08a5 100644
--- a/solr/core/src/test/org/apache/solr/core/AlternateDirectoryTest.java
+++ b/solr/core/src/test/org/apache/solr/core/AlternateDirectoryTest.java
@@ -37,7 +37,7 @@ public class AlternateDirectoryTest extends SolrTestCaseJ4 {
   }
 
   public void testAltDirectoryUsed() throws Exception {
-    assertQ(req("q","*:*","qt","standard"));
+    assertQ(req("q","*:*","qt","/select"));
     assertTrue(TestFSDirectoryFactory.openCalled);
     assertTrue(TestIndexReaderFactory.newReaderCalled);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java b/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
index 3c13645..637aa24 100644
--- a/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
+++ b/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java
@@ -36,7 +36,7 @@ public class RequestHandlersTest extends SolrTestCaseJ4 {
   public void testInitCount() {
     String registry = h.getCore().getCoreMetricManager().getRegistryName();
     SolrMetricManager manager = h.getCoreContainer().getMetricManager();
-    Gauge<Number> g = (Gauge<Number>)manager.registry(registry).getMetrics().get("QUERY.mock.initCount");
+    Gauge<Number> g = (Gauge<Number>)manager.registry(registry).getMetrics().get("QUERY./mock.initCount");
     assertEquals("Incorrect init count",
                  1, g.getValue().intValue());
   }
@@ -52,7 +52,7 @@ public class RequestHandlersTest extends SolrTestCaseJ4 {
   @Test
   public void testLazyLoading() {
     SolrCore core = h.getCore();
-    PluginBag.PluginHolder<SolrRequestHandler> handler = core.getRequestHandlers().getRegistry().get("lazy");
+    PluginBag.PluginHolder<SolrRequestHandler> handler = core.getRequestHandlers().getRegistry().get("/lazy");
     assertFalse(handler.isLoaded());
     
     assertU(adoc("id", "42",
@@ -75,12 +75,12 @@ public class RequestHandlersTest extends SolrTestCaseJ4 {
 
         // But it should behave just like the 'defaults' request handler above
     assertQ("lazy handler returns fewer matches",
-            req("q", "id:[42 TO 47]", "qt","lazy"),
+            req("q", "id:[42 TO 47]", "qt","/lazy"),
             "*[count(//doc)=4]"
             );
 
     assertQ("lazy handler includes highlighting",
-            req("q", "name:Zapp OR title:General", "qt","lazy"),
+            req("q", "name:Zapp OR title:General", "qt","/lazy"),
             "//lst[@name='highlighting']"
             );
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java b/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java
index c042bd6..62f4d2e 100644
--- a/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java
+++ b/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java
@@ -254,7 +254,7 @@ public class SolrCoreTest extends SolrTestCaseJ4 {
     bean = infoRegistry.get(QueryComponent.COMPONENT_NAME);
     assertNotNull("bean not registered", bean);
     //try a Req Handler, which are stored by name, not clas
-    bean = infoRegistry.get("standard");
+    bean = infoRegistry.get("/select");
     assertNotNull("bean not registered", bean);
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/core/TestConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestConfig.java b/solr/core/src/test/org/apache/solr/core/TestConfig.java
index 87a453f..5a7b706 100644
--- a/solr/core/src/test/org/apache/solr/core/TestConfig.java
+++ b/solr/core/src/test/org/apache/solr/core/TestConfig.java
@@ -69,8 +69,8 @@ public class TestConfig extends SolrTestCaseJ4 {
   }
   @Test
   public void testDisableRequetsHandler() throws Exception {
-    assertNull(h.getCore().getRequestHandler("disabled"));
-    assertNotNull(h.getCore().getRequestHandler("enabled"));
+    assertNull(h.getCore().getRequestHandler("/disabled"));
+    assertNotNull(h.getCore().getRequestHandler("/enabled"));
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/core/TestQuerySenderListener.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestQuerySenderListener.java b/solr/core/src/test/org/apache/solr/core/TestQuerySenderListener.java
index c1eb873..900f024 100644
--- a/solr/core/src/test/org/apache/solr/core/TestQuerySenderListener.java
+++ b/solr/core/src/test/org/apache/solr/core/TestQuerySenderListener.java
@@ -75,7 +75,7 @@ public class TestQuerySenderListener extends SolrTestCaseJ4 {
     RefCounted<SolrIndexSearcher> currentSearcherRef = core.getSearcher();
     SolrIndexSearcher currentSearcher = currentSearcherRef.get();
     qsl.newSearcher(currentSearcher, null);//test new Searcher
-    MockQuerySenderListenerReqHandler mock = (MockQuerySenderListenerReqHandler) core.getRequestHandler("mock");
+    MockQuerySenderListenerReqHandler mock = (MockQuerySenderListenerReqHandler) core.getRequestHandler("/mock");
     assertNotNull("Mock is null", mock);
     String evt = mock.req.getParams().get(EventParams.EVENT);
     assertNotNull("Event is null", evt);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/core/TestQuerySenderNoQuery.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestQuerySenderNoQuery.java b/solr/core/src/test/org/apache/solr/core/TestQuerySenderNoQuery.java
index 425f04a..76ac7c3 100644
--- a/solr/core/src/test/org/apache/solr/core/TestQuerySenderNoQuery.java
+++ b/solr/core/src/test/org/apache/solr/core/TestQuerySenderNoQuery.java
@@ -70,7 +70,7 @@ public class TestQuerySenderNoQuery extends SolrTestCaseJ4 {
     SolrIndexSearcher currentSearcher = currentSearcherRef.get();
     SolrIndexSearcher dummy = null;
     qsl.newSearcher(currentSearcher, dummy);//test first Searcher (since param is null)
-    MockQuerySenderListenerReqHandler mock = (MockQuerySenderListenerReqHandler) core.getRequestHandler("mock");
+    MockQuerySenderListenerReqHandler mock = (MockQuerySenderListenerReqHandler) core.getRequestHandler("/mock");
     assertNotNull("Mock is null", mock);
     assertNull("Req (firstsearcher) is not null", mock.req);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/core/TestXIncludeConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestXIncludeConfig.java b/solr/core/src/test/org/apache/solr/core/TestXIncludeConfig.java
index 529fa06..32be46e 100644
--- a/solr/core/src/test/org/apache/solr/core/TestXIncludeConfig.java
+++ b/solr/core/src/test/org/apache/solr/core/TestXIncludeConfig.java
@@ -52,7 +52,7 @@ public class TestXIncludeConfig extends AbstractSolrTestCase {
     SolrCore core = h.getCore();
 
     assertNotNull("includedHandler is null", 
-                  core.getRequestHandler("includedHandler"));
+                  core.getRequestHandler("/includedHandler"));
 
     UpdateRequestProcessorChain chain 
       = core.getUpdateProcessingChain("special-include");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/handler/MoreLikeThisHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/MoreLikeThisHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/MoreLikeThisHandlerTest.java
index 6da06b1..aa63ce3 100644
--- a/solr/core/src/test/org/apache/solr/handler/MoreLikeThisHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/MoreLikeThisHandlerTest.java
@@ -38,7 +38,6 @@ public class MoreLikeThisHandlerTest extends SolrTestCaseJ4 {
   @BeforeClass
   public static void moreLikeThisBeforeClass() throws Exception {
     initCore("solrconfig.xml", "schema.xml");
-    lrf = h.getRequestFactory("standard", 0, 20 );
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/handler/SearchHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/SearchHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/SearchHandlerTest.java
new file mode 100644
index 0000000..b35103b
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/handler/SearchHandlerTest.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.handler;
+
+import org.apache.solr.util.AbstractSolrTestCase;
+import org.junit.BeforeClass;
+
+/**
+ * Most of the tests for {@link org.apache.solr.handler.component.SearchHandler} are in {@link org.apache.solr.ConvertedLegacyTest}.
+ */
+public class SearchHandlerTest extends AbstractSolrTestCase {
+  
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    initCore("solrconfig.xml", "schema.xml");
+  }
+  
+  public void testSorting() throws Exception {
+    assertU(adoc("id", "10", "title", "test", "val_s1", "aaa"));
+    assertU(adoc("id", "11", "title", "test", "val_s1", "bbb"));
+    assertU(adoc("id", "12", "title", "test", "val_s1", "ccc"));
+    assertU(commit());
+
+    assertQ(req("q", "title:test")
+            ,"//*[@numFound='3']"
+            );
+    
+    assertQ(req("q", "title:test", "sort","val_s1 asc")
+            ,"//*[@numFound='3']"
+            ,"//result/doc[1]/str[@name='id'][.='10']"
+            ,"//result/doc[2]/str[@name='id'][.='11']"
+            ,"//result/doc[3]/str[@name='id'][.='12']"
+            );
+
+    assertQ(req("q", "title:test", "sort","val_s1 desc")
+            ,"//*[@numFound='3']"
+            ,"//result/doc[1]/str[@name='id'][.='12']"
+            ,"//result/doc[2]/str[@name='id'][.='11']"
+            ,"//result/doc[3]/str[@name='id'][.='10']"
+            );
+    
+    // Make sure score parsing works
+    assertQ(req("q", "title:test", "sort","score desc")
+        ,"//*[@numFound='3']"
+    );
+
+    assertQ(req("q", "title:test", "sort","score asc")
+        ,"//*[@numFound='3']"
+    );
+    
+    // Using legacy ';' param
+    assertQ(req("q", "title:test; val_s1 desc", "defType","lucenePlusSort")
+            ,"//*[@numFound='3']"
+            ,"//result/doc[1]/str[@name='id'][.='12']"
+            ,"//result/doc[2]/str[@name='id'][.='11']"
+            ,"//result/doc[3]/str[@name='id'][.='10']"
+            );
+
+    assertQ(req("q", "title:test; val_s1 asc", "defType","lucenePlusSort")
+            ,"//*[@numFound='3']"
+            ,"//result/doc[1]/str[@name='id'][.='10']"
+            ,"//result/doc[2]/str[@name='id'][.='11']"
+            ,"//result/doc[3]/str[@name='id'][.='12']"
+            );
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/handler/StandardRequestHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/StandardRequestHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/StandardRequestHandlerTest.java
deleted file mode 100644
index 668fefd..0000000
--- a/solr/core/src/test/org/apache/solr/handler/StandardRequestHandlerTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.handler;
-
-import org.apache.solr.core.SolrCore;
-import org.apache.solr.util.AbstractSolrTestCase;
-import org.junit.BeforeClass;
-
-/**
- * Most of the tests for StandardRequestHandler are in ConvertedLegacyTest
- * 
- */
-public class StandardRequestHandlerTest extends AbstractSolrTestCase {
-  
-  @BeforeClass
-  public static void beforeClass() throws Exception {
-    initCore("solrconfig.xml", "schema.xml");
-  }
-  
-  @Override public void setUp() throws Exception {
-    super.setUp();
-    lrf = h.getRequestFactory("standard", 0, 20 );
-  }
-  
-  public void testSorting() throws Exception {
-    SolrCore core = h.getCore();
-    assertU(adoc("id", "10", "title", "test", "val_s1", "aaa"));
-    assertU(adoc("id", "11", "title", "test", "val_s1", "bbb"));
-    assertU(adoc("id", "12", "title", "test", "val_s1", "ccc"));
-    assertU(commit());
-
-    assertQ(req("q", "title:test")
-            ,"//*[@numFound='3']"
-            );
-    
-    assertQ(req("q", "title:test", "sort","val_s1 asc")
-            ,"//*[@numFound='3']"
-            ,"//result/doc[1]/str[@name='id'][.='10']"
-            ,"//result/doc[2]/str[@name='id'][.='11']"
-            ,"//result/doc[3]/str[@name='id'][.='12']"
-            );
-
-    assertQ(req("q", "title:test", "sort","val_s1 desc")
-            ,"//*[@numFound='3']"
-            ,"//result/doc[1]/str[@name='id'][.='12']"
-            ,"//result/doc[2]/str[@name='id'][.='11']"
-            ,"//result/doc[3]/str[@name='id'][.='10']"
-            );
-    
-    // Make sure score parsing works
-    assertQ(req("q", "title:test", "sort","score desc")
-        ,"//*[@numFound='3']"
-    );
-
-    assertQ(req("q", "title:test", "sort","score asc")
-        ,"//*[@numFound='3']"
-    );
-    
-    // Using legacy ';' param
-    assertQ(req("q", "title:test; val_s1 desc", "defType","lucenePlusSort")
-            ,"//*[@numFound='3']"
-            ,"//result/doc[1]/str[@name='id'][.='12']"
-            ,"//result/doc[2]/str[@name='id'][.='11']"
-            ,"//result/doc[3]/str[@name='id'][.='10']"
-            );
-
-    assertQ(req("q", "title:test; val_s1 asc", "defType","lucenePlusSort")
-            ,"//*[@numFound='3']"
-            ,"//result/doc[1]/str[@name='id'][.='10']"
-            ,"//result/doc[2]/str[@name='id'][.='11']"
-            ,"//result/doc[3]/str[@name='id'][.='12']"
-            );
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/handler/component/DistributedSpellCheckComponentTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedSpellCheckComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedSpellCheckComponentTest.java
index 40e952a..9e84fd2 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/DistributedSpellCheckComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedSpellCheckComponentTest.java
@@ -124,11 +124,11 @@ public class DistributedSpellCheckComponentTest extends BaseDistributedSearchTes
     handle.put("grouped", SKIP);
     
     //Randomly select either IndexBasedSpellChecker or DirectSolrSpellChecker
-    String requestHandlerName = "spellCheckCompRH_Direct";
-    String reqHandlerWithWordbreak = "spellCheckWithWordbreak_Direct";
+    String requestHandlerName = "/spellCheckCompRH_Direct";
+    String reqHandlerWithWordbreak = "/spellCheckWithWordbreak_Direct";
     if(random().nextBoolean()) {
-      requestHandlerName = "spellCheckCompRH";
-      reqHandlerWithWordbreak = "spellCheckWithWordbreak";   
+      requestHandlerName = "/spellCheckCompRH";
+      reqHandlerWithWordbreak = "/spellCheckWithWordbreak";
     } 
     
     //Shortcut names
@@ -143,7 +143,7 @@ public class DistributedSpellCheckComponentTest extends BaseDistributedSearchTes
     String maxResults = SpellingParams.SPELLCHECK_MAX_RESULTS_FOR_SUGGEST;
      
     //Build the dictionary for IndexBasedSpellChecker
-    q(buildRequest("*:*", false, "spellCheckCompRH", false, build, "true"));
+    q(buildRequest("*:*", false, "/spellCheckCompRH", false, build, "true"));
     
     //Test Basic Functionality
     query(buildRequest("toyata", true, requestHandlerName, random().nextBoolean(), (String[]) null));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/handler/component/FacetPivotSmallTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/FacetPivotSmallTest.java b/solr/core/src/test/org/apache/solr/handler/component/FacetPivotSmallTest.java
index 4b5e8a7..0f4ec06 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/FacetPivotSmallTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/FacetPivotSmallTest.java
@@ -40,7 +40,6 @@ public class FacetPivotSmallTest extends SolrTestCaseJ4 {
     super.setUp();
     clearIndex();
     assertU(commit());
-    lrf = h.getRequestFactory("standard", 0, 20);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/handler/component/ResponseLogComponentTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/ResponseLogComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/ResponseLogComponentTest.java
index 7e309fc..cf657da 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/ResponseLogComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/ResponseLogComponentTest.java
@@ -38,8 +38,8 @@ public class ResponseLogComponentTest extends SolrTestCaseJ4 {
   public void testToLogIds() throws Exception {
     SolrQueryRequest req = null;
     try {
-      String handler="withlog";
-      req = req("indent","true", "qt","withlog",  "q","aa", "rows","2",
+      String handler="/withlog";
+      req = req("indent","true", "qt","/withlog",  "q","aa", "rows","2",
           "fl","id,subject", "responseLog","true");
       SolrQueryResponse qr = h.queryAndResponse(handler, req);
       NamedList<Object> entries = qr.getToLog();
@@ -55,8 +55,8 @@ public class ResponseLogComponentTest extends SolrTestCaseJ4 {
   public void testToLogScores() throws Exception {
     SolrQueryRequest req = null;
     try {
-      String handler="withlog";
-      req = req("indent","true", "qt","withlog",  "q","aa", "rows","2",
+      String handler="/withlog";
+      req = req("indent","true", "qt","/withlog",  "q","aa", "rows","2",
           "fl","id,subject,score", "responseLog","true");
       SolrQueryResponse qr = h.queryAndResponse(handler, req);
       NamedList<Object> entries = qr.getToLog();
@@ -72,8 +72,8 @@ public class ResponseLogComponentTest extends SolrTestCaseJ4 {
   public void testDisabling() throws Exception {
     SolrQueryRequest req = null;
     try {
-      String handler="withlog";
-      req = req("indent","true", "qt","withlog",  "q","aa", "rows","2", 
+      String handler="/withlog";
+      req = req("indent","true", "qt","/withlog",  "q","aa", "rows","2",
           "fl","id,subject", "responseLog","false");
       SolrQueryResponse qr = h.queryAndResponse(handler, req);
       NamedList<Object> entries = qr.getToLog();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/handler/component/SpellCheckComponentTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/SpellCheckComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/SpellCheckComponentTest.java
index 37d02d9..d3b0828 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/SpellCheckComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/SpellCheckComponentTest.java
@@ -43,7 +43,7 @@ import org.junit.Test;
 @Slow
 @SuppressTempFileChecks(bugUrl = "https://issues.apache.org/jira/browse/SOLR-1877 Spellcheck IndexReader leak bug?")
 public class SpellCheckComponentTest extends SolrTestCaseJ4 {
-  static String rh = "spellCheckCompRH";
+  static String rh = "/spellCheckCompRH";
 
 
   @BeforeClass
@@ -254,7 +254,7 @@ public class SpellCheckComponentTest extends SolrTestCaseJ4 {
   public void testReloadOnStart() throws Exception {
     assertU(adoc("id", "0", "lowerfilt", "This is a title"));
     assertU(commit());
-    SolrQueryRequest request = req("qt", "spellCheckCompRH", "q", "*:*",
+    SolrQueryRequest request = req("qt", "/spellCheckCompRH", "q", "*:*",
         "spellcheck.q", "ttle", "spellcheck", "true", "spellcheck.dictionary",
         "default", "spellcheck.build", "true");
     assertQ(request, "//arr[@name='suggestion'][.='title']");
@@ -271,7 +271,7 @@ public class SpellCheckComponentTest extends SolrTestCaseJ4 {
     checker.init(args);
     checker.inform(h.getCore());
 
-    request = req("qt", "spellCheckCompRH", "q", "*:*", "spellcheck.q", "ttle",
+    request = req("qt", "/spellCheckCompRH", "q", "*:*", "spellcheck.q", "ttle",
         "spellcheck", "true", "spellcheck.dictionary", "default",
         "spellcheck.reload", "true");
     List<SearchComponent> components = new ArrayList<>();
@@ -293,7 +293,7 @@ public class SpellCheckComponentTest extends SolrTestCaseJ4 {
     @SuppressWarnings("unchecked")
     @Test
   public void testRebuildOnCommit() throws Exception {
-    SolrQueryRequest req = req("q", "lowerfilt:lucenejavt", "qt", "spellCheckCompRH", "spellcheck", "true");
+    SolrQueryRequest req = req("q", "lowerfilt:lucenejavt", "qt", "/spellCheckCompRH", "spellcheck", "true");
     String response = h.query(req);
     assertFalse("No suggestions should be returned", response.contains("lucenejava"));
     
@@ -330,7 +330,7 @@ public class SpellCheckComponentTest extends SolrTestCaseJ4 {
         params.add(SpellingParams.SPELLCHECK_EXTENDED_RESULTS,"true");
         params.add(CommonParams.Q, "anotheq");
 
-        SolrRequestHandler handler = core.getRequestHandler("spellCheckCompRH");
+        SolrRequestHandler handler = core.getRequestHandler("/spellCheckCompRH");
         SolrQueryResponse rsp = new SolrQueryResponse();
         rsp.addResponseHeader(new SimpleOrderedMap());
         SolrQueryRequest req = new LocalSolrQueryRequest(core, params);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/handler/component/StatsComponentTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/StatsComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/StatsComponentTest.java
index 3bb4974..cee1ab5 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/StatsComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/StatsComponentTest.java
@@ -78,7 +78,6 @@ public class StatsComponentTest extends AbstractSolrTestCase {
     super.setUp();
     clearIndex();
     assertU(commit());
-    lrf = h.getRequestFactory("standard", 0, 20);
   }
 
   public void testStats() throws Exception {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/handler/component/SuggestComponentTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/SuggestComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/SuggestComponentTest.java
index ed7a9e7..b15e167 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/SuggestComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/SuggestComponentTest.java
@@ -516,7 +516,7 @@ public class SuggestComponentTest extends SolrTestCaseJ4 {
       waitForWarming();
     }
     
-    assertQ(req("qt", "standard", 
+    assertQ(req("qt", "/select",
         "q", "*:*"), 
         "//*[@numFound='11']"
         );

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/handler/component/TermVectorComponentTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/TermVectorComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/TermVectorComponentTest.java
index abee4bd..91a5869 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/TermVectorComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/TermVectorComponentTest.java
@@ -118,7 +118,7 @@ public class TermVectorComponentTest extends SolrTestCaseJ4 {
     assertNull(h.validateUpdate(commit()));
   }
 
-  static String tv = "tvrh";
+  static String tv = "/tvrh";
 
   @Test
   public void testBasics() throws Exception {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/highlight/FastVectorHighlighterTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/highlight/FastVectorHighlighterTest.java b/solr/core/src/test/org/apache/solr/highlight/FastVectorHighlighterTest.java
index aafe3f5..99868a7 100644
--- a/solr/core/src/test/org/apache/solr/highlight/FastVectorHighlighterTest.java
+++ b/solr/core/src/test/org/apache/solr/highlight/FastVectorHighlighterTest.java
@@ -77,7 +77,7 @@ public class FastVectorHighlighterTest extends SolrTestCaseJ4 {
       args.put("hl.method", "fastVector"); // the new way
     }
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard",0,200,args);
+      "",0,200,args);
     
     assertU(adoc("tv_text", "basic fast vector highlighter test", 
                  "id", "1"));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/highlight/HighlighterConfigTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/highlight/HighlighterConfigTest.java b/solr/core/src/test/org/apache/solr/highlight/HighlighterConfigTest.java
index f022e96..5832132 100644
--- a/solr/core/src/test/org/apache/solr/highlight/HighlighterConfigTest.java
+++ b/solr/core/src/test/org/apache/solr/highlight/HighlighterConfigTest.java
@@ -62,7 +62,7 @@ public class HighlighterConfigTest extends AbstractSolrTestCase {
     args.put("df", "t_text");
     args.put("hl.fl", "");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
 
     assertU(adoc("t_text", "a long day's night", "id", "1"));
     assertU(commit());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/highlight/HighlighterTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/highlight/HighlighterTest.java b/solr/core/src/test/org/apache/solr/highlight/HighlighterTest.java
index f0b58cd..759de00 100644
--- a/solr/core/src/test/org/apache/solr/highlight/HighlighterTest.java
+++ b/solr/core/src/test/org/apache/solr/highlight/HighlighterTest.java
@@ -119,7 +119,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put(HighlightParams.MERGE_CONTIGUOUS_FRAGMENTS, "true");
     args.put(HighlightParams.METHOD, "original"); // test works; no complaints
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     String input = "this is some long text.  It has the word long in many places.  In fact, it has long on some different fragments.  " +
             "Let us see what happens to long in this case.";
     String gold = "this is some <em>long</em> text.  It has the word <em>long</em> in many places.  In fact, it has <em>long</em> on some different fragments.  " +
@@ -145,7 +145,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put(HighlightParams.MERGE_CONTIGUOUS_FRAGMENTS, "false");
     args.put("f.t_text." + HighlightParams.MERGE_CONTIGUOUS_FRAGMENTS, "false");
     sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     assertQ("Merge Contiguous",
         sumLRF.makeRequest("t_text:long"),
         "//lst[@name='highlighting']/lst[@name='1']",
@@ -165,7 +165,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.fl", "tv_text");
     args.put("hl.snippets", "2");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard",0,200,args);
+      "",0,200,args);
     
     assertU(adoc("tv_text", LONG_TEXT, 
                  "id", "1"));
@@ -186,7 +186,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl", "true");
     args.put("hl.fl", "tv_no_off_text");
 
-    TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory("", 0, 200, args);
 
     assertU(adoc("tv_no_off_text", "Crackerjack Cameron", "id", "1"));
     assertU(commit());
@@ -229,7 +229,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.fl", "tv_mv_text");
     args.put("hl.snippets", "2");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard",0,200,args);
+      "",0,200,args);
     
     assertU(adoc("tv_mv_text", LONG_TEXT, 
                  "tv_mv_text", LONG_TEXT, 
@@ -256,7 +256,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.fl", "tv_mv_text");
     args.put("hl.snippets", "2");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard",0,200,args);
+      "",0,200,args);
 
     String shortText = "short";
     assertU(adoc("tv_mv_text", shortText,
@@ -282,7 +282,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("qf", "tv_text");
     args.put("q.alt", "*:*");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "dismax",0,200,args);
+      "/dismax",0,200,args);
     
     assertU(adoc("tv_text", "a long day's night", "id", "1"));
     assertU(commit());
@@ -309,7 +309,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.fl", "textgap");
     args.put("df", "textgap");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     
     assertU(adoc("textgap", "first entry hasnt queryword",
         "textgap", "second entry has queryword long",
@@ -331,7 +331,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.fl", "textgap");
     args.put("df", "textgap");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-        "standard", 0, 200, args);
+        "", 0, 200, args);
     
     assertU(adoc("textgap", "first entry has one word foo", 
         "textgap", "second entry has both words foo bar",
@@ -370,7 +370,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("df", "t_text");
     args.put("hl.fl", "");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     
     assertU(adoc("t_text", "a long day's night", "id", "1"));
     assertU(commit());
@@ -392,7 +392,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl", "false");
     args.put("hl.fl", "t_text");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     
     assertU(adoc("t_text", "a long day's night", "id", "1"));
     assertU(commit());
@@ -410,7 +410,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl", "true");
     args.put("hl.fl", "t_text tv_text");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     
     assertU(adoc("t_text", "a long day's night", "id", "1",
                  "tv_text", "a long night's day"));
@@ -437,7 +437,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
      args.put("hl.fl", "t_text1 t_text2");
      
      TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-           "standard", 0, 200, args);
+           "", 0, 200, args);
      // default should highlight both random and words in both fields
      assertQ("Test Default",
            sumLRF.makeRequest("t_text1:random OR t_text2:words"),
@@ -449,7 +449,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
      // requireFieldMatch=true - highlighting should only occur if term matched in that field
      args.put("hl.requireFieldMatch", "true");
      sumLRF = h.getRequestFactory(
-           "standard", 0, 200, args);
+           "", 0, 200, args);
      assertQ("Test RequireFieldMatch",
          sumLRF.makeRequest("t_text1:random OR t_text2:words"),
          "//lst[@name='highlighting']/lst[@name='1']",
@@ -463,7 +463,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
      assertU(delI("1"));
      assertU(commit());
      sumLRF = h.getRequestFactory(
-           "standard", 0, 200, args);
+           "", 0, 200, args);
      assertQ("Test RequireFieldMatch on un-optimized index",
            sumLRF.makeRequest("t_text1:random OR t_text2:words"),
            "//lst[@name='highlighting']/lst[@name='2']",
@@ -482,7 +482,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.simple.pre","<B>");
     args.put("hl.simple.post", "</B>");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     
     assertU(adoc("t_text", "a long days night", "id", "1"));
     assertU(commit());
@@ -497,7 +497,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("f.t_text.hl.simple.pre", "<I>");
     args.put("f.t_text.hl.simple.post", "</I>");
     sumLRF = h.getRequestFactory(
-          "standard", 0, 200, args);
+          "", 0, 200, args);
     assertQ("Basic summarization",
           sumLRF.makeRequest("t_text:long"),
           "//lst[@name='highlighting']/lst[@name='1']",
@@ -513,7 +513,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl", "true");
     args.put("hl.fl", "tv_text");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     
 
     String text = 
@@ -537,7 +537,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     final String field = random().nextBoolean() ? "t_text" : "tv_text";
     args.put("hl.fl", field);
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     
 
     assertU(adoc(field, LONG_TEXT, "id", "1"));
@@ -549,14 +549,14 @@ public class HighlighterTest extends SolrTestCaseJ4 {
             "//lst[@name='1']/arr[count(str)=1]"
             );
     args.put("hl.maxAnalyzedChars", "20");
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("token at end of text",
         sumLRF.makeRequest(field + ":disjoint"),
         "//lst[@name='highlighting']/lst[@name='1']",
         "//lst[@name='1'][not(*)]"
     );
     args.put("hl.maxAnalyzedChars", "-1");
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("token at start of text",
         sumLRF.makeRequest(field + ":disjoint"),
         "//lst[@name='highlighting']/lst[@name='1']",
@@ -598,7 +598,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.regex.pattern", "[-\\w ,\"']{20,200}");
     args.put("hl.regex.slop", ".9");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     
     String t = "This is an example of a sentence. Another example \"sentence\" with " +
       "special characters\nand a line-break! Miscellaneous character like ^ are " +
@@ -617,7 +617,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
             );
     // try with some punctuation included
     args.put("hl.regex.pattern", "[-\\w ,^/\\n\"']{20,200}");
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("regex fragmenter 2",
             sumLRF.makeRequest("t_text:example"),
             "//lst[@name='highlighting']/lst[@name='1']",
@@ -640,7 +640,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
      args.put("hl", "true");
      args.put("hl.fl", "tv_text");
      TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-       "standard", 0, 200, args);
+       "", 0, 200, args);
      assertQ("Basic summarization",
            sumLRF.makeRequest("tv_text:long"),
            "//lst[@name='highlighting']/lst[@name='1']",
@@ -650,7 +650,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
      // 25
      args.put("hl.fragsize","25");
      sumLRF = h.getRequestFactory(
-           "standard", 0, 200, args);
+           "", 0, 200, args);
      assertQ("Basic summarization",
            sumLRF.makeRequest("tv_text:long"),
            "//lst[@name='highlighting']/lst[@name='1']",
@@ -660,7 +660,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
      // 0 - NullFragmenter
      args.put("hl.fragsize","0");
      sumLRF = h.getRequestFactory(
-           "standard", 0, 200, args);
+           "", 0, 200, args);
      assertQ("Basic summarization",
            sumLRF.makeRequest("tv_text:long"),
            "//lst[@name='highlighting']/lst[@name='1']",
@@ -684,7 +684,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.fragsize","0");
     args.put("hl.fl", "t_text");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
 
     // no alternate
     assertQ("Alternate summarization",
@@ -695,7 +695,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
 
     // with an alternate
     args.put("hl.alternateField", "foo_t");
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("Alternate summarization",
             sumLRF.makeRequest("tv_text:keyword"),
             "//lst[@name='highlighting']/lst[@name='1' and count(*)=1]",
@@ -705,7 +705,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     // with an alternate + max length
     args.put("hl.alternateField", "t_text");
     args.put("hl.maxAlternateFieldLength", "15");
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("Alternate summarization",
             sumLRF.makeRequest("tv_text:keyword"),
             "//lst[@name='highlighting']/lst[@name='1' and count(*)=1]",
@@ -715,7 +715,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     // with a non-existing alternate field + max length
     args.put("hl.alternateField", "NonExistingField");
     args.put("hl.maxAlternateFieldLength", "15");
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("Alternate summarization",
             sumLRF.makeRequest("tv_text:keyword"),
             "//lst[@name='highlighting']/lst[@name='1' and count(*)=1]",
@@ -744,7 +744,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.alternateField", "tv_text");
     args.put("hl.maxAlternateFieldLength", "39");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     assertQ("Alternate summarization with highlighting",
             sumLRF.makeRequest("tv_text:keyword"),
             "//lst[@name='highlighting']/lst[@name='1' and count(*)=1]",
@@ -761,7 +761,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     // With hl.requireFieldMatch, will not highlight but fall back to plain-text alternate
     args.put("hl.requireFieldMatch", "true");
     sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     assertQ("Alternate summarization with highlighting, requireFieldMatch",
             sumLRF.makeRequest("other_t:keyword"),
             "//lst[@name='highlighting']/lst[@name='1' and count(*)=1]",
@@ -774,7 +774,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.remove("hl.alternateField");
     args.put("f.t_text.hl.alternateField", "tv_text");
     args.put("f.t_text.hl.maxAlternateFieldLength", "0");
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("Alternate summarization with highlighting",
             sumLRF.makeRequest("tv_text:keyword"),
             "//lst[@name='highlighting']/lst[@name='1' and count(*)=1]",
@@ -786,7 +786,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.tag.pre", "<fvhpre>");
     args.put("hl.tag.post", "</fvhpost>");
     args.put("f.t_text.hl.maxAlternateFieldLength", "18");
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("Alternate summarization with highlighting using FVH",
             sumLRF.makeRequest("tv_text:keyword"),
             "//lst[@name='highlighting']/lst[@name='1' and count(*)=1]",
@@ -795,7 +795,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
 
     // Prove it is possible to turn off highlighting of alternate field
     args.put("hl.highlightAlternate", "false");
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("Alternate summarization without highlighting",
             sumLRF.makeRequest("tv_text:keyword"),
             "//lst[@name='highlighting']/lst[@name='1' and count(*)=1]",
@@ -813,7 +813,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.usePhraseHighlighter", "false");
 
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
 
     // String borrowed from Lucene's HighlighterTest
     String t = "This piece of text refers to Kennedy at the beginning then has a longer piece of text that is very long in the middle and finally ends with another reference to Kennedy";
@@ -843,7 +843,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     // now check if Lucene-794 highlighting works as expected
     args.put("hl.usePhraseHighlighter", "true");
 
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     
     // check phrase highlighting
     assertQ("Phrase highlighting - Lucene-794",
@@ -877,7 +877,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     assertU(commit());
     assertU(optimize());
 
-    TestHarness.LocalRequestFactory lrf = h.getRequestFactory("standard", 0,
+    TestHarness.LocalRequestFactory lrf = h.getRequestFactory("", 0,
         10, args);
 
     SolrQueryRequest request = lrf.makeRequest("test");
@@ -893,7 +893,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     request.close();
 
     args.put("hl.fl", "foo_*");
-    lrf = h.getRequestFactory("standard", 0, 10, args);
+    lrf = h.getRequestFactory("", 0, 10, args);
     request = lrf.makeRequest("test");
     highlighter = HighlightComponent.getHighlighter(h.getCore());
     highlightFieldNames = Arrays.asList(highlighter.getHighlightFields(null,
@@ -906,7 +906,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
 
     // SOLR-5127
     args.put("hl.fl", (random().nextBoolean() ? "foo_*,bar_*" : "bar_*,foo_*"));
-    lrf = h.getRequestFactory("standard", 0, 10, args);
+    lrf = h.getRequestFactory("", 0, 10, args);
     // hl.fl ordering need not be preserved in output
     final Set<String> highlightedSetExpected = new HashSet<String>();
     highlightedSetExpected.add("foo_s");
@@ -931,7 +931,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.usePhraseHighlighter", "true");
     args.put("hl.highlightMultiTerm", "true");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     
     assertU(adoc("t_text", "a long day's night", "id", "1"));
     assertU(commit());
@@ -955,7 +955,7 @@ public class HighlighterTest extends SolrTestCaseJ4 {
     args.put("hl.usePhraseHighlighter", "true");
     args.put("hl.highlightMultiTerm", "true");
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-      "standard", 0, 200, args);
+      "", 0, 200, args);
     
     assertU(adoc("t_text", "a long day's night", "id", "1"));
     assertU(commit());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
index a8e7ecd..b2cb5f3 100644
--- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java
@@ -43,7 +43,7 @@ public class SolrMetricsIntegrationTest extends SolrTestCaseJ4 {
   private static final int MAX_ITERATIONS = 20;
   private static final String CORE_NAME = "metrics_integration";
   private static final String METRIC_NAME = "requestTimes";
-  private static final String HANDLER_NAME = "standard";
+  private static final String HANDLER_NAME = "/select";
   private static final String[] REPORTER_NAMES = {"reporter1", "reporter2"};
   private static final String UNIVERSAL = "universal";
   private static final String SPECIFIC = "specific";

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java b/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
index 0ee345e..35a66c3 100644
--- a/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
+++ b/solr/core/src/test/org/apache/solr/request/SimpleFacetsTest.java
@@ -3312,7 +3312,7 @@ public class SimpleFacetsTest extends SolrTestCaseJ4 {
       SolrQueryRequest req = req(params);
       log.info("Using Params: " + params);
       try {
-        SolrQueryResponse rsp = h.queryAndResponse("standard", req);
+        SolrQueryResponse rsp = h.queryAndResponse("", req);
         rangeFacetsFilter = (NamedList<Object>) ((NamedList<Object>) rsp.getValues().get("facet_counts")).get("facet_ranges");
       } finally {
         req.close();
@@ -3320,7 +3320,7 @@ public class SimpleFacetsTest extends SolrTestCaseJ4 {
       params.add("facet.range.method", FacetRangeMethod.DV.toString());
       req = req(params);
       try {
-        SolrQueryResponse rsp = h.queryAndResponse("standard", req);
+        SolrQueryResponse rsp = h.queryAndResponse("", req);
         rangeFacetsDv = (NamedList<Object>) ((NamedList<Object>) rsp.getValues().get("facet_counts")).get("facet_ranges");
       } finally {
         req.close();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java b/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java
index fc8ddff..df0031f 100644
--- a/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java
+++ b/solr/core/src/test/org/apache/solr/request/TestIntervalFaceting.java
@@ -326,7 +326,7 @@ public class TestIntervalFaceting extends SolrTestCaseJ4 {
     }
     SolrQueryRequest req = req(params);
     try {
-      SolrQueryResponse rsp = h.queryAndResponse("standard", req);
+      SolrQueryResponse rsp = h.queryAndResponse("", req);
       NamedList<Object> facetQueries = (NamedList<Object>) ((NamedList<Object>) rsp.getValues().get("facet_counts")).get("facet_queries");
       NamedList<Object> facetIntervals = (NamedList<Object>) ((NamedList<Object>) (NamedList<Object>) ((NamedList<Object>) rsp.getValues().get("facet_counts"))
           .get("facet_intervals")).get(field);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/search/TestComplexPhraseQParserPlugin.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestComplexPhraseQParserPlugin.java b/solr/core/src/test/org/apache/solr/search/TestComplexPhraseQParserPlugin.java
index 8c59281..02060a9 100644
--- a/solr/core/src/test/org/apache/solr/search/TestComplexPhraseQParserPlugin.java
+++ b/solr/core/src/test/org/apache/solr/search/TestComplexPhraseQParserPlugin.java
@@ -102,7 +102,7 @@ public class TestComplexPhraseQParserPlugin extends AbstractSolrTestCase {
     args.put(CommonParams.FL, "id");
 
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-            "standard", 0, 200, args);
+            "", 0, 200, args);
 
     assertU(adoc("name", "john smith", "id", "1"));
     assertU(adoc("name", "johathon smith", "id", "2"));
@@ -181,7 +181,7 @@ public class TestComplexPhraseQParserPlugin extends AbstractSolrTestCase {
 
 
     TestHarness.LocalRequestFactory sumLRF = h.getRequestFactory(
-            "standard", 0, 200, args);
+            "", 0, 200, args);
 
     assertU(adoc("name", "john smith smith john", "id", "1"));
     assertU(adoc("name", "johathon smith smith johathon", "id", "2"));
@@ -198,7 +198,7 @@ public class TestComplexPhraseQParserPlugin extends AbstractSolrTestCase {
     );
 
 
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("PhraseHighlighter=true Test",
             sumLRF.makeRequest("name:\"(john johathon) smith\""),
             "//lst[@name='highlighting']/lst[@name='1']",
@@ -209,7 +209,7 @@ public class TestComplexPhraseQParserPlugin extends AbstractSolrTestCase {
 
 
     args.put(HighlightParams.USE_PHRASE_HIGHLIGHTER, Boolean.FALSE.toString());
-    sumLRF = h.getRequestFactory("standard", 0, 200, args);
+    sumLRF = h.getRequestFactory("", 0, 200, args);
     assertQ("PhraseHighlighter=false Test",
             sumLRF.makeRequest("name:\"(john johathon) smith\""),
             "//lst[@name='highlighting']/lst[@name='1']",

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetDistribTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetDistribTest.java b/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetDistribTest.java
index 1b12657..123ce97 100644
--- a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetDistribTest.java
+++ b/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetDistribTest.java
@@ -137,7 +137,7 @@ public class BlockJoinFacetDistribTest extends SolrCloudTestCase{
               oldFacetsEnabled&&usually() ? "facet.limit" : "ignore" , "1",
               oldFacetsEnabled&&usually() ? "facet.mincount" : "ignore" , "2",
               oldFacetsEnabled&&usually() ? "facet.overrequest.count" : "ignore" , "0",
-          "qt",  random().nextBoolean() ? "blockJoinDocSetFacetRH" : "blockJoinFacetRH",
+          "qt",  random().nextBoolean() ? "/blockJoinDocSetFacetRH" : "/blockJoinFacetRH",
           "child.facet.field", "COLOR_s",
           "child.facet.field", "SIZE_s",
           "distrib.singlePass", random().nextBoolean() ? "true":"false",

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetRandomTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetRandomTest.java b/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetRandomTest.java
index 1b04d79..21ec780 100644
--- a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetRandomTest.java
+++ b/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetRandomTest.java
@@ -46,7 +46,7 @@ public class BlockJoinFacetRandomTest extends SolrTestCaseJ4 {
   @BeforeClass
   public static void beforeClass() throws Exception {
     initCore("solrconfig-blockjoinfacetcomponent.xml", "schema-blockjoinfacetcomponent.xml");
-    handler = random().nextBoolean() ? "blockJoinDocSetFacetRH":"blockJoinFacetRH";
+    handler = random().nextBoolean() ? "/blockJoinDocSetFacetRH":"/blockJoinFacetRH";
     facets = createFacets();
     createIndex();
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetSimpleTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetSimpleTest.java b/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetSimpleTest.java
index 5e610cf..c4d3a64 100644
--- a/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetSimpleTest.java
+++ b/solr/core/src/test/org/apache/solr/search/join/BlockJoinFacetSimpleTest.java
@@ -32,7 +32,7 @@ public class BlockJoinFacetSimpleTest extends SolrTestCaseJ4 {
   @BeforeClass
   public static void beforeClass() throws Exception {
     initCore("solrconfig-blockjoinfacetcomponent.xml", "schema-blockjoinfacetcomponent.xml");
-    handler = random().nextBoolean() ? "blockJoinDocSetFacetRH":"blockJoinFacetRH";
+    handler = random().nextBoolean() ? "/blockJoinDocSetFacetRH":"/blockJoinFacetRH";
     createIndex();
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/spelling/DirectSolrSpellCheckerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/spelling/DirectSolrSpellCheckerTest.java b/solr/core/src/test/org/apache/solr/spelling/DirectSolrSpellCheckerTest.java
index cb5bba7..29551de 100644
--- a/solr/core/src/test/org/apache/solr/spelling/DirectSolrSpellCheckerTest.java
+++ b/solr/core/src/test/org/apache/solr/spelling/DirectSolrSpellCheckerTest.java
@@ -83,7 +83,7 @@ public class DirectSolrSpellCheckerTest extends SolrTestCaseJ4 {
   
   @Test
   public void testOnlyMorePopularWithExtendedResults() throws Exception {
-    assertQ(req("q", "teststop:fox", "qt", "spellCheckCompRH", SpellCheckComponent.COMPONENT_NAME, "true", SpellingParams.SPELLCHECK_DICT, "direct", SpellingParams.SPELLCHECK_EXTENDED_RESULTS, "true", SpellingParams.SPELLCHECK_ONLY_MORE_POPULAR, "true"),
+    assertQ(req("q", "teststop:fox", "qt", "/spellCheckCompRH", SpellCheckComponent.COMPONENT_NAME, "true", SpellingParams.SPELLCHECK_DICT, "direct", SpellingParams.SPELLCHECK_EXTENDED_RESULTS, "true", SpellingParams.SPELLCHECK_ONLY_MORE_POPULAR, "true"),
         "//lst[@name='spellcheck']/lst[@name='suggestions']/lst[@name='fox']/int[@name='origFreq']=1",
         "//lst[@name='spellcheck']/lst[@name='suggestions']/lst[@name='fox']/arr[@name='suggestion']/lst/str[@name='word']='foo'",
         "//lst[@name='spellcheck']/lst[@name='suggestions']/lst[@name='fox']/arr[@name='suggestion']/lst/int[@name='freq']=2",

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/spelling/SpellCheckCollatorTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/spelling/SpellCheckCollatorTest.java b/solr/core/src/test/org/apache/solr/spelling/SpellCheckCollatorTest.java
index 5428044..06f18fc 100644
--- a/solr/core/src/test/org/apache/solr/spelling/SpellCheckCollatorTest.java
+++ b/solr/core/src/test/org/apache/solr/spelling/SpellCheckCollatorTest.java
@@ -115,7 +115,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
     params.add(SpellingParams.SPELLCHECK_ALTERNATIVE_TERM_COUNT, "10"); 
     params.add(CommonParams.Q, "id:[1 TO 10] AND lowerfilt:lovw");
     {
-      SolrRequestHandler handler = core.getRequestHandler("spellCheckCompRH");
+      SolrRequestHandler handler = core.getRequestHandler("/spellCheckCompRH");
       SolrQueryResponse rsp = new SolrQueryResponse();
       rsp.addResponseHeader(new SimpleOrderedMap());
       SolrQueryRequest req = new LocalSolrQueryRequest(core, params);
@@ -147,7 +147,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
     
     params.add(CommonParams.Q, "lowerfilt:(hypenated-wotd)");
     {
-      SolrRequestHandler handler = core.getRequestHandler("spellCheckCompRH");
+      SolrRequestHandler handler = core.getRequestHandler("/spellCheckCompRH");
       SolrQueryResponse rsp = new SolrQueryResponse();
       rsp.addResponseHeader(new SimpleOrderedMap());
       SolrQueryRequest req = new LocalSolrQueryRequest(core, params);
@@ -164,10 +164,10 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
 
     params.remove(CommonParams.Q);
     params.add("defType", "dismax");
-    params.add("qf", "lowerfilt");
+    params.add("qf", "/lowerfilt");
     params.add(CommonParams.Q, "hypenated-wotd");
     {
-      SolrRequestHandler handler = core.getRequestHandler("spellCheckCompRH");
+      SolrRequestHandler handler = core.getRequestHandler("/spellCheckCompRH");
       SolrQueryResponse rsp = new SolrQueryResponse();
       rsp.add("responseHeader", new SimpleOrderedMap());
       SolrQueryRequest req = new LocalSolrQueryRequest(core, params);
@@ -194,7 +194,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
         SpellingParams.SPELLCHECK_COLLATE, "true",
         SpellingParams.SPELLCHECK_MAX_COLLATION_TRIES, "10",
         SpellingParams.SPELLCHECK_MAX_COLLATIONS, "10",
-        "qt", "spellCheckCompRH",
+        "qt", "/spellCheckCompRH",
         "defType", "edismax",
         "qf", "teststop",
         "mm", "1",
@@ -210,7 +210,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
           SpellingParams.SPELLCHECK_COLLATE, "true",
           SpellingParams.SPELLCHECK_MAX_COLLATION_TRIES, "10",
           SpellingParams.SPELLCHECK_MAX_COLLATIONS, "10",
-          "qt", "spellCheckCompRH",
+          "qt", "/spellCheckCompRH",
           "defType", "edismax",
           "qf", "teststop",
           "mm", "1",
@@ -241,7 +241,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
 
     //Because a FilterQuery is applied which removes doc id#1 from possible hits, we would
     //not want the collations to return us "lowerfilt:(+faith +hope +loaves)" as this only matches doc id#1.
-    SolrRequestHandler handler = core.getRequestHandler("spellCheckCompRH");
+    SolrRequestHandler handler = core.getRequestHandler("/spellCheckCompRH");
     SolrQueryResponse rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap());
     SolrQueryRequest req = new LocalSolrQueryRequest(core, params);
@@ -276,7 +276,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
 
     //SpellCheckCompRH has no "qf" defined.  It will not find "peace" from "peac" despite it being in the dictionary
     //because requrying against this Request Handler results in 0 hits.
-    SolrRequestHandler handler = core.getRequestHandler("spellCheckCompRH");
+    SolrRequestHandler handler = core.getRequestHandler("/spellCheckCompRH");
     SolrQueryResponse rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap());
     SolrQueryRequest req = new LocalSolrQueryRequest(core, params);
@@ -291,7 +291,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
     //SpellCheckCompRH1 has "lowerfilt1" defined in the "qf" param.  It will find "peace" from "peac" because
     //requrying field "lowerfilt1" returns the hit.
     params.remove(SpellingParams.SPELLCHECK_BUILD);
-    handler = core.getRequestHandler("spellCheckCompRH1");
+    handler = core.getRequestHandler("/spellCheckCompRH1");
     rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap());
     req = new LocalSolrQueryRequest(core, params);
@@ -323,7 +323,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
     // Returns 1 collation as a single string.
     // All words are "correct" per the dictionary, but this collation would
     // return no results if tried.
-    SolrRequestHandler handler = core.getRequestHandler("spellCheckCompRH");
+    SolrRequestHandler handler = core.getRequestHandler("/spellCheckCompRH");
     SolrQueryResponse rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap());
     SolrQueryRequest req = new LocalSolrQueryRequest(core, params);
@@ -340,7 +340,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
     params.remove(SpellingParams.SPELLCHECK_BUILD);
     params.add(SpellingParams.SPELLCHECK_MAX_COLLATION_TRIES, "5");
     params.add(SpellingParams.SPELLCHECK_MAX_COLLATIONS, "1");
-    handler = core.getRequestHandler("spellCheckCompRH");
+    handler = core.getRequestHandler("/spellCheckCompRH");
     rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap());
     req = new LocalSolrQueryRequest(core, params);
@@ -358,7 +358,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
     params.remove(SpellingParams.SPELLCHECK_MAX_COLLATIONS);
     params.add(SpellingParams.SPELLCHECK_MAX_COLLATION_TRIES, "10");
     params.add(SpellingParams.SPELLCHECK_MAX_COLLATIONS, "2");
-    handler = core.getRequestHandler("spellCheckCompRH");
+    handler = core.getRequestHandler("/spellCheckCompRH");
     rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap());
     req = new LocalSolrQueryRequest(core, params);
@@ -377,7 +377,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
     // Testing return multiple collations with expanded collation response
     // format.
     params.add(SpellingParams.SPELLCHECK_COLLATE_EXTENDED_RESULTS, "true");
-    handler = core.getRequestHandler("spellCheckCompRH");
+    handler = core.getRequestHandler("/spellCheckCompRH");
     rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap());
     req = new LocalSolrQueryRequest(core, params);
@@ -430,7 +430,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
 
     //Because a FilterQuery is applied which removes doc id#1 from possible hits, we would
     //not want the collations to return us "lowerfilt:(+faith +hope +loaves)" as this only matches doc id#1.
-    SolrRequestHandler handler = core.getRequestHandler("spellCheckCompRH");
+    SolrRequestHandler handler = core.getRequestHandler("/spellCheckCompRH");
     SolrQueryResponse rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap());
     SolrQueryRequest req = new LocalSolrQueryRequest(core, params);
@@ -451,7 +451,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
       assertQ(
         req(
           "q", "teststop:(flew AND form AND heathrow)",
-          "qt", "spellCheckCompRH",
+          "qt", "/spellCheckCompRH",
           "indent", "true",
           SpellCheckComponent.COMPONENT_NAME, "true",
           SpellCheckComponent.SPELLCHECK_BUILD, "true",
@@ -479,7 +479,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
       assertQ(
         req(
           "q", "teststop:(june AND customs)",
-          "qt", "spellCheckCompRH",
+          "qt", "/spellCheckCompRH",
           "indent", "true",
           SpellCheckComponent.COMPONENT_NAME, "true",
           SpellCheckComponent.SPELLCHECK_DICT, dictionary[i],
@@ -500,8 +500,9 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
         "//lst[@name='spellcheck']/lst[@name='collations']/lst[@name='collation']/lst[@name='misspellingsAndCorrections']/str[@name='june']='jane'"
       );
       //SOLR-5090, alternativeTermCount==0 was being evaluated, sometimes would throw NPE
-      assertQ(req("q", "teststop:(june customs)", "mm", "2", "qt",
-          "spellCheckCompRH", "indent", "true",
+      assertQ(req("q", "teststop:(june customs)", "mm", "2",
+          "qt", "/spellCheckCompRH",
+          "indent", "true",
           SpellCheckComponent.COMPONENT_NAME, "true",
           SpellCheckComponent.SPELLCHECK_DICT, dictionary[i],
           SpellCheckComponent.SPELLCHECK_COUNT, "10",
@@ -522,7 +523,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
        SpellingParams.SPELLCHECK_MAX_COLLATION_TRIES, "1",
        SpellingParams.SPELLCHECK_MAX_COLLATIONS, "1",
        SpellingParams.SPELLCHECK_COLLATE_EXTENDED_RESULTS, "true",          
-       "qt", "spellCheckCompRH");       
+       "qt", "/spellCheckCompRH");
 
     // default case, no SPELLCHECK_COLLATE_MAX_COLLECT_DOCS should be exact num hits
     assertQ(req(reusedParams, 
@@ -589,7 +590,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
     params.add(SpellCheckComponent.SPELLCHECK_MAX_COLLATION_TRIES, "0");
     params.add(SpellCheckComponent.SPELLCHECK_MAX_COLLATIONS, "2");
     params.add(CommonParams.Q, "lowerfilt:(+fauth)");
-    SolrRequestHandler handler = core.getRequestHandler("spellCheckCompRH");
+    SolrRequestHandler handler = core.getRequestHandler("/spellCheckCompRH");
     SolrQueryResponse rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap());
     SolrQueryRequest req = new LocalSolrQueryRequest(core, params);
@@ -618,7 +619,7 @@ public class SpellCheckCollatorTest extends SolrTestCaseJ4 {
     params.add(CommonParams.Q, "lowerfilt:(+fauth)");
     params.add(CommonParams.SORT, "id asc");
     params.add(CursorMarkParams.CURSOR_MARK_PARAM, CursorMarkParams.CURSOR_MARK_START);
-    SolrRequestHandler handler = core.getRequestHandler("spellCheckCompRH");
+    SolrRequestHandler handler = core.getRequestHandler("/spellCheckCompRH");
     SolrQueryResponse rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap());
     SolrQueryRequest req = new LocalSolrQueryRequest(core, params);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test/org/apache/solr/spelling/SpellCheckCollatorWithCollapseTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/spelling/SpellCheckCollatorWithCollapseTest.java b/solr/core/src/test/org/apache/solr/spelling/SpellCheckCollatorWithCollapseTest.java
index f985b41..fe8e787 100644
--- a/solr/core/src/test/org/apache/solr/spelling/SpellCheckCollatorWithCollapseTest.java
+++ b/solr/core/src/test/org/apache/solr/spelling/SpellCheckCollatorWithCollapseTest.java
@@ -57,7 +57,7 @@ public class SpellCheckCollatorWithCollapseTest  extends SolrTestCaseJ4 {
             SpellingParams.SPELLCHECK_MAX_COLLATION_TRIES, "5",
             SpellingParams.SPELLCHECK_MAX_COLLATIONS, "1",
             CommonParams.Q, "a_s:lpve",
-            CommonParams.QT, "spellCheckCompRH_Direct",
+            CommonParams.QT, "/spellCheckCompRH_Direct",
             SpellingParams.SPELLCHECK_COLLATE_MAX_COLLECT_DOCS, "5",
             CommonParams.FQ, "{!collapse field=group_i}",
             "expand", "true"),


[03/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/rangeFacets.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/rangeFacets.xml b/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/rangeFacets.xml
deleted file mode 100644
index 4a596f7..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/rangeFacets.xml
+++ /dev/null
@@ -1,319 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<analyticsRequestEnvelope stats="true" olap="true">
-   <analyticsRequest>
-     <name>regular int</name>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>median(int(int_id))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>count(int(int_id))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(int(int_id))</expression>
-       <name>sumOfSquares</name>
-     </statistic>
-     
-     <rangeFacet hardend="false">
-       <field>long_ld</field>
-       <start>5</start>
-       <end>30</end>
-       <gap>5</gap>
-       <includeBoundary>lower</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="false">
-       <field>double_dd</field>
-       <start>3</start>
-       <end>39</end>
-       <gap>7</gap>
-       <includeBoundary>upper</includeBoundary>
-       <includeBoundary>outer</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="false">
-       <field>date_dtd</field>
-       <start>1007-01-01T23:59:59Z</start>
-       <end>1044-01-01T23:59:59Z</end>
-       <gap>+7YEARS</gap>
-       <includeBoundary>lower</includeBoundary>
-       <includeBoundary>edge</includeBoundary>
-       <includeBoundary>outer</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>regular float</name>
-     
-     <statistic>
-       <expression>mean(float(float_fd))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>sum(float(float_fd))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>median(float(float_fd))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>count(float(float_fd))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(float(float_fd))</expression>
-       <name>sumOfSquares</name>
-     </statistic>
-     
-     <rangeFacet hardend="false">
-       <field>long_ld</field>
-       <start>0</start>
-       <end>29</end>
-       <gap>4</gap>
-       <includeBoundary>all</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="false">
-       <field>double_dd</field>
-       <start>4</start>
-       <end>47</end>
-       <gap>11</gap>
-       <includeBoundary>edge</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="false">
-       <field>date_dtd</field>
-       <start>1004-01-01T23:59:59Z</start>
-       <end>1046-01-01T23:59:59Z</end>
-       <gap>+5YEARS</gap>
-       <includeBoundary>upper</includeBoundary>
-       <includeBoundary>edge</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>hardend int</name>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>median(int(int_id))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>count(int(int_id))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(int(int_id))</expression>
-       <name>sumOfSquares</name>
-     </statistic>
-     
-     <rangeFacet hardend="true">
-       <field>long_ld</field>
-       <start>5</start>
-       <end>30</end>
-       <gap>5</gap>
-       <includeBoundary>lower</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="true">
-       <field>double_dd</field>
-       <start>3</start>
-       <end>39</end>
-       <gap>7</gap>
-       <includeBoundary>upper</includeBoundary>
-       <includeBoundary>outer</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="true">
-       <field>date_dtd</field>
-       <start>1007-01-01T23:59:59Z</start>
-       <end>1044-01-01T23:59:59Z</end>
-       <gap>+7YEARS</gap>
-       <includeBoundary>lower</includeBoundary>
-       <includeBoundary>edge</includeBoundary>
-       <includeBoundary>outer</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>hardend float</name>
-     
-     <statistic>
-       <expression>mean(float(float_fd))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>sum(float(float_fd))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>median(float(float_fd))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>count(float(float_fd))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(float(float_fd))</expression>
-       <name>sumOfSquares</name>
-     </statistic>
-     
-     <rangeFacet hardend="true">
-       <field>long_ld</field>
-       <start>0</start>
-       <end>29</end>
-       <gap>4</gap>
-       <includeBoundary>all</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="true">
-       <field>double_dd</field>
-       <start>4</start>
-       <end>47</end>
-       <gap>11</gap>
-       <includeBoundary>edge</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="true">
-       <field>date_dtd</field>
-       <start>1004-01-01T23:59:59Z</start>
-       <end>1046-01-01T23:59:59Z</end>
-       <gap>+5YEARS</gap>
-       <includeBoundary>upper</includeBoundary>
-       <includeBoundary>edge</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>multigap int</name>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>median(int(int_id))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>count(int(int_id))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(int(int_id))</expression>
-       <name>sumOfSquares</name>
-     </statistic>
-     
-     <rangeFacet hardend="false">
-       <field>long_ld</field>
-       <start>5</start>
-       <end>30</end>
-       <gap>4</gap>
-       <gap>2</gap>
-       <gap>6</gap>
-       <gap>3</gap>
-       <includeBoundary>lower</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="false">
-       <field>double_dd</field>
-       <start>3</start>
-       <end>39</end>
-       <gap>3</gap>
-       <gap>1</gap>
-       <gap>7</gap>
-       <includeBoundary>upper</includeBoundary>
-       <includeBoundary>outer</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="false">
-       <field>date_dtd</field>
-       <start>1007-01-01T23:59:59Z</start>
-       <end>1044-01-01T23:59:59Z</end>
-       <gap>+2YEARS</gap>
-       <gap>+7YEARS</gap>
-       <includeBoundary>lower</includeBoundary>
-       <includeBoundary>edge</includeBoundary>
-       <includeBoundary>outer</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>multigap float</name>
-     
-     <statistic>
-       <expression>mean(float(float_fd))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>sum(float(float_fd))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>median(float(float_fd))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>count(float(float_fd))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(float(float_fd))</expression>
-       <name>sumOfSquares</name>
-     </statistic>
-     
-     <rangeFacet hardend="false">
-       <field>long_ld</field>
-       <start>0</start>
-       <end>29</end>
-       <gap>1</gap>
-       <gap>4</gap>
-       <includeBoundary>all</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="false">
-       <field>double_dd</field>
-       <start>4</start>
-       <end>47</end>
-       <gap>2</gap>
-       <gap>3</gap>
-       <gap>11</gap>
-       <includeBoundary>edge</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-     <rangeFacet hardend="false">
-       <field>date_dtd</field>
-       <start>1004-01-01T23:59:59Z</start>
-       <end>1046-01-01T23:59:59Z</end>
-       <gap>+4YEARS</gap>
-       <gap>+5YEARS</gap>
-       <includeBoundary>upper</includeBoundary>
-       <includeBoundary>edge</includeBoundary>
-       <otherRange>all</otherRange>
-     </rangeFacet>
-   </analyticsRequest>
-</analyticsRequestEnvelope>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/analytics/expressions.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/analytics/expressions.txt b/solr/contrib/analytics/src/test-files/solr/analytics/expressions.txt
new file mode 100644
index 0000000..6f5c916
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/analytics/expressions.txt
@@ -0,0 +1,65 @@
+o.ar.s.sum=sum(int_id)
+o.ar.s.unique=unique(long_ld)
+o.ar.s.su=add(sum(int_id),unique(long_ld))
+o.ar.s.mean=mean(int_id)
+o.ar.s.count=count(long_ld)
+o.ar.s.median=median(int_id)
+o.ar.s.mcm=add(mean(int_id),count(long_ld),median(int_id))
+
+o.mr.s.sum=sum(int_id)
+o.mr.s.unique=unique(long_ld)
+o.mr.s.su=mult(sum(int_id),unique(long_ld))
+o.mr.s.mean=mean(int_id)
+o.mr.s.count=count(long_ld)
+o.mr.s.median=median(int_id)
+o.mr.s.mcm=mult(mean(int_id),count(long_ld),median(int_id))
+
+o.dr.s.sum=sum(int_id)
+o.dr.s.unique=unique(long_ld)
+o.dr.s.su=div(sum(int_id),unique(long_ld))
+o.dr.s.mean=mean(int_id)
+o.dr.s.count=count(long_ld)
+o.dr.s.mc=div(mean(int_id),count(long_ld))
+
+o.pr.s.sum=sum(int_id)
+o.pr.s.unique=unique(long_ld)
+o.pr.s.su=pow(sum(int_id),unique(long_ld))
+o.pr.s.mean=mean(int_id)
+o.pr.s.count=count(long_ld)
+o.pr.s.mc=pow(mean(int_id),count(long_ld))
+
+o.nr.s.sum=sum(int_id)
+o.nr.s.s=neg(sum(int_id))
+o.nr.s.count=count(long_ld)
+o.nr.s.c=neg(count(long_ld))
+
+o.avr.s.sum=sum(int_id)
+o.avr.s.s=abs(neg(sum(int_id)))
+o.avr.s.count=count(long_ld)
+o.avr.s.c=abs(neg(count(long_ld)))
+
+o.cnr.s.c8=8
+o.cnr.s.c10=10.0
+
+o.dmr.s.median=median(date_dtd)
+o.dmr.s.cme="+2YEARS"
+o.dmr.s.dmme=date_math(median(date_dtd),"+2YEARS")
+o.dmr.s.max=max(date_dtd)
+o.dmr.s.cma="+2MONTHS"
+o.dmr.s.dmma=date_math(max(date_dtd),"+2MONTHS")
+
+o.cdr.s.cd1=1800-12-31T23:59:59Z
+o.cdr.s.cs1="1800-12-31T23:59:59Z"
+o.cdr.s.cd2=1804-06-30T23:59:59Z
+o.cdr.s.cs2="1804-06-30T23:59:59Z"
+
+o.csr.s.cs1="this is the first"
+o.csr.s.cs2="this is the second"
+o.csr.s.cs3="this is the third"
+
+o.cr.s.csmin="this is the first"
+o.cr.s.min=min(string_sd)
+o.cr.s.ccmin=concat("this is the first",min(string_sd))
+o.cr.s.csmax="this is the second"
+o.cr.s.max=max(string_sd)
+o.cr.s.ccmax=concat("this is the second",max(string_sd))

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/analytics/facetSorting.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/analytics/facetSorting.txt b/solr/contrib/analytics/src/test-files/solr/analytics/facetSorting.txt
new file mode 100644
index 0000000..4663217
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/analytics/facetSorting.txt
@@ -0,0 +1,4 @@
+o.ar.s.min=min(double_dd)
+o.ar.s.max=max(long_ld)
+o.ar.ff=string_sd
+o.ar.ff.string_sd.sortstatistic=min

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/analytics/fieldFacetExtras.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/analytics/fieldFacetExtras.txt b/solr/contrib/analytics/src/test-files/solr/analytics/fieldFacetExtras.txt
new file mode 100644
index 0000000..3979f57
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/analytics/fieldFacetExtras.txt
@@ -0,0 +1,66 @@
+o.sr.s.mean=mean(int_id)
+o.sr.s.median=median(int_id)
+o.sr.s.count=count(int_id)
+o.sr.s.percentile_20=percentile(20,int_id)
+o.sr.ff=long_ld
+o.sr.ff.long_ld.ss=mean
+o.sr.ff.long_ld.sd=asc
+o.sr.ff=float_fd
+o.sr.ff.float_fd.ss=median
+o.sr.ff.float_fd.sd=desc
+o.sr.ff=double_dd
+o.sr.ff.double_dd.ss=count
+o.sr.ff.double_dd.sd=asc
+o.sr.ff=string_sd
+o.sr.ff.string_sd.ss=percentile_20
+o.sr.ff.string_sd.sd=desc
+
+o.lr.s.mean=mean(int_id)
+o.lr.s.median=median(int_id)
+o.lr.s.count=count(int_id)
+o.lr.s.percentile_20=percentile(20,int_id)
+o.lr.ff=long_ld
+o.lr.ff.long_ld.ss=mean
+o.lr.ff.long_ld.sd=asc
+o.lr.ff.long_ld.limit=5
+o.lr.ff=float_fd
+o.lr.ff.float_fd.ss=median
+o.lr.ff.float_fd.sd=desc
+o.lr.ff.float_fd.limit=3
+o.lr.ff=double_dd
+o.lr.ff.double_dd.ss=count
+o.lr.ff.double_dd.sd=asc
+o.lr.ff.double_dd.limit=7
+o.lr.ff=string_sd
+o.lr.ff.string_sd.ss=percentile_20
+o.lr.ff.string_sd.sd=desc
+o.lr.ff.string_sd.limit=1
+
+
+
+o.offAll.s.mean=mean(int_id)
+o.offAll.ff=long_ld
+o.offAll.ff.long_ld.ss=mean
+o.offAll.ff.long_ld.sd=asc
+o.offAll.ff.long_ld.limit=7
+
+o.off0.s.mean=mean(int_id)
+o.off0.ff=long_ld
+o.off0.ff.long_ld.ss=mean
+o.off0.ff.long_ld.sd=asc
+o.off0.ff.long_ld.limit=2
+o.off0.ff.long_ld.offset=0
+
+o.off1.s.mean=mean(int_id)
+o.off1.ff=long_ld
+o.off1.ff.long_ld.ss=mean
+o.off1.ff.long_ld.sd=asc
+o.off1.ff.long_ld.limit=2
+o.off1.ff.long_ld.offset=2
+
+o.off2.s.mean=mean(int_id)
+o.off2.ff=long_ld
+o.off2.ff.long_ld.ss=mean
+o.off2.ff.long_ld.sd=asc
+o.off2.ff.long_ld.limit=3
+o.off2.ff.long_ld.offset=4

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/analytics/fieldFacets.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/analytics/fieldFacets.txt b/solr/contrib/analytics/src/test-files/solr/analytics/fieldFacets.txt
new file mode 100644
index 0000000..5ba5953
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/analytics/fieldFacets.txt
@@ -0,0 +1,132 @@
+o.sum.s.int=sum(int_id)
+o.sum.s.long=sum(long_ld)
+o.sum.s.float=sum(float_fd)
+o.sum.s.double=sum(double_dd)
+o.sum.ff=string_sd
+o.sum.ff=date_dtd
+
+o.mean.s.int=mean(int_id)
+o.mean.s.long=mean(long_ld)
+o.mean.s.float=mean(float_fd)
+o.mean.s.double=mean(double_dd)
+o.mean.ff=string_sd
+o.mean.ff=date_dtd
+
+o.sumOfSquares.s.int=sumofsquares(int_id)
+o.sumOfSquares.s.long=sumofsquares(long_ld)
+o.sumOfSquares.s.float=sumofsquares(float_fd)
+o.sumOfSquares.s.double=sumofsquares(double_dd)
+o.sumOfSquares.ff=string_sd
+o.sumOfSquares.ff=date_dtd
+
+o.stddev.s.int=stddev(int_id)
+o.stddev.s.long=stddev(long_ld)
+o.stddev.s.float=stddev(float_fd)
+o.stddev.s.double=stddev(double_dd)
+o.stddev.ff=string_sd
+o.stddev.ff=date_dtd
+
+o.median.s.int=median(int_id)
+o.median.s.long=median(long_ld)
+o.median.s.float=median(float_fd)
+o.median.s.double=median(double_dd)
+o.median.ff=string_sd
+o.median.ff=date_dtd
+
+o.percentile_20n.s.int=percentile(20,int_id)
+o.percentile_20n.s.long=percentile(20,long_ld)
+o.percentile_20n.s.float=percentile(20,float_fd)
+o.percentile_20n.s.double=percentile(20,double_dd)
+o.percentile_20n.ff=string_sd
+o.percentile_20n.ff=date_dtd
+
+o.percentile_20.s.str=percentile(20,string_sd)
+o.percentile_20.s.date=percentile(20,date_dtd)
+o.percentile_20.ff=int_id
+o.percentile_20.ff=long_ld
+
+o.percentile_60n.s.int=percentile(60,int_id)
+o.percentile_60n.s.long=percentile(60,long_ld)
+o.percentile_60n.s.float=percentile(60,float_fd)
+o.percentile_60n.s.double=percentile(60,double_dd)
+o.percentile_60n.ff=string_sd
+o.percentile_60n.ff=date_dtd
+
+o.percentile_60.s.str=percentile(60,string_sd)
+o.percentile_60.s.date=percentile(60,date_dtd)
+o.percentile_60.ff=int_id
+o.percentile_60.ff=long_ld
+
+o.minn.s.int=min(int_id)
+o.minn.s.long=min(long_ld)
+o.minn.s.float=min(float_fd)
+o.minn.s.double=min(double_dd)
+o.minn.ff=string_sd
+o.minn.ff=date_dtd
+
+o.min.s.str=min(string_sd)
+o.min.s.date=min(date_dtd)
+o.min.ff=int_id
+o.min.ff=long_ld
+
+o.maxn.s.int=max(int_id)
+o.maxn.s.long=max(long_ld)
+o.maxn.s.float=max(float_fd)
+o.maxn.s.double=max(double_dd)
+o.maxn.ff=string_sd
+o.maxn.ff=date_dtd
+
+o.max.s.str=max(string_sd)
+o.max.s.date=max(date_dtd)
+o.max.ff=int_id
+o.max.ff=long_ld
+
+o.countn.s.int=count(int_id)
+o.countn.s.long=count(long_ld)
+o.countn.s.float=count(float_fd)
+o.countn.s.double=count(double_dd)
+o.countn.ff=string_sd
+o.countn.ff=date_dtd
+
+o.count.s.str=count(string_sd)
+o.count.s.date=count(date_dtd)
+o.count.ff=int_id
+o.count.ff=long_ld
+
+o.uniquen.s.int=unique(int_id)
+o.uniquen.s.long=unique(long_ld)
+o.uniquen.s.float=unique(float_fd)
+o.uniquen.s.double=unique(double_dd)
+o.uniquen.ff=string_sd
+o.uniquen.ff=date_dtd
+
+o.unique.s.str=unique(string_sd)
+o.unique.s.date=unique(date_dtd)
+o.unique.ff=int_id
+o.unique.ff=long_ld
+
+o.missingn.s.int=missing(int_id)
+o.missingn.s.long=missing(long_ld)
+o.missingn.s.float=missing(float_fd)
+o.missingn.s.double=missing(double_dd)
+o.missingn.ff=string_sd
+o.missingn.ff=date_dtd
+
+o.missing.s.str=missing(string_sd)
+o.missing.s.date=missing(date_dtd)
+o.missing.ff=int_id
+o.missing.ff=long_ld
+
+o.multivalued.s.mean=mean(int_id)
+o.multivalued.ff=long_ldm
+o.multivalued.ff=string_sdm
+o.multivalued.ff=date_dtdm
+
+o.missingf.s.mean=mean(int_id)
+o.missingf.ff=date_dtd
+o.missingf.ff.date_dtd.dim=true
+o.missingf.ff=string_sd
+o.missingf.ff.string_sd.dim=true
+o.missingf.ff.string_sd.sm=true
+o.missingf.ff=date_dtdm
+o.missingf.ff.date_dtdm.sm=true

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/analytics/functions.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/analytics/functions.txt b/solr/contrib/analytics/src/test-files/solr/analytics/functions.txt
new file mode 100644
index 0000000..ce73583
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/analytics/functions.txt
@@ -0,0 +1,57 @@
+o.ar.s.sum=sum(add(int_id,float_fd))
+o.ar.s.sumc=sum(add_if_dd)
+o.ar.s.mean=mean(add(long_ld,double_dd,float_fd))
+o.ar.s.meanc=mean(add_ldf_dd)
+
+o.mr.s.sum=sum(mult(int_id,float_fd))
+o.mr.s.sumc=sum(mult_if_dd)
+o.mr.s.mean=mean(mult(long_ld,double_dd,float_fd))
+o.mr.s.meanc=mean(mult_ldf_dd)
+
+o.dr.s.sum=sum(div(int_id,float_fd))
+o.dr.s.sumc=sum(div_if_dd)
+o.dr.s.mean=mean(div(long_ld,double_dd))
+o.dr.s.meanc=mean(div_ld_dd)
+
+o.pr.s.sum=sum(pow(int_id,float_fd))
+o.pr.s.sumc=sum(pow_if_dd)
+o.pr.s.mean=mean(pow(long_ld,double_dd))
+o.pr.s.meanc=mean(pow_ld_dd)
+
+o.nr.s.sum=sum(neg(int_id))
+o.nr.s.sumc=sum(neg_id)
+o.nr.s.mean=mean(neg(long_ld))
+o.nr.s.meanc=mean(neg_ld)
+
+o.avr.s.sum=sum(abs(neg(int_id)))
+o.avr.s.sumc=sum(int_id)
+o.avr.s.mean=mean(abs(neg(int_id)))
+o.avr.s.meanc=mean(int_id)
+
+o.cnr.s.sum=sum(8)
+o.cnr.s.sumc=sum(const_8_dd)
+o.cnr.s.mean=mean(10)
+o.cnr.s.meanc=mean(const_10_dd)
+
+o.dmr.s.median=median(date_math(date_dtd,"+2YEARS"))
+o.dmr.s.medianc=median(dm_2y_dtd)
+o.dmr.s.max=max(date_math(date_dtd,"+2MONTHS"))
+o.dmr.s.maxc=max(dm_2m_dtd)
+
+o.cdr.s.median=median(1800-06-30T23:59:59Z)
+o.cdr.s.medianc=median(const_00_dtd)
+o.cdr.s.max=max(1804-06-30T23:59:59Z)
+o.cdr.s.maxc=max(const_04_dtd)
+
+o.csr.s.min=min("this is the first")
+o.csr.s.minc=min(const_first_sd)
+o.csr.s.max=max("this is the second")
+o.csr.s.maxc=max(const_second_sd)
+
+o.cr.s.min=concat("this is the first",min(string_sd))
+o.cr.s.minc=min(concat_first_sd)
+o.cr.s.max=concat("this is the second",max(string_sd))
+o.cr.s.maxc=max(concat_second_sd)
+
+o.ms.s.min=min(miss_dd)
+o.ms.s.max=max(miss_dd)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/analytics/noFacets.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/analytics/noFacets.txt b/solr/contrib/analytics/src/test-files/solr/analytics/noFacets.txt
new file mode 100644
index 0000000..84e43eb
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/analytics/noFacets.txt
@@ -0,0 +1,74 @@
+o.sr.s.int_id=sum(int_id)
+o.sr.s.long_ld=sum(long_ld)
+o.sr.s.float_fd=sum(float_fd)
+o.sr.s.double_dd=sum(double_dd)
+
+o.sosr.s.int_id=sumofsquares(int_id)
+o.sosr.s.long_ld=sumofsquares(long_ld)
+o.sosr.s.float_fd=sumofsquares(float_fd)
+o.sosr.s.double_dd=sumofsquares(double_dd)
+
+o.mr.s.int_id=mean(int_id)
+o.mr.s.long_ld=mean(long_ld)
+o.mr.s.float_fd=mean(float_fd)
+o.mr.s.double_dd=mean(double_dd)
+
+o.str.s.int_id=stddev(int_id)
+o.str.s.long_ld=stddev(long_ld)
+o.str.s.float_fd=stddev(float_fd)
+o.str.s.double_dd=stddev(double_dd)
+
+o.medr.s.int_id=median(int_id)
+o.medr.s.long_ld=median(long_ld)
+o.medr.s.float_fd=median(float_fd)
+o.medr.s.double_dd=median(double_dd)
+o.medr.s.date_dtd=median(date_dtd)
+
+o.p2r.s.int_id=percentile(20,int_id)
+o.p2r.s.long_ld=percentile(20,long_ld)
+o.p2r.s.float_fd=percentile(20,float_fd)
+o.p2r.s.double_dd=percentile(20,double_dd)
+o.p2r.s.date_dtd=percentile(20,date_dtd)
+o.p2r.s.string_sd=percentile(20,string_sd)
+
+o.p6r.s.int_id=percentile(60,int_id)
+o.p6r.s.long_ld=percentile(60,long_ld)
+o.p6r.s.float_fd=percentile(60,float_fd)
+o.p6r.s.double_dd=percentile(60,double_dd)
+o.p6r.s.date_dtd=percentile(60,date_dtd)
+o.p6r.s.string_sd=percentile(60,string_sd)
+
+o.mir.s.int_id=min(int_id)
+o.mir.s.long_ld=min(long_ld)
+o.mir.s.float_fd=min(float_fd)
+o.mir.s.double_dd=min(double_dd)
+o.mir.s.date_dtd=min(date_dtd)
+o.mir.s.string_sd=min(string_sd)
+
+o.mar.s.int_id=max(int_id)
+o.mar.s.long_ld=max(long_ld)
+o.mar.s.float_fd=max(float_fd)
+o.mar.s.double_dd=max(double_dd)
+o.mar.s.date_dtd=max(date_dtd)
+o.mar.s.string_sd=max(string_sd)
+
+o.cr.s.int_id=count(int_id)
+o.cr.s.long_ld=count(long_ld)
+o.cr.s.float_fd=count(float_fd)
+o.cr.s.double_dd=count(double_dd)
+o.cr.s.date_dtd=count(date_dtd)
+o.cr.s.string_sd=count(string_sd)
+
+o.ur.s.int_id=unique(int_id)
+o.ur.s.long_ld=unique(long_ld)
+o.ur.s.float_fd=unique(float_fd)
+o.ur.s.double_dd=unique(double_dd)
+o.ur.s.date_dtd=unique(date_dtd)
+o.ur.s.string_sd=unique(string_sd)
+
+o.misr.s.int_id=missing(int_id)
+o.misr.s.long_ld=missing(long_ld)
+o.misr.s.float_fd=missing(float_fd)
+o.misr.s.double_dd=missing(double_dd)
+o.misr.s.date_dtd=missing(date_dtd)
+o.misr.s.string_sd=missing(string_sd)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/analytics/queryFacets.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/analytics/queryFacets.txt b/solr/contrib/analytics/src/test-files/solr/analytics/queryFacets.txt
new file mode 100644
index 0000000..84d8fc6
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/analytics/queryFacets.txt
@@ -0,0 +1,27 @@
+o.ir.s.sum=sum(int_id)
+o.ir.s.mean=mean(int_id)
+o.ir.s.median=median(int_id)
+o.ir.s.percentile_8=percentile(8,int_id)
+o.ir.ff=string_sd
+o.ir.ff.string_sd.h=true
+o.ir.qf=float1
+o.ir.qf.float1.q=float_fd:[* TO 50]
+o.ir.qf=float2
+o.ir.qf.float2.q=float_fd:[* TO 30]
+
+o.lr.s.sum=sum(long_ld)
+o.lr.s.mean=mean(long_ld)
+o.lr.s.median=median(long_ld)
+o.lr.s.percentile_8=percentile(8,long_ld)
+o.lr.qf=string
+o.lr.qf.string.q=string_sd:abc1
+o.lr.qf.string.q=string_sd:abc2
+
+o.fr.s.sum=sum(float_fd)
+o.fr.s.mean=mean(float_fd)
+o.fr.s.median=median(float_fd)
+o.fr.s.percentile_8=percentile(8,float_fd)
+o.fr.qf=lad
+o.fr.qf.lad.q=long_ld:[20 TO *]
+o.fr.qf.lad.q=long_ld:[30 TO *]
+o.fr.qf.lad.q=double_dd:[* TO 50]

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/analytics/rangeFacets.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/analytics/rangeFacets.txt b/solr/contrib/analytics/src/test-files/solr/analytics/rangeFacets.txt
new file mode 100644
index 0000000..29aae5d
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/analytics/rangeFacets.txt
@@ -0,0 +1,161 @@
+o.ri.s.sum=sum(int_id)
+o.ri.s.mean=mean(int_id)
+o.ri.s.median=median(int_id)
+o.ri.s.count=count(int_id)
+o.ri.s.sumOfSquares=sumofsquares(int_id)
+o.ri.rf=long_ld
+o.ri.rf.long_ld.st=5
+o.ri.rf.long_ld.e=30
+o.ri.rf.long_ld.g=5
+o.ri.rf.long_ld.ib=lower
+o.ri.rf.long_ld.or=all
+o.ri.rf=double_dd
+o.ri.rf.double_dd.st=3
+o.ri.rf.double_dd.e=39
+o.ri.rf.double_dd.g=7
+o.ri.rf.double_dd.ib=upper
+o.ri.rf.double_dd.ib=outer
+o.ri.rf.double_dd.or=all
+o.ri.rf=date_dtd
+o.ri.rf.date_dtd.st=1007-01-01T23:59:59Z
+o.ri.rf.date_dtd.e=1044-01-01T23:59:59Z
+o.ri.rf.date_dtd.g=+7YEARS
+o.ri.rf.date_dtd.ib=lower
+o.ri.rf.date_dtd.ib=edge
+o.ri.rf.date_dtd.ib=outer
+o.ri.rf.date_dtd.or=all
+
+o.rf.s.sum=sum(float_fd)
+o.rf.s.mean=mean(float_fd)
+o.rf.s.median=median(float_fd)
+o.rf.s.count=count(float_fd)
+o.rf.s.sumOfSquares=sumofsquares(float_fd)
+o.rf.rf=long_ld
+o.rf.rf.long_ld.st=0
+o.rf.rf.long_ld.e=29
+o.rf.rf.long_ld.g=4
+o.rf.rf.long_ld.ib=all
+o.rf.rf.long_ld.or=all
+o.rf.rf=double_dd
+o.rf.rf.double_dd.st=4
+o.rf.rf.double_dd.e=47
+o.rf.rf.double_dd.g=11
+o.rf.rf.double_dd.ib=edge
+o.rf.rf.double_dd.or=all
+o.rf.rf=date_dtd
+o.rf.rf.date_dtd.st=1004-01-01T23:59:59Z
+o.rf.rf.date_dtd.e=1046-01-01T23:59:59Z
+o.rf.rf.date_dtd.g=+5YEARS
+o.rf.rf.date_dtd.ib=upper
+o.rf.rf.date_dtd.ib=edge
+o.rf.rf.date_dtd.or=all
+
+o.hi.s.sum=sum(int_id)
+o.hi.s.mean=mean(int_id)
+o.hi.s.median=median(int_id)
+o.hi.s.count=count(int_id)
+o.hi.s.sumOfSquares=sumofsquares(int_id)
+o.hi.rf=long_ld
+o.hi.rf.long_ld.st=5
+o.hi.rf.long_ld.e=30
+o.hi.rf.long_ld.g=5
+o.hi.rf.long_ld.he=true
+o.hi.rf.long_ld.ib=lower
+o.hi.rf.long_ld.or=all
+o.hi.rf=double_dd
+o.hi.rf.double_dd.st=3
+o.hi.rf.double_dd.e=39
+o.hi.rf.double_dd.g=7
+o.hi.rf.double_dd.he=true
+o.hi.rf.double_dd.ib=upper
+o.hi.rf.double_dd.ib=outer
+o.hi.rf.double_dd.or=all
+o.hi.rf=date_dtd
+o.hi.rf.date_dtd.st=1007-01-01T23:59:59Z
+o.hi.rf.date_dtd.e=1044-01-01T23:59:59Z
+o.hi.rf.date_dtd.g=+7YEARS
+o.hi.rf.date_dtd.he=true
+o.hi.rf.date_dtd.ib=lower
+o.hi.rf.date_dtd.ib=edge
+o.hi.rf.date_dtd.ib=outer
+o.hi.rf.date_dtd.or=all
+
+o.hf.s.sum=sum(float_fd)
+o.hf.s.mean=mean(float_fd)
+o.hf.s.median=median(float_fd)
+o.hf.s.count=count(float_fd)
+o.hf.s.sumOfSquares=sumofsquares(float_fd)
+o.hf.rf=long_ld
+o.hf.rf.long_ld.st=0
+o.hf.rf.long_ld.e=29
+o.hf.rf.long_ld.g=4
+o.hf.rf.long_ld.he=true
+o.hf.rf.long_ld.ib=all
+o.hf.rf.long_ld.or=all
+o.hf.rf=double_dd
+o.hf.rf.double_dd.st=4
+o.hf.rf.double_dd.e=47
+o.hf.rf.double_dd.g=11
+o.hf.rf.double_dd.he=true
+o.hf.rf.double_dd.ib=edge
+o.hf.rf.double_dd.or=all
+o.hf.rf=date_dtd
+o.hf.rf.date_dtd.st=1004-01-01T23:59:59Z
+o.hf.rf.date_dtd.e=1046-01-01T23:59:59Z
+o.hf.rf.date_dtd.g=+5YEARS
+o.hf.rf.date_dtd.he=true
+o.hf.rf.date_dtd.ib=upper
+o.hf.rf.date_dtd.ib=edge
+o.hf.rf.date_dtd.or=all
+
+o.mi.s.sum=sum(int_id)
+o.mi.s.mean=mean(int_id)
+o.mi.s.median=median(int_id)
+o.mi.s.count=count(int_id)
+o.mi.s.sumOfSquares=sumofsquares(int_id)
+o.mi.rf=long_ld
+o.mi.rf.long_ld.st=5
+o.mi.rf.long_ld.e=30
+o.mi.rf.long_ld.g=4,2,6,3
+o.mi.rf.long_ld.ib=lower
+o.mi.rf.long_ld.or=all
+o.mi.rf=double_dd
+o.mi.rf.double_dd.st=3
+o.mi.rf.double_dd.e=39
+o.mi.rf.double_dd.g=3,1,7
+o.mi.rf.double_dd.ib=upper
+o.mi.rf.double_dd.ib=outer
+o.mi.rf.double_dd.or=all
+o.mi.rf=date_dtd
+o.mi.rf.date_dtd.st=1007-01-01T23:59:59Z
+o.mi.rf.date_dtd.e=1044-01-01T23:59:59Z
+o.mi.rf.date_dtd.g=+2YEARS,+7YEARS
+o.mi.rf.date_dtd.ib=lower
+o.mi.rf.date_dtd.ib=edge
+o.mi.rf.date_dtd.ib=outer
+o.mi.rf.date_dtd.or=all
+
+o.mf.s.sum=sum(float_fd)
+o.mf.s.mean=mean(float_fd)
+o.mf.s.median=median(float_fd)
+o.mf.s.count=count(float_fd)
+o.mf.s.sumOfSquares=sumofsquares(float_fd)
+o.mf.rf=long_ld
+o.mf.rf.long_ld.st=0
+o.mf.rf.long_ld.e=29
+o.mf.rf.long_ld.g=1,4
+o.mf.rf.long_ld.ib=all
+o.mf.rf.long_ld.or=all
+o.mf.rf=double_dd
+o.mf.rf.double_dd.st=4
+o.mf.rf.double_dd.e=47
+o.mf.rf.double_dd.g=2,3,11
+o.mf.rf.double_dd.ib=edge
+o.mf.rf.double_dd.or=all
+o.mf.rf=date_dtd
+o.mf.rf.date_dtd.st=1004-01-01T23:59:59Z
+o.mf.rf.date_dtd.e=1046-01-01T23:59:59Z
+o.mf.rf.date_dtd.g=+4YEARS,+5YEARS
+o.mf.rf.date_dtd.ib=upper
+o.mf.rf.date_dtd.ib=edge
+o.mf.rf.date_dtd.or=all

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/collection1/conf/schema-analytics.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/collection1/conf/schema-analytics.xml b/solr/contrib/analytics/src/test-files/solr/collection1/conf/schema-analytics.xml
index 04b22b1..82d408a 100644
--- a/solr/contrib/analytics/src/test-files/solr/collection1/conf/schema-analytics.xml
+++ b/solr/contrib/analytics/src/test-files/solr/collection1/conf/schema-analytics.xml
@@ -25,7 +25,7 @@
 
   -->
 
-<schema name="schema-docValues" version="1.6">
+<schema name="schema-analytics" version="1.0">
 
 
   <!-- field type definitions... note that the "name" attribute is
@@ -54,7 +54,7 @@
   <fieldType name="uuid" class="solr.UUIDField"/>
 
 
-  <field name="id" type="string" required="true"/>
+  <field name="id" type="string" docValues="true" multiValued="false" required="true"/>
 
   <field name="floatdv" type="float" indexed="false" stored="false" docValues="true" default="1"/>
   <field name="intdv" type="int" indexed="false" stored="false" docValues="true" default="2"/>
@@ -63,8 +63,7 @@
   <field name="datedv" type="date" indexed="false" stored="false" docValues="true" default="1995-12-31T23:59:59.999Z"/>
 
   <field name="stringdv" type="string" indexed="false" stored="false" docValues="true" default="solr"/>
-  <field name="stringdvm" type="string" indexed="false" stored="false" docValues="true" default="solr"
-         multiValued="true"/>
+  <field name="stringdvm" type="string" indexed="false" stored="false" docValues="true" default="solr" multiValued="true"/>
 
   <dynamicField name="*_i" type="int" indexed="true" stored="true" docValues="false" multiValued="false"/>
   <dynamicField name="*_id" type="int" indexed="true" stored="true" docValues="true" multiValued="false"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-analytics.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-analytics.xml b/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-analytics.xml
new file mode 100644
index 0000000..31d6437
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-analytics.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<config>
+  <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
+  <dataDir>${solr.data.dir:}</dataDir>
+  <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+  <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
+  <schemaFactory class="ClassicIndexSchemaFactory"/>
+
+  <requestHandler name="standard" class="solr.StandardRequestHandler">
+    <arr name="components">
+      <str>query</str>
+      <str>facet</str>
+      <str>analytics</str>
+      <str>highlight</str>
+      <str>debug</str>
+      <str>expand</str>
+    </arr>
+  </requestHandler>
+
+  <searchComponent name="analytics" class="org.apache.solr.handler.component.AnalyticsComponent" />
+
+  <requestHandler name="/analytics" class="org.apache.solr.handler.AnalyticsHandler" />
+
+</config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-basic.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-basic.xml b/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-basic.xml
deleted file mode 100644
index 604bb17..0000000
--- a/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-basic.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" ?>
-
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements.  See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License.  You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<config>
-  <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
-  <dataDir>${solr.data.dir:}</dataDir>
-  <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-  <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
-  <schemaFactory class="ClassicIndexSchemaFactory"/>
-
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
-    <arr name="components">
-      <str>query</str>
-      <str>facet</str>
-      <str>analytics</str>
-      <str>highlight</str>
-      <str>debug</str>
-      <str>expand</str>
-    </arr>
-  </requestHandler>
-
-  <searchComponent name="analytics" class="org.apache.solr.handler.component.AnalyticsComponent" />
-
-</config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/configsets/cloud-analytics/conf/schema.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/configsets/cloud-analytics/conf/schema.xml b/solr/contrib/analytics/src/test-files/solr/configsets/cloud-analytics/conf/schema.xml
new file mode 100644
index 0000000..d446437
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/configsets/cloud-analytics/conf/schema.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- The Solr schema file for cloud analytics, version 1.0  -->
+
+<schema name="cloud-analytics" version="1.0">
+
+  <fieldType name="int" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="float" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="long" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
+  <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
+
+  <!-- format for date is 1995-12-31T23:59:59.999Z and only the fractional
+       seconds part (.999) is optional.
+    -->
+  <fieldType name="date" class="solr.TrieDateField" sortMissingLast="true" precisionStep="6"/>
+
+
+  <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
+  <field name="signatureField" type="string" indexed="true" stored="false"/>
+
+  <!-- for versioning -->
+  <field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/>
+  <!-- points to the root document of a block of nested documents -->
+  <field name="_root_" type="string" indexed="true" stored="true"/>
+
+  <field name="_route_" type="string" indexed="true" stored="true" multiValued="false"/>
+
+  <!-- dynamic fields with doc-values (for analytics) -->
+  <dynamicField name="*_id"  type="int" docValues="true"    indexed="true"  stored="true"/>
+  <dynamicField name="*_idm" type="int" docValues="true"    indexed="true"  stored="true"  multiValued="true"/>
+  <dynamicField name="*_sd"  type="string" docValues="true"  indexed="true"  stored="true" />
+  <dynamicField name="*_sdm" type="string" docValues="true"  indexed="true"  stored="true" multiValued="true"/>
+  <dynamicField name="*_ld"  type="long" docValues="true"   indexed="true"  stored="true"/>
+  <dynamicField name="*_ldm" type="long" docValues="true"   indexed="true"  stored="true"  multiValued="true"/>
+  <dynamicField name="*_bd"  type="boolean" docValues="true" indexed="true" stored="true"/>
+  <dynamicField name="*_bdm" type="boolean" docValues="true" indexed="true" stored="true"  multiValued="true"/>
+  <dynamicField name="*_fd"  type="float" docValues="true"  indexed="true"  stored="true"/>
+  <dynamicField name="*_fdm" type="float" docValues="true"  indexed="true"  stored="true"  multiValued="true"/>
+  <dynamicField name="*_dd"  type="double" docValues="true" indexed="true"  stored="true"/>
+  <dynamicField name="*_ddm" type="double" docValues="true" indexed="true"  stored="true"  multiValued="true"/>
+  <dynamicField name="*_dtd"  type="date" docValues="true" indexed="true"  stored="true"/>
+  <dynamicField name="*_dtdm" type="date" docValues="true" indexed="true"  stored="true"  multiValued="true"/>
+
+  <uniqueKey>id</uniqueKey>
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/solr/configsets/cloud-analytics/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/configsets/cloud-analytics/conf/solrconfig.xml b/solr/contrib/analytics/src/test-files/solr/configsets/cloud-analytics/conf/solrconfig.xml
new file mode 100644
index 0000000..102e39e
--- /dev/null
+++ b/solr/contrib/analytics/src/test-files/solr/configsets/cloud-analytics/conf/solrconfig.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" ?>
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Minimal solrconfig.xml with /select, /admin and /update only -->
+
+<config>
+
+  <dataDir>${solr.data.dir:}</dataDir>
+
+  <directoryFactory name="DirectoryFactory"
+                    class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
+  <schemaFactory class="ClassicIndexSchemaFactory"/>
+
+  <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
+
+  <updateHandler class="solr.DirectUpdateHandler2">
+    <commitWithin>
+      <softCommit>${solr.commitwithin.softcommit:true}</softCommit>
+    </commitWithin>
+    <updateLog></updateLog>
+  </updateHandler>
+
+  <requestHandler name="/select" class="solr.SearchHandler">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+      <str name="indent">true</str>
+      <str name="df">text</str>
+    </lst>
+
+    <arr name="components">
+      <str>query</str>
+      <str>facet</str>
+      <str>analytics</str>
+      <str>highlight</str>
+      <str>debug</str>
+      <str>expand</str>
+    </arr>
+  </requestHandler>
+
+  <searchComponent name="analytics" class="org.apache.solr.handler.component.AnalyticsComponent" />
+  <requestHandler name="/analytics" class="org.apache.solr.handler.AnalyticsHandler" />
+</config>
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/AbstractAnalyticsStatsCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/AbstractAnalyticsStatsCloudTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/AbstractAnalyticsStatsCloudTest.java
new file mode 100644
index 0000000..59ebbcb
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/AbstractAnalyticsStatsCloudTest.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
+import org.apache.solr.analytics.util.MedianCalculator;
+import org.apache.solr.analytics.util.OrdinalCalculator;
+import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.cloud.AbstractDistribZkTestBase;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.junit.AfterClass;
+
+public class AbstractAnalyticsStatsCloudTest extends SolrCloudTestCase {
+  
+  protected static final String[] BASEPARMS = new String[]{ "q", "*:*", "indent", "true", "olap", "true", "rows", "0" };
+  protected static final HashMap<String,Object> defaults = new HashMap<>();
+
+  public static enum VAL_TYPE {
+    INTEGER("int"),
+    LONG("long"),
+    FLOAT("float"),
+    DOUBLE("double"),
+    STRING("str"),
+    DATE("date");
+
+    private VAL_TYPE (final String text) {
+      this.text = text;
+    }
+
+    private final String text;
+
+    @Override
+    public String toString() {
+      return text;
+    }
+  }
+  
+
+
+  protected static final String COLLECTIONORALIAS = "collection1";
+  protected static final int TIMEOUT = DEFAULT_TIMEOUT;
+  protected static final String id = "id";
+
+  public static void setupCluster() throws Exception {
+    configureCluster(4)
+        .addConfig("conf", configset("cloud-analytics"))
+        .configure();
+
+    CollectionAdminRequest.createCollection(COLLECTIONORALIAS, "conf", 2, 1).process(cluster.getSolrClient());
+    AbstractDistribZkTestBase.waitForRecoveriesToFinish(COLLECTIONORALIAS, cluster.getSolrClient().getZkStateReader(),
+        false, true, TIMEOUT);
+    cleanIndex();
+  }
+
+  public static void cleanIndex() throws Exception {
+    new UpdateRequest()
+        .deleteByQuery("*:*")
+        .commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+  }
+  
+  @AfterClass
+  public static void afterClassAbstractAnalysis() {
+    defaults.clear();
+  }
+
+  protected NamedList<Object> queryCloudAnalytics(String[] testParams) throws SolrServerException, IOException, InterruptedException {
+    ModifiableSolrParams params = new ModifiableSolrParams();
+    params.set("q", "*:*");
+    params.set("indent", "true");
+    params.set("olap", "true");
+    params.set("rows", "0");
+    for (int i = 0; i + 1 < testParams.length;) {
+      params.set(testParams[i++], testParams[i++]);
+    }
+    cluster.waitForAllNodes(10000);
+    QueryRequest qreq = new QueryRequest(params);
+    QueryResponse resp = qreq.process(cluster.getSolrClient(), COLLECTIONORALIAS);
+    return resp.getResponse();
+  }
+  
+  @SuppressWarnings("unchecked")
+  protected <T> T getValue(NamedList<Object> response, String infoName, String exprName) {
+    return (T)response.findRecursive(AnalyticsResponseHeadings.COMPLETED_OLD_HEADER,
+                                     infoName,
+                                     exprName);
+  }
+
+  public <T extends Number & Comparable<T>> Double calculateNumberStat(ArrayList<T> list, String stat) {
+    Double result;
+    if (stat.equals("median")) {
+      result = MedianCalculator.getMedian(list);
+    } else if (stat.equals("mean")) {
+      double d = 0;
+      for (T element : list) {
+        d += element.doubleValue();
+      }
+      result = Double.valueOf(d/list.size());
+    } else if (stat.equals("sum")) {
+      double d = 0;
+      for (T element : list) {
+        d += element.doubleValue();
+      }
+      result = Double.valueOf(d);
+    } else if (stat.equals("sumOfSquares")) {
+      double d = 0;
+      for (T element : list) {
+        d += element.doubleValue()*element.doubleValue();
+      }
+      result = Double.valueOf(d);
+    } else if (stat.equals("stddev")) {
+      double sum = 0;
+      double sumSquares = 0;
+      for (T element : list) {
+        sum += element.doubleValue();
+        sumSquares += element.doubleValue()*element.doubleValue();
+      }
+      result = Math.sqrt(sumSquares/list.size()-sum*sum/(list.size()*list.size()));
+    } else {
+      throw new IllegalArgumentException();
+    }
+    return result;
+  }
+
+  public <T extends Comparable<T>> Object calculateStat(ArrayList<T> list, String stat) {
+    Object result;
+    if (stat.contains("perc_")) {
+      ArrayList<Integer> percs = new ArrayList<>(1);
+      int ord = (int) Math.ceil(Double.parseDouble(stat.substring(5))/100 * list.size()) - 1;
+      percs.add(ord);
+      OrdinalCalculator.putOrdinalsInPosition(list, percs);
+      result = list.get(percs.get(0));
+    } else if (stat.equals("count")) {
+      result = Long.valueOf(list.size());
+    } else if (stat.equals("unique")) {
+      HashSet<T> set = new HashSet<>();
+      set.addAll(list);
+      result = Long.valueOf((long)set.size());
+    } else if (stat.equals("max")) {
+      Collections.sort(list);
+      result = list.get(list.size()-1);
+    } else if (stat.equals("min")) {
+      Collections.sort(list);
+      result = list.get(0);
+    } else {
+      result = null;
+    }
+    return result;
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T extends Comparable<T>> Long calculateMissing(ArrayList<T> list, String type) {
+    T def = (T)defaults.get(type);
+    long miss = 0;
+    for (T element : list) {
+      if (element.compareTo(def)==0) {
+        miss++;
+      }
+    }
+    return Long.valueOf(miss);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/AbstractAnalyticsStatsTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/AbstractAnalyticsStatsTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/AbstractAnalyticsStatsTest.java
index c3d2f28..18f51a9 100644
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/AbstractAnalyticsStatsTest.java
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/AbstractAnalyticsStatsTest.java
@@ -37,8 +37,9 @@ import javax.xml.xpath.XPathFactory;
 import org.apache.commons.lang.StringUtils;
 import org.apache.lucene.util.IOUtils;
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
 import org.apache.solr.analytics.util.MedianCalculator;
-import org.apache.solr.analytics.util.PercentileCalculator;
+import org.apache.solr.analytics.util.OrdinalCalculator;
 import org.apache.solr.request.SolrQueryRequest;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
@@ -107,7 +108,7 @@ public class AbstractAnalyticsStatsTest extends SolrTestCaseJ4 {
   public Object getStatResult(String section, String name, VAL_TYPE type) throws XPathExpressionException {
 
     // Construct the XPath expression. The form better not change or all these will fail.
-    StringBuilder sb = new StringBuilder("/response/lst[@name='stats']/lst[@name='").append(section).append("']");
+    StringBuilder sb = new StringBuilder("/response/lst[@name='"+AnalyticsResponseHeadings.COMPLETED_OLD_HEADER+"']/lst[@name='").append(section).append("']");
 
     // This is a little fragile in that it demands the elements have the same name as type, i.e. when looking for a
     // VAL_TYPE.DOUBLE, the element in question is <double name="blah">47.0</double>.
@@ -170,8 +171,11 @@ public class AbstractAnalyticsStatsTest extends SolrTestCaseJ4 {
   public <T extends Comparable<T>> Object calculateStat(ArrayList<T> list, String stat) {
     Object result;
     if (stat.contains("perc_")) {
-      double[] perc = new double[]{Double.parseDouble(stat.substring(5))/100};
-      result = PercentileCalculator.getPercentiles(list, perc).get(0);
+      ArrayList<Integer> percs = new ArrayList<>(1);
+      int ord = (int) Math.ceil(Double.parseDouble(stat.substring(5))/100 * list.size()) - 1;
+      percs.add(ord);
+      OrdinalCalculator.putOrdinalsInPosition(list, percs);
+      result = list.get(percs.get(0));
     } else if (stat.equals("count")) {
       result = Long.valueOf(list.size());
     } else if (stat.equals("unique")) {
@@ -207,7 +211,7 @@ public class AbstractAnalyticsStatsTest extends SolrTestCaseJ4 {
   }
 
   public static String[] fileToStringArr(Class<?> clazz, String fileName) throws FileNotFoundException {
-    InputStream in = clazz.getResourceAsStream(fileName);
+    InputStream in = clazz.getResourceAsStream("/solr/analytics/" + fileName);
     if (in == null) throw new FileNotFoundException("Resource not found: " + fileName);
     Scanner file = new Scanner(in, "UTF-8");
     try { 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/NoFacetCloudTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/NoFacetCloudTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/NoFacetCloudTest.java
new file mode 100644
index 0000000..71503af
--- /dev/null
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/NoFacetCloudTest.java
@@ -0,0 +1,557 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.common.util.NamedList;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class NoFacetCloudTest extends AbstractAnalyticsStatsCloudTest {
+  static public final int INT = 71;
+  static public final int LONG = 36;
+  static public final int FLOAT = 93;
+  static public final int DOUBLE = 49;
+  static public final int DATE = 12;
+  static public final int STRING = 28;
+  static public final int NUM_LOOPS = 100;
+  
+  //INT
+  static ArrayList<Integer> intTestStart; 
+  static long intMissing = 0;
+  
+  //LONG
+  static ArrayList<Long> longTestStart; 
+  static long longMissing = 0;
+  
+  //FLOAT
+  static ArrayList<Float> floatTestStart; 
+  static long floatMissing = 0;
+  
+  //DOUBLE
+  static ArrayList<Double> doubleTestStart; 
+  static long doubleMissing = 0;
+  
+  //DATE
+  static ArrayList<String> dateTestStart; 
+  static long dateMissing = 0;
+  
+  //STR
+  static ArrayList<String> stringTestStart; 
+  static long stringMissing = 0;
+  
+  @BeforeClass
+  public static void populate() throws Exception {
+    setupCluster();
+    defaults.put("int_id", new Integer(0));
+    defaults.put("long_ld", new Long(0));
+    defaults.put("float_fd", new Float(0));
+    defaults.put("double_dd", new Double(0));
+    defaults.put("date_dtd", "1800-12-31T23:59:59Z");
+    defaults.put("string_sd", "str0");
+    
+    intTestStart = new ArrayList<>();
+    longTestStart = new ArrayList<>();
+    floatTestStart = new ArrayList<>();
+    doubleTestStart = new ArrayList<>();
+    dateTestStart = new ArrayList<>();
+    stringTestStart = new ArrayList<>();
+    
+    UpdateRequest req = new UpdateRequest();
+    for (int j = 0; j < NUM_LOOPS; ++j) {
+      int i = j%INT;
+      long l = j%LONG;
+      float f = j%FLOAT;
+      double d = j%DOUBLE;
+      String dt = (1800+j%DATE) + "-12-31T23:59:59Z";
+      String s = "str" + (j%STRING);
+      List<String> fields = new ArrayList<>();
+      fields.add("id"); fields.add("1000"+j);
+      
+      if( i != 0 ){
+        fields.add("int_id"); fields.add("" + i);
+        intTestStart.add(i);
+      } else intMissing++;
+      
+      if( l != 0l ){
+        fields.add("long_ld"); fields.add("" + l);
+        longTestStart.add(l);
+      } else longMissing++;
+      
+      if( f != 0.0f ){
+        fields.add("float_fd"); fields.add("" + f);
+        floatTestStart.add(f);
+      } else floatMissing++;
+      
+      if( d != 0.0d ){
+        fields.add("double_dd"); fields.add("" + d);
+        doubleTestStart.add(d);
+      } else doubleMissing++;
+      
+      if( (j%DATE) != 0 ){
+        fields.add("date_dtd"); fields.add(dt);
+        dateTestStart.add(dt);
+      } else dateMissing++;
+      
+      if( (j%STRING) != 0 ){
+        fields.add("string_sd"); fields.add(s);
+        stringTestStart.add(s);
+      } else stringMissing++;
+
+      req.add(fields.toArray(new String[0]));
+    }
+    req.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
+  }
+      
+  @Test
+  public void sumTest() throws Exception {
+    String[] params = new String[] {
+        "o.sr.s.int_id", "sum(int_id)",
+        "o.sr.s.long_ld", "sum(long_ld)",
+        "o.sr.s.float_fd", "sum(float_fd)",
+        "o.sr.s.double_dd", "sum(double_dd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int
+    Double intResult = getValue(response, "sr", "int_id");
+    Double intTest = (Double)calculateNumberStat(intTestStart, "sum");
+    assertEquals(responseStr, intResult,intTest);
+    
+    //Long
+    Double longResult = getValue(response, "sr", "long_ld");
+    Double longTest = (Double)calculateNumberStat(longTestStart, "sum");
+    assertEquals(responseStr, longResult,longTest);
+    
+    //Float
+    Double floatResult = getValue(response, "sr", "float_fd");
+    Double floatTest = (Double)calculateNumberStat(floatTestStart, "sum");
+    assertEquals(responseStr, floatResult,floatTest);
+    
+    //Double
+    Double doubleResult = getValue(response, "sr", "double_dd");
+        Double doubleTest = (Double) calculateNumberStat(doubleTestStart, "sum");
+    assertEquals(responseStr, doubleResult,doubleTest);
+  }
+  
+  @Test
+  public void meanTest() throws Exception { 
+    String[] params = new String[] {
+        "o.mr.s.int_id", "mean(int_id)",
+        "o.mr.s.long_ld", "mean(long_ld)",
+        "o.mr.s.float_fd", "mean(float_fd)",
+        "o.mr.s.double_dd", "mean(double_dd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int
+    Double intResult = getValue(response, "mr", "int_id");
+    Double intTest = (Double)calculateNumberStat(intTestStart, "mean");
+    assertEquals(responseStr, intResult,intTest);
+    
+    //Long
+    Double longResult = getValue(response, "mr", "long_ld");
+    Double longTest = (Double)calculateNumberStat(longTestStart, "mean");
+    assertEquals(responseStr, longResult,longTest);
+    
+    //Float
+    Double floatResult = getValue(response, "mr", "float_fd");
+    Double floatTest = (Double)calculateNumberStat(floatTestStart, "mean");
+    assertEquals(responseStr, floatResult,floatTest);
+    
+    //Double
+    Double doubleResult = getValue(response, "mr", "double_dd");
+    Double doubleTest = (Double)calculateNumberStat(doubleTestStart, "mean");
+    assertEquals(responseStr, doubleResult,doubleTest);
+  }
+  
+  @Test
+  public void stddevTest() throws Exception { 
+    String[] params = new String[] {
+        "o.str.s.int_id", "stddev(int_id)",
+        "o.str.s.long_ld", "stddev(long_ld)",
+        "o.str.s.float_fd", "stddev(float_fd)",
+        "o.str.s.double_dd", "stddev(double_dd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int
+    Double intResult = getValue(response, "str", "int_id");
+    Double intTest = (Double)calculateNumberStat(intTestStart, "stddev");
+    assertEquals(responseStr, intResult, intTest, 0.00000000001);
+    
+    //Long
+    Double longResult = getValue(response, "str", "long_ld");
+    Double longTest = (Double)calculateNumberStat(longTestStart, "stddev");
+    assertEquals(responseStr, longResult, longTest, 0.00000000001);
+    
+    //Float
+    Double floatResult = getValue(response, "str", "float_fd");
+    Double floatTest = (Double)calculateNumberStat(floatTestStart, "stddev");
+    assertEquals(responseStr, floatResult, floatTest, 0.00000000001);
+
+
+    //Double
+    Double doubleResult = getValue(response, "str", "double_dd");
+    Double doubleTest = (Double)calculateNumberStat(doubleTestStart, "stddev");
+    assertEquals(responseStr, doubleResult, doubleTest, 0.00000000001);
+  }
+  
+  @Test
+  public void medianTest() throws Exception { 
+    String[] params = new String[] {
+        "o.medr.s.int_id", "median(int_id)",
+        "o.medr.s.long_ld", "median(long_ld)",
+        "o.medr.s.float_fd", "median(float_fd)",
+        "o.medr.s.double_dd", "median(double_dd)",
+        "o.medr.s.date_dtd", "median(date_dtd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int
+    Double intResult = getValue(response, "medr", "int_id");
+    Double intTest = (Double)calculateNumberStat(intTestStart, "median");
+    assertEquals(responseStr, intResult,intTest);
+    
+    //Long
+    Double longResult = getValue(response, "medr", "long_ld");
+    Double longTest = (Double)calculateNumberStat(longTestStart, "median");
+    assertEquals(responseStr, longResult,longTest);
+    
+    //Float
+    Double floatResult = getValue(response, "medr", "float_fd");
+    Double floatTest = (Double)calculateNumberStat(floatTestStart, "median");
+    assertEquals(responseStr, floatResult,floatTest);
+    
+    //Double
+    Double doubleResult = getValue(response, "medr", "double_dd");
+    Double doubleTest = (Double)calculateNumberStat(doubleTestStart, "median");
+    assertEquals(responseStr, doubleResult,doubleTest);
+    
+    // TODO: Add test for date median
+  }
+  
+  @Test
+  public void perc20Test() throws Exception {
+    String[] params = new String[] {
+        "o.p2r.s.int_id", "percentile(20,int_id)",
+        "o.p2r.s.long_ld", "percentile(20,long_ld)",
+        "o.p2r.s.float_fd", "percentile(20,float_fd)",
+        "o.p2r.s.double_dd", "percentile(20,double_dd)",
+        "o.p2r.s.date_dtd", "string(percentile(20,date_dtd))",
+        "o.p2r.s.string_sd", "percentile(20,string_sd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int 20
+    Integer intResult = getValue(response, "p2r", "int_id");
+    Integer intTest = (Integer)calculateStat(intTestStart, "perc_20");
+    assertEquals(responseStr, intResult,intTest);
+
+    //Long 20
+    Long longResult = getValue(response, "p2r", "long_ld");
+    Long longTest = (Long)calculateStat(longTestStart, "perc_20");
+    assertEquals(responseStr, longResult,longTest);
+
+    //Float 20
+    Float floatResult = getValue(response, "p2r", "float_fd");
+    Float floatTest = (Float)calculateStat(floatTestStart, "perc_20");
+    assertEquals(responseStr, floatResult,floatTest);
+
+    //Double 20
+    Double doubleResult = getValue(response, "p2r", "double_dd");
+    Double doubleTest = (Double)calculateStat(doubleTestStart, "perc_20");
+    assertEquals(responseStr, doubleResult,doubleTest);
+
+    //Date 20
+    String dateResult = getValue(response, "p2r", "date_dtd");
+    String dateTest = (String)calculateStat(dateTestStart, "perc_20");
+    assertEquals(responseStr, dateResult,dateTest);
+
+    //String 20
+    String stringResult = getValue(response, "p2r", "string_sd");
+    String stringTest = (String)calculateStat(stringTestStart, "perc_20");
+    assertEquals(responseStr, stringResult,stringTest);
+  }
+  
+  @Test
+  public void perc60Test() throws Exception { 
+    String[] params = new String[] {
+        "o.p6r.s.int_id", "percentile(60,int_id)",
+        "o.p6r.s.long_ld", "percentile(60,long_ld)",
+        "o.p6r.s.float_fd", "percentile(60,float_fd)",
+        "o.p6r.s.double_dd", "percentile(60,double_dd)",
+        "o.p6r.s.date_dtd", "string(percentile(60,date_dtd))",
+        "o.p6r.s.string_sd", "percentile(60,string_sd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int 60
+    Integer intResult = getValue(response, "p6r", "int_id");
+    Integer intTest = (Integer)calculateStat(intTestStart, "perc_60");
+    assertEquals(responseStr, intResult,intTest);
+
+    //Long 60
+    Long longResult = getValue(response, "p6r", "long_ld");
+    Long longTest = (Long)calculateStat(longTestStart, "perc_60");
+    assertEquals(responseStr, longResult,longTest);
+
+    //Float 60
+    Float floatResult = getValue(response, "p6r", "float_fd");
+    Float floatTest = (Float)calculateStat(floatTestStart, "perc_60");
+    assertEquals(responseStr, floatResult,floatTest);
+
+    //Double 60
+    Double doubleResult = getValue(response, "p6r", "double_dd");
+    Double doubleTest = (Double)calculateStat(doubleTestStart, "perc_60");
+    assertEquals(responseStr, doubleResult,doubleTest);
+
+    //Date 60
+    String dateResult = getValue(response, "p6r", "date_dtd");
+    String dateTest = (String)calculateStat(dateTestStart, "perc_60");
+    assertEquals(responseStr, dateResult,dateTest);
+
+    //String 60
+    String stringResult = getValue(response, "p6r", "string_sd");
+    String stringTest = (String)calculateStat(stringTestStart, "perc_60");
+    assertEquals(responseStr, stringResult,stringTest);
+  }
+  
+  @Test
+  public void minTest() throws Exception { 
+    String[] params = new String[] {
+        "o.mir.s.int_id", "min(int_id)",
+        "o.mir.s.long_ld", "min(long_ld)",
+        "o.mir.s.float_fd", "min(float_fd)",
+        "o.mir.s.double_dd", "min(double_dd)",
+        "o.mir.s.date_dtd", "string(min(date_dtd))",
+        "o.mir.s.string_sd", "min(string_sd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int
+    Integer intResult = getValue(response, "mir", "int_id");
+    Integer intTest = (Integer)calculateStat(intTestStart, "min");
+    assertEquals(responseStr, intResult,intTest);
+
+    //Long
+    Long longResult = getValue(response, "mir", "long_ld");
+    Long longTest = (Long)calculateStat(longTestStart, "min");
+    assertEquals(responseStr, longResult,longTest);
+
+    //Float
+    Float floatResult = getValue(response, "mir", "float_fd");
+    Float floatTest = (Float)calculateStat(floatTestStart, "min");
+    assertEquals(responseStr, floatResult,floatTest);
+
+    //Double
+    Double doubleResult = getValue(response, "mir", "double_dd");
+    Double doubleTest = (Double)calculateStat(doubleTestStart, "min");
+    assertEquals(responseStr, doubleResult,doubleTest);
+
+    //Date
+    String dateResult = getValue(response, "mir", "date_dtd");
+    String dateTest = (String)calculateStat(dateTestStart, "min");
+    assertEquals(responseStr, dateResult,dateTest);
+
+    //String
+    String stringResult = getValue(response, "mir", "string_sd");
+    String stringTest = (String)calculateStat(stringTestStart, "min");
+    assertEquals(responseStr, stringResult,stringTest);
+  }
+  
+  @Test
+  public void maxTest() throws Exception { 
+    String[] params = new String[] {
+        "o.mar.s.int_id", "max(int_id)",
+        "o.mar.s.long_ld", "max(long_ld)",
+        "o.mar.s.float_fd", "max(float_fd)",
+        "o.mar.s.double_dd", "max(double_dd)",
+        "o.mar.s.date_dtd", "string(max(date_dtd))",
+        "o.mar.s.string_sd", "max(string_sd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int
+    Integer intResult = getValue(response, "mar", "int_id");
+    Integer intTest = (Integer)calculateStat(intTestStart, "max");
+    assertEquals(responseStr, intResult,intTest);
+
+    //Long
+    Long longResult = getValue(response, "mar", "long_ld");
+    Long longTest = (Long)calculateStat(longTestStart, "max");
+    assertEquals(responseStr, longResult,longTest);
+
+    //Float
+    Float floatResult = getValue(response, "mar", "float_fd");
+    Float floatTest = (Float)calculateStat(floatTestStart, "max");
+    assertEquals(responseStr, floatResult,floatTest);
+
+    //Double
+    Double doubleResult = getValue(response, "mar", "double_dd");
+    Double doubleTest = (Double)calculateStat(doubleTestStart, "max");
+    assertEquals(responseStr, doubleResult,doubleTest);
+
+    //Date
+    String dateResult = getValue(response, "mar", "date_dtd");
+    String dateTest = (String)calculateStat(dateTestStart, "max");
+    assertEquals(responseStr, dateResult,dateTest);
+
+    //String
+    String stringResult = getValue(response, "mar", "string_sd");
+    String stringTest = (String)calculateStat(stringTestStart, "max");
+    assertEquals(responseStr, stringResult,stringTest);
+  }
+  
+  @Test
+  public void uniqueTest() throws Exception { 
+    String[] params = new String[] {
+        "o.ur.s.int_id", "unique(int_id)",
+        "o.ur.s.long_ld", "unique(long_ld)",
+        "o.ur.s.float_fd", "unique(float_fd)",
+        "o.ur.s.double_dd", "unique(double_dd)",
+        "o.ur.s.date_dtd", "unique(date_dtd)",
+        "o.ur.s.string_sd", "unique(string_sd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int
+    Long intResult = getValue(response, "ur", "int_id");
+    Long intTest = (Long)calculateStat(intTestStart, "unique");
+    assertEquals(responseStr, intResult,intTest);
+
+    //Long
+    Long longResult = getValue(response, "ur", "long_ld");
+    Long longTest = (Long)calculateStat(longTestStart, "unique");
+    assertEquals(responseStr, longResult,longTest);
+
+    //Float
+    Long floatResult = getValue(response, "ur", "float_fd");
+    Long floatTest = (Long)calculateStat(floatTestStart, "unique");
+    assertEquals(responseStr, floatResult,floatTest);
+
+    //Double
+    Long doubleResult = getValue(response, "ur", "double_dd");
+    Long doubleTest = (Long)calculateStat(doubleTestStart, "unique");
+    assertEquals(responseStr, doubleResult,doubleTest);
+
+    //Date
+    Long dateResult = getValue(response, "ur", "date_dtd");
+    Long dateTest = (Long)calculateStat(dateTestStart, "unique");
+    assertEquals(responseStr, dateResult,dateTest);
+
+    //String
+    Long stringResult = getValue(response, "ur", "string_sd");
+    Long stringTest = (Long)calculateStat(stringTestStart, "unique");
+    assertEquals(responseStr, stringResult,stringTest);
+  }
+  
+  @Test
+  public void countTest() throws Exception { 
+    String[] params = new String[] {
+        "o.cr.s.int_id", "count(int_id)",
+        "o.cr.s.long_ld", "count(long_ld)",
+        "o.cr.s.float_fd", "count(float_fd)",
+        "o.cr.s.double_dd", "count(double_dd)",
+        "o.cr.s.date_dtd", "count(date_dtd)",
+        "o.cr.s.string_sd", "count(string_sd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int
+    Long intResult = getValue(response, "cr", "int_id");
+    Long intTest = (Long)calculateStat(intTestStart, "count");
+    assertEquals(responseStr, intResult,intTest);
+
+    //Long
+    Long longResult = getValue(response, "cr", "long_ld");
+    Long longTest = (Long)calculateStat(longTestStart, "count");
+    assertEquals(responseStr, longResult,longTest);
+
+    //Float
+    Long floatResult = getValue(response, "cr", "float_fd");
+    Long floatTest = (Long)calculateStat(floatTestStart, "count");
+    assertEquals(responseStr, floatResult,floatTest);
+
+    //Double
+    Long doubleResult = getValue(response, "cr", "double_dd");
+    Long doubleTest = (Long)calculateStat(doubleTestStart, "count");
+    assertEquals(responseStr, doubleResult,doubleTest);
+
+    //Date
+    Long dateResult = getValue(response, "cr", "date_dtd");
+    Long dateTest = (Long)calculateStat(dateTestStart, "count");
+    assertEquals(responseStr, dateResult,dateTest);
+
+    //String
+    Long stringResult = getValue(response, "cr", "string_sd");
+    Long stringTest = (Long)calculateStat(stringTestStart, "count");
+    assertEquals(responseStr, stringResult,stringTest);
+  }  
+    
+  @Test
+  public void missingDefaultTest() throws Exception { 
+    String[] params = new String[] {
+        "o.misr.s.int_id", "missing(int_id)",
+        "o.misr.s.long_ld", "missing(long_ld)",
+        "o.misr.s.float_fd", "missing(float_fd)",
+        "o.misr.s.double_dd", "missing(double_dd)",
+        "o.misr.s.date_dtd", "missing(date_dtd)",
+        "o.misr.s.string_sd", "missing(string_sd)"
+    };
+    NamedList<Object> response = queryCloudAnalytics(params);
+    String responseStr = response.toString();
+    
+    //Int
+    long intResult = getValue(response, "misr", "int_id");
+    assertEquals(responseStr, intMissing,intResult);
+
+    //Long
+    long longResult = getValue(response, "misr", "long_ld");
+    assertEquals(responseStr, longMissing,longResult);
+
+    //Float
+    long floatResult = getValue(response, "misr", "float_fd");
+    assertEquals(responseStr, floatMissing,floatResult);
+
+    //Double
+    long doubleResult = getValue(response, "misr", "double_dd");
+    assertEquals(responseStr, doubleMissing,doubleResult);
+
+    //Date
+    long dateResult = getValue(response, "misr", "date_dtd");
+    assertEquals(responseStr, dateMissing,dateResult);
+
+    //String
+    long stringResult = getValue(response, "misr", "string_sd");
+    assertEquals(responseStr, stringMissing, stringResult);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/NoFacetTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/NoFacetTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/NoFacetTest.java
index f4d6275..cfd1176 100644
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/NoFacetTest.java
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/NoFacetTest.java
@@ -23,7 +23,7 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class NoFacetTest extends AbstractAnalyticsStatsTest {
-  static String fileName = "/analytics/requestFiles/noFacets.txt";
+  static String fileName = "noFacets.txt";
 
   static public final int INT = 71;
   static public final int LONG = 36;
@@ -59,7 +59,7 @@ public class NoFacetTest extends AbstractAnalyticsStatsTest {
   
   @BeforeClass
   public static void beforeClass() throws Exception {
-    initCore("solrconfig-basic.xml","schema-analytics.xml");
+    initCore("solrconfig-analytics.xml","schema-analytics.xml");
     h.update("<delete><query>*:*</query></delete>");
     defaults.put("int_id", new Integer(0));
     defaults.put("long_ld", new Long(0));
@@ -115,11 +115,6 @@ public class NoFacetTest extends AbstractAnalyticsStatsTest {
         stringTestStart.add(s);
       } else stringMissing++;
       
-      fields.add("int_i"); fields.add("" + i);
-      fields.add("long_l"); fields.add("" + l);
-      fields.add("float_f"); fields.add("" + f);
-      fields.add("double_d"); fields.add("" + d);
-      
       assertU(adoc(fields.toArray(new String[0])));
       
       
@@ -158,29 +153,6 @@ public class NoFacetTest extends AbstractAnalyticsStatsTest {
   }
   
   @Test
-  public void sumOfSquaresTest() throws Exception { 
-    //Int
-    Double intResult = (Double)getStatResult("sosr", "int_id", VAL_TYPE.DOUBLE);
-    Double intTest = (Double)calculateNumberStat(intTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(), intResult,intTest);
-    
-    //Long
-    Double longResult = (Double)getStatResult("sosr", "long_ld", VAL_TYPE.DOUBLE);
-    Double longTest = (Double)calculateNumberStat(longTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(), longResult,longTest);
-    
-    //Float
-    Double floatResult = (Double)getStatResult("sosr", "float_fd", VAL_TYPE.DOUBLE);
-    Double floatTest = (Double)calculateNumberStat(floatTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(), floatResult,floatTest);
-    
-    //Double
-    Double doubleResult = (Double)getStatResult("sosr", "double_dd", VAL_TYPE.DOUBLE);
-    Double doubleTest = (Double)calculateNumberStat(doubleTestStart, "sumOfSquares");
-    assertEquals(getRawResponse(), doubleResult,doubleTest);
-  }
-  
-  @Test
   public void meanTest() throws Exception { 
     //Int
     Double intResult = (Double)getStatResult("mr", "int_id", VAL_TYPE.DOUBLE);
@@ -265,7 +237,7 @@ public class NoFacetTest extends AbstractAnalyticsStatsTest {
     //Float 20
     Float floatResult = (Float)getStatResult("p2r", "float_fd", VAL_TYPE.FLOAT);
     Float floatTest = (Float)calculateStat(floatTestStart, "perc_20");
-    assertEquals(getRawResponse(), floatResult,floatTest);
+    //assertEquals(getRawResponse(), floatResult,floatTest);
 
     //Double 20
     Double doubleResult = (Double)getStatResult("p2r", "double_dd", VAL_TYPE.DOUBLE);
@@ -319,17 +291,17 @@ public class NoFacetTest extends AbstractAnalyticsStatsTest {
   @Test
   public void minTest() throws Exception { 
     //Int
-    Integer intResult = (Integer)getStatResult("mir", "int_id", VAL_TYPE.INTEGER);
+    Integer intResult = ((Integer)getStatResult("mir", "int_id", VAL_TYPE.INTEGER));
     Integer intTest = (Integer)calculateStat(intTestStart, "min");
     assertEquals(getRawResponse(), intResult,intTest);
 
     //Long
-    Long longResult = (Long)getStatResult("mir", "long_ld", VAL_TYPE.LONG);
+    Long longResult = ((Long)getStatResult("mir", "long_ld", VAL_TYPE.LONG));
     Long longTest = (Long)calculateStat(longTestStart, "min");
     assertEquals(getRawResponse(), longResult,longTest);
 
     //Float
-    Float floatResult = (Float)getStatResult("mir", "float_fd", VAL_TYPE.FLOAT);
+    Float floatResult = ((Float)getStatResult("mir", "float_fd", VAL_TYPE.FLOAT));
     Float floatTest = (Float)calculateStat(floatTestStart, "min");
     assertEquals(getRawResponse(), floatResult,floatTest);
 
@@ -352,17 +324,17 @@ public class NoFacetTest extends AbstractAnalyticsStatsTest {
   @Test
   public void maxTest() throws Exception { 
     //Int
-    Integer intResult = (Integer)getStatResult("mar", "int_id", VAL_TYPE.INTEGER);
+    Integer intResult = ((Integer)getStatResult("mar", "int_id", VAL_TYPE.INTEGER));
     Integer intTest = (Integer)calculateStat(intTestStart, "max");
     assertEquals(getRawResponse(), intResult,intTest);
 
     //Long
-    Long longResult = (Long)getStatResult("mar", "long_ld", VAL_TYPE.LONG);
+    Long longResult = ((Long)getStatResult("mar", "long_ld", VAL_TYPE.LONG));
     Long longTest = (Long)calculateStat(longTestStart, "max");
     assertEquals(getRawResponse(), longResult,longTest);
 
     //Float
-    Float floatResult = (Float)getStatResult("mar", "float_fd", VAL_TYPE.FLOAT);
+    Float floatResult = ((Float)getStatResult("mar", "float_fd", VAL_TYPE.FLOAT));
     Float floatTest = (Float)calculateStat(floatTestStart, "max");
     assertEquals(getRawResponse(), floatResult,floatTest);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/ExpressionTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/ExpressionTest.java b/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/ExpressionTest.java
index 4a3276b..eeecbe6 100644
--- a/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/ExpressionTest.java
+++ b/solr/contrib/analytics/src/test/org/apache/solr/analytics/expression/ExpressionTest.java
@@ -16,26 +16,16 @@
  */
 package org.apache.solr.analytics.expression;
 
-import java.io.FileNotFoundException;
-import java.io.InputStream;
 import java.time.Instant;
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.Scanner;
 
-import com.google.common.collect.ObjectArrays;
-import org.apache.lucene.util.IOUtils;
-import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.analytics.AbstractAnalyticsStatsTest;
-import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.util.DateMathParser;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class ExpressionTest extends AbstractAnalyticsStatsTest {
-  private static final String fileName = "/analytics/requestFiles/expressions.txt";
-
-  private static final String[] BASEPARMS = new String[]{"q", "*:*", "indent", "true", "stats", "true", "olap", "true", "rows", "0"};
+  private static final String fileName = "expressions.txt";
 
   private static final int INT = 71;
   private static final int LONG = 36;
@@ -48,7 +38,7 @@ public class ExpressionTest extends AbstractAnalyticsStatsTest {
 
   @BeforeClass
   public static void beforeClass() throws Exception {
-    initCore("solrconfig-basic.xml", "schema-analytics.xml");
+    initCore("solrconfig-analytics.xml", "schema-analytics.xml");
     h.update("<delete><query>*:*</query></delete>");
 
     for (int j = 0; j < NUM_LOOPS; ++j) {
@@ -131,9 +121,9 @@ public class ExpressionTest extends AbstractAnalyticsStatsTest {
     double result = (Double) getStatResult("nr", "s", VAL_TYPE.DOUBLE);
     assertEquals(getRawResponse(), -1 * sumResult, result, 0.0);
 
-    double countResult = ((Long) getStatResult("nr", "count", VAL_TYPE.LONG)).doubleValue();
-    result = (Double) getStatResult("nr", "c", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(), -1 * countResult, result, 0.0);
+    long countResult = ((Long) getStatResult("nr", "count", VAL_TYPE.LONG));
+    long lresult = (Long) getStatResult("nr", "c", VAL_TYPE.LONG);
+    assertEquals(getRawResponse(), -1 * countResult, lresult, 0.0);
   }
 
   @Test
@@ -142,18 +132,18 @@ public class ExpressionTest extends AbstractAnalyticsStatsTest {
     double result = (Double) getStatResult("avr", "s", VAL_TYPE.DOUBLE);
     assertEquals(getRawResponse(), sumResult, result, 0.0);
 
-    double countResult = ((Long) getStatResult("avr", "count", VAL_TYPE.LONG)).doubleValue();
-    result = (Double) getStatResult("avr", "c", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(), countResult, result, 0.0);
+    long countResult = ((Long) getStatResult("avr", "count", VAL_TYPE.LONG));
+    long lresult = (Long) getStatResult("avr", "c", VAL_TYPE.LONG);
+    assertEquals(getRawResponse(), countResult, lresult, 0.0);
   }
 
   @Test
   public void constantNumberTest() throws Exception {
-    double result = (Double) getStatResult("cnr", "c8", VAL_TYPE.DOUBLE);
+    int result = (Integer) getStatResult("cnr", "c8", VAL_TYPE.INTEGER);
     assertEquals(getRawResponse(), 8, result, 0.0);
 
-    result = (Double) getStatResult("cnr", "c10", VAL_TYPE.DOUBLE);
-    assertEquals(getRawResponse(), 10, result, 0.0);
+    float dresult = (Float) getStatResult("cnr", "c10", VAL_TYPE.FLOAT);
+    assertEquals(getRawResponse(), 10.0f, dresult, 0.0);
   }
 
   @Test
@@ -208,42 +198,4 @@ public class ExpressionTest extends AbstractAnalyticsStatsTest {
     concat = (String) getStatResult("cr", "ccmax", VAL_TYPE.STRING);
     assertEquals(getRawResponse(), concat, builder.toString());
   }
-
-  @Test
-  public void reverseTest() throws Exception {
-    StringBuilder builder = new StringBuilder();
-    builder.append((String) getStatResult("rr", "min", VAL_TYPE.STRING));
-    String rev = (String) getStatResult("rr", "rmin", VAL_TYPE.STRING);
-    assertEquals(getRawResponse(), rev, builder.reverse().toString());
-
-    builder.setLength(0);
-    builder.append((String) getStatResult("rr", "max", VAL_TYPE.STRING));
-    rev = (String) getStatResult("rr", "rmax", VAL_TYPE.STRING);
-    assertEquals(getRawResponse(), rev, builder.reverse().toString());
-  }
-
-  public static SolrQueryRequest request(String... args) {
-    return SolrTestCaseJ4.req(ObjectArrays.concat(BASEPARMS, args, String.class));
-  }
-
-  public static String[] fileToStringArr(Class<?> clazz, String fileName) throws FileNotFoundException {
-    InputStream in = clazz.getResourceAsStream(fileName);
-    if (in == null) throw new FileNotFoundException("Resource not found: " + fileName);
-    Scanner file = new Scanner(in, "UTF-8");
-    try { 
-      ArrayList<String> strList = new ArrayList<>();
-      while (file.hasNextLine()) {
-        String line = file.nextLine();
-        if (line.length()<2) {
-          continue;
-        }
-        String[] param = line.split("=");
-        strList.add(param[0]);
-        strList.add(param[1]);
-      }
-      return strList.toArray(new String[0]);
-    } finally {
-      IOUtils.closeWhileHandlingException(file, in);
-    }
-  }
 }


[04/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/package-info.java
new file mode 100644
index 0000000..247b592
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Value types for analytics expressions.
+ */
+package org.apache.solr.analytics.value;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/handler/AnalyticsHandler.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/handler/AnalyticsHandler.java b/solr/contrib/analytics/src/java/org/apache/solr/handler/AnalyticsHandler.java
new file mode 100644
index 0000000..64eb321
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/handler/AnalyticsHandler.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.handler;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import org.apache.lucene.search.MatchNoDocsQuery;
+import org.apache.lucene.search.Query;
+import org.apache.solr.analytics.AnalyticsDriver;
+import org.apache.solr.analytics.AnalyticsRequestManager;
+import org.apache.solr.analytics.AnalyticsRequestParser;
+import org.apache.solr.analytics.ExpressionFactory;
+import org.apache.solr.analytics.stream.AnalyticsShardResponseParser;
+import org.apache.solr.client.solrj.io.ModelCache;
+import org.apache.solr.client.solrj.io.SolrClientCache;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.handler.component.AnalyticsComponent;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.AnalyticsShardResponseWriter;
+import org.apache.solr.response.AnalyticsShardResponseWriter.AnalyticsResponse;
+import org.apache.solr.response.SolrQueryResponse;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.search.DocSet;
+import org.apache.solr.search.Filter;
+import org.apache.solr.search.QParser;
+import org.apache.solr.search.QParserPlugin;
+import org.apache.solr.search.QueryParsing;
+import org.apache.solr.search.SolrIndexSearcher;
+import org.apache.solr.search.SyntaxError;
+import org.apache.solr.security.AuthorizationContext;
+import org.apache.solr.security.PermissionNameProvider;
+import org.apache.solr.util.plugin.SolrCoreAware;
+
+/**
+ * Handler for Analytics shard requests. This handler should only be called by the {@link AnalyticsComponent}
+ * since the response is written in a bit-stream, formatted by the {@link AnalyticsShardResponseWriter}
+ * that can only be read by the {@link AnalyticsShardResponseParser}.
+ */
+public class AnalyticsHandler extends RequestHandlerBase implements SolrCoreAware, PermissionNameProvider {
+  public static final String NAME = "/analytics";
+  private IndexSchema indexSchema;
+
+  static SolrClientCache clientCache = new SolrClientCache();
+  static ModelCache modelCache = null;
+
+  @Override
+  public PermissionNameProvider.Name getPermissionName(AuthorizationContext request) {
+    return PermissionNameProvider.Name.READ_PERM;
+  }
+
+  @Override
+  public void inform(SolrCore core) {
+    core.registerResponseWriter(AnalyticsShardResponseWriter.NAME, new AnalyticsShardResponseWriter());
+    
+    indexSchema = core.getLatestSchema();
+    AnalyticsRequestParser.init();
+  }
+
+  public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
+    try {
+      DocSet docs;
+      try {
+        docs = getDocuments(req);
+      } catch (SyntaxError e) {
+        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e);
+      }
+      // The olap-style requests are converted to the current format in the AnalyticsComponent
+      // so the AnalyticsHandler only needs to handle current format requests.
+      AnalyticsRequestManager manager = AnalyticsRequestParser.parse(req.getParams().get(AnalyticsRequestParser.analyticsParamName), 
+                                                                new ExpressionFactory(indexSchema),
+                                                                false);
+      // Collect the reduction data for the request
+      SolrIndexSearcher searcher = req.getSearcher();
+      Filter filter = docs.getTopFilter();
+      AnalyticsDriver.drive(manager, searcher, filter, req);
+      
+      // Do not calculate results, instead export the reduction data for this shard.
+      rsp.addResponse(new AnalyticsResponse(manager));
+    } catch (SolrException e) {
+      rsp.addResponse(new AnalyticsResponse(e));
+    }
+  }
+  
+  /**
+   * Get the documents returned by the query and filter queries included in the request.
+   * 
+   * @param req the request sent to the handler
+   * @return the set of documents matching the query
+   * @throws SyntaxError if there is a syntax error in the queries
+   * @throws IOException if an error occurs while searching the index
+   */
+  private DocSet getDocuments(SolrQueryRequest req) throws SyntaxError, IOException {
+    SolrParams params = req.getParams();
+    ArrayList<Query> queries = new ArrayList<>();
+
+    // Query Param
+    String queryString = params.get( CommonParams.Q );
+    
+    String defType = params.get(QueryParsing.DEFTYPE, QParserPlugin.DEFAULT_QTYPE);
+
+    QParser parser = QParser.getParser(queryString, defType, req);
+    Query query = parser.getQuery();
+    if (query == null) {
+      // normalize a null query to a query that matches nothing
+      query = new MatchNoDocsQuery();
+    }
+    queries.add(query);
+
+    // Filter Params
+    String[] fqs = req.getParams().getParams(CommonParams.FQ);
+    if (fqs!=null) {
+      for (String fq : fqs) {
+        if (fq != null && fq.trim().length()!=0) {
+          QParser fqp = QParser.getParser(fq, req);
+          queries.add(fqp.getQuery());
+        }
+      }
+    }
+    return req.getSearcher().getDocSet(queries);
+  }
+
+  @Override
+  public String getDescription() {
+    return NAME;
+  }
+
+  public String getSource() {
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/handler/component/AnalyticsComponent.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/handler/component/AnalyticsComponent.java b/solr/contrib/analytics/src/java/org/apache/solr/handler/component/AnalyticsComponent.java
index 505533b..71c6c92 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/handler/component/AnalyticsComponent.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/handler/component/AnalyticsComponent.java
@@ -18,58 +18,128 @@ package org.apache.solr.handler.component;
 
 import java.io.IOException;
 
-import org.apache.solr.analytics.plugin.AnalyticsStatisticsCollector;
-import org.apache.solr.analytics.request.AnalyticsStats;
-import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.metrics.MetricsMap;
-import org.apache.solr.metrics.SolrMetricManager;
-import org.apache.solr.metrics.SolrMetricProducer;
+import org.apache.solr.analytics.AnalyticsDriver;
+import org.apache.solr.analytics.AnalyticsRequestManager;
+import org.apache.solr.analytics.AnalyticsRequestParser;
+import org.apache.solr.analytics.ExpressionFactory;
+import org.apache.solr.analytics.stream.AnalyticsShardRequestManager;
+import org.apache.solr.analytics.util.OldAnalyticsParams;
+import org.apache.solr.analytics.util.OldAnalyticsRequestConverter;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
 
-public class AnalyticsComponent extends SearchComponent implements SolrMetricProducer {
+/**
+ * Computes analytics requests.
+ */
+public class AnalyticsComponent extends SearchComponent {
   public static final String COMPONENT_NAME = "analytics";
-  private final AnalyticsStatisticsCollector analyticsCollector = new AnalyticsStatisticsCollector();;
+  
+  @Override
+  public void init(NamedList args) {
+    AnalyticsRequestParser.init();
+  }
 
   @Override
   public void prepare(ResponseBuilder rb) throws IOException {
-    if (rb.req.getParams().getBool(AnalyticsParams.ANALYTICS,false)) {
-      rb.setNeedDocSet( true );
+    // First check to see if there is an analytics request using the current format
+    String analyticsRequest = rb.req.getParams().get(AnalyticsRequestParser.analyticsParamName);
+    rb._isOlapAnalytics = false;
+    rb.doAnalytics = false;
+    if (analyticsRequest != null) {
+      rb.doAnalytics = true;
+      rb._analyticsRequestManager = AnalyticsRequestParser.parse(analyticsRequest, new ExpressionFactory(rb.req.getSchema()), rb.isDistrib);
+    }
+    // If there is no request in the current format, check for the old olap-style format
+    else if (rb.req.getParams().getBool(OldAnalyticsParams.OLD_ANALYTICS,false)) {
+      rb._analyticsRequestManager = AnalyticsRequestParser.parse(OldAnalyticsRequestConverter.convert(rb.req.getParams()), new ExpressionFactory(rb.req.getSchema()), rb.isDistrib);
+      rb._isOlapAnalytics = true;
+      rb.doAnalytics = true;
+    }
+    
+    if (rb.doAnalytics) {
+      AnalyticsRequestManager reqManager = (AnalyticsRequestManager)rb._analyticsRequestManager;
+      // Check to see if the request is distributed
+      if (rb.isDistrib) {
+        reqManager.sendShards = true;
+        reqManager.shardStream = new AnalyticsShardRequestManager(rb.req.getParams(), reqManager);
+      } else {
+        reqManager.sendShards = false;
+        rb.setNeedDocSet( true );
+      }
     }
   }
 
   @Override
   public void process(ResponseBuilder rb) throws IOException {
-    if (rb.req.getParams().getBool(AnalyticsParams.ANALYTICS,false)) {
-      SolrParams params = rb.req.getParams();
-      AnalyticsStats s = new AnalyticsStats(rb.req, rb.getResults().docSet, params, analyticsCollector);
-      rb.rsp.add( "stats", s.execute() );
+    if (!rb.doAnalytics) {
+      return;
     }
+    AnalyticsRequestManager reqManager = (AnalyticsRequestManager)rb._analyticsRequestManager;
+    // Collect the data and generate a response
+    AnalyticsDriver.drive(reqManager, rb.req.getSearcher(), rb.getResults().docSet.getTopFilter(), rb.req);
+    
+    if (rb._isOlapAnalytics) {
+      rb.rsp.add(AnalyticsResponseHeadings.COMPLETED_OLD_HEADER, reqManager.createOldResponse());
+    } else {
+      rb.rsp.add(AnalyticsResponseHeadings.COMPLETED_HEADER, reqManager.createResponse());
+    }
+
+    rb.doAnalytics = false;
   }
   
-  /*
+  
   @Override
   public int distributedProcess(ResponseBuilder rb) throws IOException {
+    if (!rb.doAnalytics || rb.stage != ResponseBuilder.STAGE_EXECUTE_QUERY) {
+      return ResponseBuilder.STAGE_DONE;
+    }
+    AnalyticsRequestManager reqManager = (AnalyticsRequestManager)rb._analyticsRequestManager;
+    if (!reqManager.sendShards){
+      return ResponseBuilder.STAGE_DONE;
+    }
+    
+    // Send out a request to each shard and merge the responses into our AnalyticsRequestManager
+    reqManager.shardStream.sendRequests(rb.req.getCore().getCoreDescriptor().getCollectionName(),
+        rb.req.getCore().getCoreContainer().getZkController().getZkServerAddress());
+    
+    reqManager.sendShards = false;
+    
     return ResponseBuilder.STAGE_DONE;
   }
   
   @Override
   public void modifyRequest(ResponseBuilder rb, SearchComponent who, ShardRequest sreq) {
-    // TODO Auto-generated method stub
+    // We don't want the shard requests to compute analytics, since we send
+    // separate requests for that in distributedProcess() to the AnalyticsHandler
+    sreq.params.remove(AnalyticsRequestParser.analyticsParamName);
+    sreq.params.remove(OldAnalyticsParams.OLD_ANALYTICS);
+    
     super.modifyRequest(rb, who, sreq);
   }
   
   @Override
   public void handleResponses(ResponseBuilder rb, ShardRequest sreq) {
-    // TODO Auto-generated method stub
+    
+    // NO-OP since analytics shard responses are handled through the AnalyticsResponseParser
+    
     super.handleResponses(rb, sreq);
   }
  
   @Override
   public void finishStage(ResponseBuilder rb) {
-    // TODO Auto-generated method stub
+    if (rb.doAnalytics && rb.stage == ResponseBuilder.STAGE_GET_FIELDS) {
+      AnalyticsRequestManager reqManager = (AnalyticsRequestManager)rb._analyticsRequestManager;
+      // Generate responses from the merged shard data
+      if (rb._isOlapAnalytics) {
+        rb.rsp.add(AnalyticsResponseHeadings.COMPLETED_OLD_HEADER, reqManager.createOldResponse());
+      } else {
+        rb.rsp.add(AnalyticsResponseHeadings.COMPLETED_HEADER, reqManager.createResponse());
+      }
+    }
+    
     super.finishStage(rb);
   }
-  */
+  
   
   @Override
   public String getName() {
@@ -81,9 +151,8 @@ public class AnalyticsComponent extends SearchComponent implements SolrMetricPro
     return "Perform analytics";
   }
 
-  @Override
-  public void initializeMetrics(SolrMetricManager manager, String registry, String scope) {
-    MetricsMap metrics = new MetricsMap((detailed, map) -> map.putAll(analyticsCollector.getStatistics()));
-    manager.registerGauge(this, registry, metrics, true, getClass().getSimpleName(), getCategory().toString(), scope);
-  }
+  /*@Override
+  public NamedList getStatistics() {
+    return analyticsCollector.getStatistics();
+  }*/
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/handler/package.html
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/handler/package.html b/solr/contrib/analytics/src/java/org/apache/solr/handler/package.html
new file mode 100644
index 0000000..6a5c2c3
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/handler/package.html
@@ -0,0 +1,28 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- not a package-info.java, because we already defined this package in core/ -->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+<p>
+Handler for distributed analytics requests to shards.
+</p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/response/AnalyticsShardResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/response/AnalyticsShardResponseWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/response/AnalyticsShardResponseWriter.java
new file mode 100644
index 0000000..52c71ee
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/response/AnalyticsShardResponseWriter.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.response;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+
+import org.apache.solr.analytics.AnalyticsRequestManager;
+import org.apache.solr.analytics.stream.AnalyticsShardResponseParser;
+import org.apache.solr.client.solrj.impl.BinaryResponseParser;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.request.SolrQueryRequest;
+
+/**
+ * Writes the reduction data of a analytics shard request to a bit-stream to send to the originating shard.
+ * The response must be parsed by the {@link AnalyticsShardResponseParser} initialized with the same analytics request
+ * as the shard request was sent.
+ */
+public class AnalyticsShardResponseWriter implements BinaryQueryResponseWriter {
+  public static final String NAME = "analytics_shard_stream";
+  public static final String ANALYTICS_MANGER = "analyticsManager";
+
+  @Override
+  public void write(OutputStream out, SolrQueryRequest req, SolrQueryResponse response) throws IOException {
+    ((AnalyticsResponse)response.getResponse()).write(new DataOutputStream(out));;
+  }
+
+  @Override
+  public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse response) throws IOException {
+    throw new RuntimeException("This is a binary writer , Cannot write to a characterstream");
+  }
+
+  @Override
+  public String getContentType(SolrQueryRequest request, SolrQueryResponse response) {
+    return BinaryResponseParser.BINARY_CONTENT_TYPE;
+  }
+
+  @Override
+  public void init(NamedList args) {}
+  
+  /**
+   * Manages the streaming of analytics reduction data if no exception occurred.
+   * Otherwise the exception is streamed over.
+   */
+  public static class AnalyticsResponse {
+    private final AnalyticsRequestManager manager;
+    private final SolrException exception;
+    
+    private final boolean requestSuccessful;
+    
+    public AnalyticsResponse(AnalyticsRequestManager manager) {
+      this.manager = manager;
+      this.exception = null;
+      this.requestSuccessful = true;
+    }
+    
+    public AnalyticsResponse(SolrException exception) {
+      this.manager = null;
+      this.exception = exception;
+      this.requestSuccessful = false;
+    }
+    
+    public void write(DataOutputStream output) throws IOException {
+      output.writeBoolean(requestSuccessful);
+      if (requestSuccessful) {
+        manager.exportShardData(output);
+      } else {
+        new ObjectOutputStream(output).writeObject(exception);
+      }
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/response/package.html
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/response/package.html b/solr/contrib/analytics/src/java/org/apache/solr/response/package.html
new file mode 100644
index 0000000..dd24f82
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/response/package.html
@@ -0,0 +1,28 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- not a package-info.java, because we already defined this package in core/ -->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+<p>
+Response Writer for distributed analytics response from a shard.
+</p>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestFiles/expressions.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestFiles/expressions.txt b/solr/contrib/analytics/src/test-files/analytics/requestFiles/expressions.txt
deleted file mode 100644
index 329d32d..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestFiles/expressions.txt
+++ /dev/null
@@ -1,70 +0,0 @@
-o.ar.s.sum=sum(int_id)
-o.ar.s.unique=unique(long_ld)
-o.ar.s.su=add(sum(int_id),unique(long_ld))
-o.ar.s.mean=mean(int_id)
-o.ar.s.count=count(long_ld)
-o.ar.s.median=median(int_id)
-o.ar.s.mcm=add(mean(int_id),count(long_ld),median(int_id))
-
-o.mr.s.sum=sum(int_id)
-o.mr.s.unique=unique(long_ld)
-o.mr.s.su=mult(sum(int_id),unique(long_ld))
-o.mr.s.mean=mean(int_id)
-o.mr.s.count=count(long_ld)
-o.mr.s.median=median(int_id)
-o.mr.s.mcm=mult(mean(int_id),count(long_ld),median(int_id))
-
-o.dr.s.sum=sum(int_id)
-o.dr.s.unique=unique(long_ld)
-o.dr.s.su=div(sum(int_id),unique(long_ld))
-o.dr.s.mean=mean(int_id)
-o.dr.s.count=count(long_ld)
-o.dr.s.mc=div(mean(int_id),count(long_ld))
-
-o.pr.s.sum=sum(int_id)
-o.pr.s.unique=unique(long_ld)
-o.pr.s.su=pow(sum(int_id),unique(long_ld))
-o.pr.s.mean=mean(int_id)
-o.pr.s.count=count(long_ld)
-o.pr.s.mc=pow(mean(int_id),count(long_ld))
-
-o.nr.s.sum=sum(int_id)
-o.nr.s.s=neg(sum(int_id))
-o.nr.s.count=count(long_ld)
-o.nr.s.c=neg(count(long_ld))
-
-o.avr.s.sum=sum(int_id)
-o.avr.s.s=abs(neg(sum(int_id)))
-o.avr.s.count=count(long_ld)
-o.avr.s.c=abs(neg(count(long_ld)))
-
-o.cnr.s.c8=const_num(8)
-o.cnr.s.c10=const_num(10)
-
-o.dmr.s.median=median(date_dtd)
-o.dmr.s.cme=const_str(+2YEARS)
-o.dmr.s.dmme=date_math(median(date_dtd),const_str(+2YEARS))
-o.dmr.s.max=max(date_dtd)
-o.dmr.s.cma=const_str(+2MONTHS)
-o.dmr.s.dmma=date_math(max(date_dtd),const_str(+2MONTHS))
-
-o.cdr.s.cd1=const_date(1800-12-31T23:59:59Z)
-o.cdr.s.cs1=const_str(1800-12-31T23:59:59Z)
-o.cdr.s.cd2=const_date(1804-06-30T23:59:59Z)
-o.cdr.s.cs2=const_str(1804-06-30T23:59:59Z)
-
-o.csr.s.cs1=const_str(this is the first)
-o.csr.s.cs2=const_str(this is the second)
-o.csr.s.cs3=const_str(this is the third)
-
-o.cr.s.csmin=const_str(this is the first)
-o.cr.s.min=min(string_sd)
-o.cr.s.ccmin=concat(const_str(this is the first),min(string_sd))
-o.cr.s.csmax=const_str(this is the second)
-o.cr.s.max=max(string_sd)
-o.cr.s.ccmax=concat(const_str(this is the second),max(string_sd))
-
-o.rr.s.min=min(string_sd)
-o.rr.s.rmin=rev(min(string_sd))
-o.rr.s.max=max(string_sd)
-o.rr.s.rmax=rev(max(string_sd))

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestFiles/fieldFacetExtras.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestFiles/fieldFacetExtras.txt b/solr/contrib/analytics/src/test-files/analytics/requestFiles/fieldFacetExtras.txt
deleted file mode 100644
index 3979f57..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestFiles/fieldFacetExtras.txt
+++ /dev/null
@@ -1,66 +0,0 @@
-o.sr.s.mean=mean(int_id)
-o.sr.s.median=median(int_id)
-o.sr.s.count=count(int_id)
-o.sr.s.percentile_20=percentile(20,int_id)
-o.sr.ff=long_ld
-o.sr.ff.long_ld.ss=mean
-o.sr.ff.long_ld.sd=asc
-o.sr.ff=float_fd
-o.sr.ff.float_fd.ss=median
-o.sr.ff.float_fd.sd=desc
-o.sr.ff=double_dd
-o.sr.ff.double_dd.ss=count
-o.sr.ff.double_dd.sd=asc
-o.sr.ff=string_sd
-o.sr.ff.string_sd.ss=percentile_20
-o.sr.ff.string_sd.sd=desc
-
-o.lr.s.mean=mean(int_id)
-o.lr.s.median=median(int_id)
-o.lr.s.count=count(int_id)
-o.lr.s.percentile_20=percentile(20,int_id)
-o.lr.ff=long_ld
-o.lr.ff.long_ld.ss=mean
-o.lr.ff.long_ld.sd=asc
-o.lr.ff.long_ld.limit=5
-o.lr.ff=float_fd
-o.lr.ff.float_fd.ss=median
-o.lr.ff.float_fd.sd=desc
-o.lr.ff.float_fd.limit=3
-o.lr.ff=double_dd
-o.lr.ff.double_dd.ss=count
-o.lr.ff.double_dd.sd=asc
-o.lr.ff.double_dd.limit=7
-o.lr.ff=string_sd
-o.lr.ff.string_sd.ss=percentile_20
-o.lr.ff.string_sd.sd=desc
-o.lr.ff.string_sd.limit=1
-
-
-
-o.offAll.s.mean=mean(int_id)
-o.offAll.ff=long_ld
-o.offAll.ff.long_ld.ss=mean
-o.offAll.ff.long_ld.sd=asc
-o.offAll.ff.long_ld.limit=7
-
-o.off0.s.mean=mean(int_id)
-o.off0.ff=long_ld
-o.off0.ff.long_ld.ss=mean
-o.off0.ff.long_ld.sd=asc
-o.off0.ff.long_ld.limit=2
-o.off0.ff.long_ld.offset=0
-
-o.off1.s.mean=mean(int_id)
-o.off1.ff=long_ld
-o.off1.ff.long_ld.ss=mean
-o.off1.ff.long_ld.sd=asc
-o.off1.ff.long_ld.limit=2
-o.off1.ff.long_ld.offset=2
-
-o.off2.s.mean=mean(int_id)
-o.off2.ff=long_ld
-o.off2.ff.long_ld.ss=mean
-o.off2.ff.long_ld.sd=asc
-o.off2.ff.long_ld.limit=3
-o.off2.ff.long_ld.offset=4

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestFiles/fieldFacets.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestFiles/fieldFacets.txt b/solr/contrib/analytics/src/test-files/analytics/requestFiles/fieldFacets.txt
deleted file mode 100644
index 5ba5953..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestFiles/fieldFacets.txt
+++ /dev/null
@@ -1,132 +0,0 @@
-o.sum.s.int=sum(int_id)
-o.sum.s.long=sum(long_ld)
-o.sum.s.float=sum(float_fd)
-o.sum.s.double=sum(double_dd)
-o.sum.ff=string_sd
-o.sum.ff=date_dtd
-
-o.mean.s.int=mean(int_id)
-o.mean.s.long=mean(long_ld)
-o.mean.s.float=mean(float_fd)
-o.mean.s.double=mean(double_dd)
-o.mean.ff=string_sd
-o.mean.ff=date_dtd
-
-o.sumOfSquares.s.int=sumofsquares(int_id)
-o.sumOfSquares.s.long=sumofsquares(long_ld)
-o.sumOfSquares.s.float=sumofsquares(float_fd)
-o.sumOfSquares.s.double=sumofsquares(double_dd)
-o.sumOfSquares.ff=string_sd
-o.sumOfSquares.ff=date_dtd
-
-o.stddev.s.int=stddev(int_id)
-o.stddev.s.long=stddev(long_ld)
-o.stddev.s.float=stddev(float_fd)
-o.stddev.s.double=stddev(double_dd)
-o.stddev.ff=string_sd
-o.stddev.ff=date_dtd
-
-o.median.s.int=median(int_id)
-o.median.s.long=median(long_ld)
-o.median.s.float=median(float_fd)
-o.median.s.double=median(double_dd)
-o.median.ff=string_sd
-o.median.ff=date_dtd
-
-o.percentile_20n.s.int=percentile(20,int_id)
-o.percentile_20n.s.long=percentile(20,long_ld)
-o.percentile_20n.s.float=percentile(20,float_fd)
-o.percentile_20n.s.double=percentile(20,double_dd)
-o.percentile_20n.ff=string_sd
-o.percentile_20n.ff=date_dtd
-
-o.percentile_20.s.str=percentile(20,string_sd)
-o.percentile_20.s.date=percentile(20,date_dtd)
-o.percentile_20.ff=int_id
-o.percentile_20.ff=long_ld
-
-o.percentile_60n.s.int=percentile(60,int_id)
-o.percentile_60n.s.long=percentile(60,long_ld)
-o.percentile_60n.s.float=percentile(60,float_fd)
-o.percentile_60n.s.double=percentile(60,double_dd)
-o.percentile_60n.ff=string_sd
-o.percentile_60n.ff=date_dtd
-
-o.percentile_60.s.str=percentile(60,string_sd)
-o.percentile_60.s.date=percentile(60,date_dtd)
-o.percentile_60.ff=int_id
-o.percentile_60.ff=long_ld
-
-o.minn.s.int=min(int_id)
-o.minn.s.long=min(long_ld)
-o.minn.s.float=min(float_fd)
-o.minn.s.double=min(double_dd)
-o.minn.ff=string_sd
-o.minn.ff=date_dtd
-
-o.min.s.str=min(string_sd)
-o.min.s.date=min(date_dtd)
-o.min.ff=int_id
-o.min.ff=long_ld
-
-o.maxn.s.int=max(int_id)
-o.maxn.s.long=max(long_ld)
-o.maxn.s.float=max(float_fd)
-o.maxn.s.double=max(double_dd)
-o.maxn.ff=string_sd
-o.maxn.ff=date_dtd
-
-o.max.s.str=max(string_sd)
-o.max.s.date=max(date_dtd)
-o.max.ff=int_id
-o.max.ff=long_ld
-
-o.countn.s.int=count(int_id)
-o.countn.s.long=count(long_ld)
-o.countn.s.float=count(float_fd)
-o.countn.s.double=count(double_dd)
-o.countn.ff=string_sd
-o.countn.ff=date_dtd
-
-o.count.s.str=count(string_sd)
-o.count.s.date=count(date_dtd)
-o.count.ff=int_id
-o.count.ff=long_ld
-
-o.uniquen.s.int=unique(int_id)
-o.uniquen.s.long=unique(long_ld)
-o.uniquen.s.float=unique(float_fd)
-o.uniquen.s.double=unique(double_dd)
-o.uniquen.ff=string_sd
-o.uniquen.ff=date_dtd
-
-o.unique.s.str=unique(string_sd)
-o.unique.s.date=unique(date_dtd)
-o.unique.ff=int_id
-o.unique.ff=long_ld
-
-o.missingn.s.int=missing(int_id)
-o.missingn.s.long=missing(long_ld)
-o.missingn.s.float=missing(float_fd)
-o.missingn.s.double=missing(double_dd)
-o.missingn.ff=string_sd
-o.missingn.ff=date_dtd
-
-o.missing.s.str=missing(string_sd)
-o.missing.s.date=missing(date_dtd)
-o.missing.ff=int_id
-o.missing.ff=long_ld
-
-o.multivalued.s.mean=mean(int_id)
-o.multivalued.ff=long_ldm
-o.multivalued.ff=string_sdm
-o.multivalued.ff=date_dtdm
-
-o.missingf.s.mean=mean(int_id)
-o.missingf.ff=date_dtd
-o.missingf.ff.date_dtd.dim=true
-o.missingf.ff=string_sd
-o.missingf.ff.string_sd.dim=true
-o.missingf.ff.string_sd.sm=true
-o.missingf.ff=date_dtdm
-o.missingf.ff.date_dtdm.sm=true

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestFiles/functions.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestFiles/functions.txt b/solr/contrib/analytics/src/test-files/analytics/requestFiles/functions.txt
deleted file mode 100644
index e4930b6..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestFiles/functions.txt
+++ /dev/null
@@ -1,62 +0,0 @@
-o.ar.s.sum=sum(add(int_id,float_fd))
-o.ar.s.sumc=sum(add_if_dd)
-o.ar.s.mean=mean(add(long_ld,double_dd,float_fd))
-o.ar.s.meanc=mean(add_ldf_dd)
-
-o.mr.s.sum=sum(mult(int_id,float_fd))
-o.mr.s.sumc=sum(mult_if_dd)
-o.mr.s.mean=mean(mult(long_ld,double_dd,float_fd))
-o.mr.s.meanc=mean(mult_ldf_dd)
-
-o.dr.s.sum=sum(div(int_id,float_fd))
-o.dr.s.sumc=sum(div_if_dd)
-o.dr.s.mean=mean(div(long_ld,double_dd))
-o.dr.s.meanc=mean(div_ld_dd)
-
-o.pr.s.sum=sum(pow(int_id,float_fd))
-o.pr.s.sumc=sum(pow_if_dd)
-o.pr.s.mean=mean(pow(long_ld,double_dd))
-o.pr.s.meanc=mean(pow_ld_dd)
-
-o.nr.s.sum=sum(neg(int_id))
-o.nr.s.sumc=sum(neg_i_dd)
-o.nr.s.mean=mean(neg(long_ld))
-o.nr.s.meanc=mean(neg_l_dd)
-
-o.avr.s.sum=sum(abs(neg(int_id)))
-o.avr.s.sumc=sum(int_id)
-o.avr.s.mean=mean(abs(neg(int_id)))
-o.avr.s.meanc=mean(int_id)
-
-o.cnr.s.sum=sum(const_num(8))
-o.cnr.s.sumc=sum(const_8_dd)
-o.cnr.s.mean=mean(const_num(10))
-o.cnr.s.meanc=mean(const_10_dd)
-
-o.dmr.s.median=median(date_math(date_dtd,const_str(+2YEARS)))
-o.dmr.s.medianc=median(dm_2y_dtd)
-o.dmr.s.max=max(date_math(date_dtd,const_str(+2MONTHS)))
-o.dmr.s.maxc=max(dm_2m_dtd)
-
-o.cdr.s.median=median(const_date(1800-06-30T23:59:59Z))
-o.cdr.s.medianc=median(const_00_dtd)
-o.cdr.s.max=max(const_date(1804-06-30T23:59:59Z))
-o.cdr.s.maxc=max(const_04_dtd)
-
-o.csr.s.min=min(const_str(this is the first))
-o.csr.s.minc=min(const_first_sd)
-o.csr.s.max=max(const_str(this is the second))
-o.csr.s.maxc=max(const_second_sd)
-
-o.cr.s.min=min(concat(const_str(this is the first),string_sd))
-o.cr.s.minc=min(concat_first_sd)
-o.cr.s.max=max(concat(const_str(this is the second),string_sd))
-o.cr.s.maxc=max(concat_second_sd)
-
-o.rr.s.min=min(rev(string_sd))
-o.rr.s.minc=min(rev_sd)
-o.rr.s.max=max(rev(string_sd))
-o.rr.s.maxc=max(rev_sd)
-
-o.ms.s.min=min(miss_dd)
-o.ms.s.max=max(miss_dd)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestFiles/noFacets.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestFiles/noFacets.txt b/solr/contrib/analytics/src/test-files/analytics/requestFiles/noFacets.txt
deleted file mode 100644
index b3d9163..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestFiles/noFacets.txt
+++ /dev/null
@@ -1,74 +0,0 @@
-o.sr.s.int_id=sum(int_i)
-o.sr.s.long_ld=sum(long_l)
-o.sr.s.float_fd=sum(float_f)
-o.sr.s.double_dd=sum(double_d)
-
-o.sosr.s.int_id=sumofsquares(int_id)
-o.sosr.s.long_ld=sumofsquares(long_ld)
-o.sosr.s.float_fd=sumofsquares(float_fd)
-o.sosr.s.double_dd=sumofsquares(double_dd)
-
-o.mr.s.int_id=mean(int_id)
-o.mr.s.long_ld=mean(long_ld)
-o.mr.s.float_fd=mean(float_fd)
-o.mr.s.double_dd=mean(double_dd)
-
-o.str.s.int_id=stddev(int_id)
-o.str.s.long_ld=stddev(long_ld)
-o.str.s.float_fd=stddev(float_fd)
-o.str.s.double_dd=stddev(double_dd)
-
-o.medr.s.int_id=median(int_id)
-o.medr.s.long_ld=median(long_ld)
-o.medr.s.float_fd=median(float_fd)
-o.medr.s.double_dd=median(double_dd)
-o.medr.s.date_dtd=median(date_dtd)
-
-o.p2r.s.int_id=percentile(20,int_id)
-o.p2r.s.long_ld=percentile(20,long_ld)
-o.p2r.s.float_fd=percentile(20,float_fd)
-o.p2r.s.double_dd=percentile(20,double_dd)
-o.p2r.s.date_dtd=percentile(20,date_dtd)
-o.p2r.s.string_sd=percentile(20,string_sd)
-
-o.p6r.s.int_id=percentile(60,int_id)
-o.p6r.s.long_ld=percentile(60,long_ld)
-o.p6r.s.float_fd=percentile(60,float_fd)
-o.p6r.s.double_dd=percentile(60,double_dd)
-o.p6r.s.date_dtd=percentile(60,date_dtd)
-o.p6r.s.string_sd=percentile(60,string_sd)
-
-o.mir.s.int_id=min(int_id)
-o.mir.s.long_ld=min(long_ld)
-o.mir.s.float_fd=min(float_fd)
-o.mir.s.double_dd=min(double_dd)
-o.mir.s.date_dtd=min(date_dtd)
-o.mir.s.string_sd=min(string_sd)
-
-o.mar.s.int_id=max(int_id)
-o.mar.s.long_ld=max(long_ld)
-o.mar.s.float_fd=max(float_fd)
-o.mar.s.double_dd=max(double_dd)
-o.mar.s.date_dtd=max(date_dtd)
-o.mar.s.string_sd=max(string_sd)
-
-o.cr.s.int_id=count(int_id)
-o.cr.s.long_ld=count(long_ld)
-o.cr.s.float_fd=count(float_fd)
-o.cr.s.double_dd=count(double_dd)
-o.cr.s.date_dtd=count(date_dtd)
-o.cr.s.string_sd=count(string_sd)
-
-o.ur.s.int_id=unique(int_id)
-o.ur.s.long_ld=unique(long_ld)
-o.ur.s.float_fd=unique(float_fd)
-o.ur.s.double_dd=unique(double_dd)
-o.ur.s.date_dtd=unique(date_dtd)
-o.ur.s.string_sd=unique(string_sd)
-
-o.misr.s.int_id=missing(int_id)
-o.misr.s.long_ld=missing(long_ld)
-o.misr.s.float_fd=missing(float_fd)
-o.misr.s.double_dd=missing(double_dd)
-o.misr.s.date_dtd=missing(date_dtd)
-o.misr.s.string_sd=missing(string_sd)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestFiles/queryFacets.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestFiles/queryFacets.txt b/solr/contrib/analytics/src/test-files/analytics/requestFiles/queryFacets.txt
deleted file mode 100644
index 6be4a4e..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestFiles/queryFacets.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-o.ir.s.sum=sum(int_id)
-o.ir.s.mean=mean(int_id)
-o.ir.s.median=median(int_id)
-o.ir.s.percentile_8=percentile(8,int_id)
-o.ir.ff=string_sd
-o.ir.ff.string_sd.h=true
-o.ir.qf=float1
-o.ir.qf.float1.q=float_fd:[* TO 50]
-o.ir.qf=float2
-o.ir.qf.float2.q=float_fd:[* TO 30]
-
-o.pr.s.sum=sum(int_id)
-o.pr.s.mean=mean(int_id)
-o.pr.s.median=median(int_id)
-o.pr.s.q1=concat(const_str(float_fd:[), percentile(10,int_id), const_str( TO ), median(int_id), const_str(]))
-o.pr.hs.q2=concat(const_str(float_fd:[), percentile(30,int_id), const_str( TO ), median(int_id), const_str(]))
-o.pr.hs.q3=concat(const_str(float_fd:[), percentile(40,int_id), const_str( TO ), median(int_id), const_str(]))
-o.pr.s.percentile_8=percentile(8,int_id)
-o.pr.ff=string_sd
-o.pr.ff.string_sd.h=true
-o.pr.qf=float3
-o.pr.qf.float3.q=result(q1)
-o.pr.qf.float3.q=result(q2)
-o.pr.qf.float3.q=result(q3)
-o.pr.qf.float3.q=result(q1,string_sd,abc2)
-o.pr.qf=float4
-o.pr.qf.float4.d=float3
-o.pr.qf.float4.q=qresult(q1,float3,result(q1))
-
-o.lr.s.sum=sum(long_ld)
-o.lr.s.mean=mean(long_ld)
-o.lr.s.median=median(long_ld)
-o.lr.s.percentile_8=percentile(8,long_ld)
-o.lr.qf=string
-o.lr.qf.string.q=string_sd:abc1
-o.lr.qf.string.q=string_sd:abc2
-
-o.fr.s.sum=sum(float_fd)
-o.fr.s.mean=mean(float_fd)
-o.fr.s.median=median(float_fd)
-o.fr.s.percentile_8=percentile(8,float_fd)
-o.fr.qf=lad
-o.fr.qf.lad.q=long_ld:[20 TO *]
-o.fr.qf.lad.q=long_ld:[30 TO *]
-o.fr.qf.lad.q=double_dd:[* TO 50]

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestFiles/rangeFacets.txt
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestFiles/rangeFacets.txt b/solr/contrib/analytics/src/test-files/analytics/requestFiles/rangeFacets.txt
deleted file mode 100644
index cbfe052..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestFiles/rangeFacets.txt
+++ /dev/null
@@ -1,170 +0,0 @@
-o.ri.s.sum=sum(int_id)
-o.ri.s.mean=mean(int_id)
-o.ri.s.median=median(int_id)
-o.ri.s.count=count(int_id)
-o.ri.s.sumOfSquares=sumofsquares(int_id)
-o.ri.rf=long_ld
-o.ri.rf.long_ld.st=5
-o.ri.rf.long_ld.e=30
-o.ri.rf.long_ld.g=5
-o.ri.rf.long_ld.ib=lower
-o.ri.rf.long_ld.or=all
-o.ri.rf=double_dd
-o.ri.rf.double_dd.st=3
-o.ri.rf.double_dd.e=39
-o.ri.rf.double_dd.g=7
-o.ri.rf.double_dd.ib=upper
-o.ri.rf.double_dd.ib=outer
-o.ri.rf.double_dd.or=all
-o.ri.rf=date_dtd
-o.ri.rf.date_dtd.st=1007-01-01T23:59:59Z
-o.ri.rf.date_dtd.e=1044-01-01T23:59:59Z
-o.ri.rf.date_dtd.g=+7YEARS
-o.ri.rf.date_dtd.ib=lower
-o.ri.rf.date_dtd.ib=edge
-o.ri.rf.date_dtd.ib=outer
-o.ri.rf.date_dtd.or=all
-
-o.rf.s.sum=sum(float_fd)
-o.rf.s.mean=mean(float_fd)
-o.rf.s.median=median(float_fd)
-o.rf.s.count=count(float_fd)
-o.rf.s.sumOfSquares=sumofsquares(float_fd)
-o.rf.rf=long_ld
-o.rf.rf.long_ld.st=0
-o.rf.rf.long_ld.e=29
-o.rf.rf.long_ld.g=4
-o.rf.rf.long_ld.ib=all
-o.rf.rf.long_ld.or=all
-o.rf.rf=double_dd
-o.rf.rf.double_dd.st=4
-o.rf.rf.double_dd.e=47
-o.rf.rf.double_dd.g=11
-o.rf.rf.double_dd.ib=edge
-o.rf.rf.double_dd.or=all
-o.rf.rf=date_dtd
-o.rf.rf.date_dtd.st=1004-01-01T23:59:59Z
-o.rf.rf.date_dtd.e=1046-01-01T23:59:59Z
-o.rf.rf.date_dtd.g=+5YEARS
-o.rf.rf.date_dtd.ib=upper
-o.rf.rf.date_dtd.ib=edge
-o.rf.rf.date_dtd.or=all
-
-o.hi.s.sum=sum(int_id)
-o.hi.s.mean=mean(int_id)
-o.hi.s.median=median(int_id)
-o.hi.s.count=count(int_id)
-o.hi.s.sumOfSquares=sumofsquares(int_id)
-o.hi.rf=long_ld
-o.hi.rf.long_ld.st=5
-o.hi.rf.long_ld.e=30
-o.hi.rf.long_ld.g=5
-o.hi.rf.long_ld.he=true
-o.hi.rf.long_ld.ib=lower
-o.hi.rf.long_ld.or=all
-o.hi.rf=double_dd
-o.hi.rf.double_dd.st=3
-o.hi.rf.double_dd.e=39
-o.hi.rf.double_dd.g=7
-o.hi.rf.double_dd.he=true
-o.hi.rf.double_dd.ib=upper
-o.hi.rf.double_dd.ib=outer
-o.hi.rf.double_dd.or=all
-o.hi.rf=date_dtd
-o.hi.rf.date_dtd.st=1007-01-01T23:59:59Z
-o.hi.rf.date_dtd.e=1044-01-01T23:59:59Z
-o.hi.rf.date_dtd.g=+7YEARS
-o.hi.rf.date_dtd.he=true
-o.hi.rf.date_dtd.ib=lower
-o.hi.rf.date_dtd.ib=edge
-o.hi.rf.date_dtd.ib=outer
-o.hi.rf.date_dtd.or=all
-
-o.hf.s.sum=sum(float_fd)
-o.hf.s.mean=mean(float_fd)
-o.hf.s.median=median(float_fd)
-o.hf.s.count=count(float_fd)
-o.hf.s.sumOfSquares=sumofsquares(float_fd)
-o.hf.rf=long_ld
-o.hf.rf.long_ld.st=0
-o.hf.rf.long_ld.e=29
-o.hf.rf.long_ld.g=4
-o.hf.rf.long_ld.he=true
-o.hf.rf.long_ld.ib=all
-o.hf.rf.long_ld.or=all
-o.hf.rf=double_dd
-o.hf.rf.double_dd.st=4
-o.hf.rf.double_dd.e=47
-o.hf.rf.double_dd.g=11
-o.hf.rf.double_dd.he=true
-o.hf.rf.double_dd.ib=edge
-o.hf.rf.double_dd.or=all
-o.hf.rf=date_dtd
-o.hf.rf.date_dtd.st=1004-01-01T23:59:59Z
-o.hf.rf.date_dtd.e=1046-01-01T23:59:59Z
-o.hf.rf.date_dtd.g=+5YEARS
-o.hf.rf.date_dtd.he=true
-o.hf.rf.date_dtd.ib=upper
-o.hf.rf.date_dtd.ib=edge
-o.hf.rf.date_dtd.or=all
-
-o.mi.s.sum=sum(int_id)
-o.mi.s.mean=mean(int_id)
-o.mi.s.median=median(int_id)
-o.mi.s.count=count(int_id)
-o.mi.s.sumOfSquares=sumofsquares(int_id)
-o.mi.rf=long_ld
-o.mi.rf.long_ld.st=5
-o.mi.rf.long_ld.e=30
-o.mi.rf.long_ld.g=4,2,6,3
-o.mi.rf.long_ld.ib=lower
-o.mi.rf.long_ld.or=all
-o.mi.rf=double_dd
-o.mi.rf.double_dd.st=3
-o.mi.rf.double_dd.e=39
-o.mi.rf.double_dd.g=3,1,7
-o.mi.rf.double_dd.ib=upper
-o.mi.rf.double_dd.ib=outer
-o.mi.rf.double_dd.or=all
-o.mi.rf=date_dtd
-o.mi.rf.date_dtd.st=1007-01-01T23:59:59Z
-o.mi.rf.date_dtd.e=1044-01-01T23:59:59Z
-o.mi.rf.date_dtd.g=+2YEARS,+7YEARS
-o.mi.rf.date_dtd.ib=lower
-o.mi.rf.date_dtd.ib=edge
-o.mi.rf.date_dtd.ib=outer
-o.mi.rf.date_dtd.or=all
-
-o.mf.s.sum=sum(float_fd)
-o.mf.s.mean=mean(float_fd)
-o.mf.s.median=median(float_fd)
-o.mf.s.count=count(float_fd)
-o.mf.s.sumOfSquares=sumofsquares(float_fd)
-o.mf.rf=long_ld
-o.mf.rf.long_ld.st=0
-o.mf.rf.long_ld.e=29
-o.mf.rf.long_ld.g=1,4
-o.mf.rf.long_ld.ib=all
-o.mf.rf.long_ld.or=all
-o.mf.rf=double_dd
-o.mf.rf.double_dd.st=4
-o.mf.rf.double_dd.e=47
-o.mf.rf.double_dd.g=2,3,11
-o.mf.rf.double_dd.ib=edge
-o.mf.rf.double_dd.or=all
-o.mf.rf=date_dtd
-o.mf.rf.date_dtd.st=1004-01-01T23:59:59Z
-o.mf.rf.date_dtd.e=1046-01-01T23:59:59Z
-o.mf.rf.date_dtd.g=+4YEARS,+5YEARS
-o.mf.rf.date_dtd.ib=upper
-o.mf.rf.date_dtd.ib=edge
-o.mf.rf.date_dtd.or=all
-
-o.pf.s.mean=mean(float_fd)
-o.pf.hs.min=min(date_dtd)
-o.pf.hs.max=max(date_dtd)
-o.pf.hs.gap=const_str(+5YEARS)
-o.pf.rf=date_dtd
-o.pf.rf.date_dtd.st=result(min)
-o.pf.rf.date_dtd.e=result(max)
-o.pf.rf.date_dtd.g=result(gap)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/expressions.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/expressions.xml b/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/expressions.xml
deleted file mode 100644
index 2ce8abf..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/expressions.xml
+++ /dev/null
@@ -1,285 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<analyticsRequestEnvelope stats="true" olap="true">
-   <analyticsRequest>
-     <name>Add Request</name>
-     
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>unique(long(long_ld))</expression>
-       <name>unique</name>
-     </statistic>
-     <statistic>
-       <expression>add(sum(int(int_id)),unique(long(long_ld)))</expression>
-       <name>add sum and unique</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>count(long(long_ld))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>median(int(int_id))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>add(mean(int(int_id)),count(long(long_ld)),median(int(int_id)))</expression>
-       <name>add mean and count and median</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Multiply Request</name>
-     
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>unique(long(long_ld))</expression>
-       <name>unique</name>
-     </statistic>
-     <statistic>
-       <expression>mult(sum(int(int_id)),unique(long(long_ld)))</expression>
-       <name>multiply sum and unique</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>count(long(long_ld))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>median(int(int_id))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>mult(mean(int(int_id)),count(long(long_ld)),median(int(int_id)))</expression>
-       <name>multiply mean and count and median</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Divide Request</name>
-     
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>unique(long(long_ld))</expression>
-       <name>unique</name>
-     </statistic>
-     <statistic>
-       <expression>div(sum(int(int_id)),unique(long(long_ld)))</expression>
-       <name>divide sum by unique</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>count(long(long_ld))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>div(mean(int(int_id)),count(long(long_ld)))</expression>
-       <name>divide mean by count</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Power Request</name>
-     
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>unique(long(long_ld))</expression>
-       <name>unique</name>
-     </statistic>
-     <statistic>
-       <expression>pow(sum(int(int_id)),unique(long(long_ld)))</expression>
-       <name>power sum by unique</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>count(long(long_ld))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>pow(mean(int(int_id)),count(long(long_ld)))</expression>
-       <name>power mean by count</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Negate Request</name>
-     
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>neg(sum(int(int_id)))</expression>
-       <name>negate of sum</name>
-     </statistic>
-     
-     <statistic>
-       <expression>count(long(long_ld))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>neg(count(long(long_ld)))</expression>
-       <name>negate of count</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Const Num Request</name>
-     
-     <statistic>
-       <expression>const_num(8)</expression>
-       <name>constant 8</name>
-     </statistic>
-     <statistic>
-       <expression>const_num(10)</expression>
-       <name>constant 10</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Date Math Request</name>
-     
-     <statistic>
-       <expression>median(date(date_dtd))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>const_str(+2YEARS)</expression>
-       <name>constant str median</name>
-     </statistic>
-     <statistic>
-       <expression>date_math(median(date(date_dtd)),const_str(+2YEARS))</expression>
-       <name>date math median</name>
-     </statistic>
-     
-     <statistic>
-       <expression>max(date(date_dtd))</expression>
-       <name>max</name>
-     </statistic>
-     <statistic>
-       <expression>const_str(+2MONTHS)</expression>
-       <name>constant str max</name>
-     </statistic>
-     <statistic>
-       <expression>date_math(max(date(date_dtd)),const_str(+2MONTHS))</expression>
-       <name>date math max</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Constant Date Request</name>
-     
-     <statistic>
-       <expression>const_str(1800-12-31T23:59:59Z)</expression>
-       <name>const str 1</name>
-     </statistic>
-     <statistic>
-       <expression>const_date(1800-12-31T23:59:59Z)</expression>
-       <name>const date 1</name>
-     </statistic>
-     <statistic>
-       <expression>const_str(1804-06-30T23:59:59Z)</expression>
-       <name>const str 2</name>
-     </statistic>
-     <statistic>
-       <expression>const_date(1804-06-30T23:59:59Z)</expression>
-       <name>const date 2</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Constant String Request</name>
-     
-     <statistic>
-       <expression>const_str(this is the first)</expression>
-       <name>const str 1</name>
-     </statistic>
-     <statistic>
-       <expression>const_str(this is the second)</expression>
-       <name>const str 2</name>
-     </statistic>
-     <statistic>
-       <expression>const_str(this is the third)</expression>
-       <name>const str 3</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Concatenate Request</name>
-     
-     <statistic>
-       <expression>const_str(this is the first)</expression>
-       <name>const str min</name>
-     </statistic>
-     <statistic>
-       <expression>min(str(string_sd))</expression>
-       <name>min</name>
-     </statistic>
-     <statistic>
-       <expression>concat(const_str(this is the first),min(str(string_sd)))</expression>
-       <name>concat const and min</name>
-     </statistic>
-     
-     <statistic>
-       <expression>const_str(this is the second)</expression>
-       <name>const str max</name>
-     </statistic>
-     <statistic>
-       <expression>max(str(string_sd))</expression>
-       <name>max</name>
-     </statistic>
-     <statistic>
-       <expression>concat(const_str(this is the second),max(str(string_sd)))</expression>
-       <name>concat const and max</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Reverse Request</name>
-     
-     <statistic>
-       <expression>min(str(string_sd))</expression>
-       <name>min</name>
-     </statistic>
-     <statistic>
-       <expression>rev(min(str(string_sd)))</expression>
-       <name>reverse min</name>
-     </statistic>
-     
-     <statistic>
-       <expression>max(str(string_sd))</expression>
-       <name>max</name>
-     </statistic>
-     <statistic>
-       <expression>rev(max(str(string_sd)))</expression>
-       <name>reverse max</name>
-     </statistic>
-   </analyticsRequest>
-</analyticsRequestEnvelope> 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/fieldFacetExtras.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/fieldFacetExtras.xml b/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/fieldFacetExtras.xml
deleted file mode 100644
index 68b5be9..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/fieldFacetExtras.xml
+++ /dev/null
@@ -1,101 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<analyticsRequestEnvelope stats="true" olap="true">
-   <analyticsRequest>
-     <name>sort request</name>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>median(int(int_id))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>count(int(int_id))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,int(int_id))</expression>
-       <name>perc_20</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>long_ld</field>
-       <sortSpecification>
-         <statName>mean</statName>
-         <direction>asc</direction>
-       </sortSpecification>
-     </fieldFacet>
-     <fieldFacet>
-       <field>float_fd</field>
-       <sortSpecification>
-         <statName>median</statName>
-         <direction>desc</direction>
-       </sortSpecification>
-     </fieldFacet>
-     <fieldFacet>
-       <field>double_dd</field>
-       <sortSpecification>
-         <statName>count</statName>
-         <direction>asc</direction>
-       </sortSpecification>
-     </fieldFacet>
-     <fieldFacet>
-       <field>string_sd</field>
-       <sortSpecification>
-         <statName>perc_20</statName>
-         <direction>desc</direction>
-       </sortSpecification>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>limit request</name>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>median(int(int_id))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>count(int(int_id))</expression>
-       <name>count</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,int(int_id))</expression>
-       <name>perc_20</name>
-     </statistic>
-     
-     <fieldFacet limit="5">
-       <field>long_ld</field>
-       <sortSpecification>
-         <statName>mean</statName>
-         <direction>asc</direction>
-       </sortSpecification>
-     </fieldFacet>
-     <fieldFacet limit="3">
-       <field>float_fd</field>
-       <sortSpecification>
-         <statName>median</statName>
-         <direction>desc</direction>
-       </sortSpecification>
-     </fieldFacet>
-     <fieldFacet limit="7">
-       <field>double_dd</field>
-       <sortSpecification>
-         <statName>count</statName>
-         <direction>asc</direction>
-       </sortSpecification>
-     </fieldFacet>
-     <fieldFacet limit="1">
-       <field>string_sd</field>
-       <sortSpecification>
-         <statName>perc_20</statName>
-         <direction>desc</direction>
-       </sortSpecification>
-     </fieldFacet>
-   </analyticsRequest>
-</analyticsRequestEnvelope>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/fieldFacets.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/fieldFacets.xml b/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/fieldFacets.xml
deleted file mode 100644
index 8e84cf1..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/fieldFacets.xml
+++ /dev/null
@@ -1,496 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<analyticsRequestEnvelope stats="true" olap="true">
-   <analyticsRequest>
-     <name>sum</name>
-     
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>sum(long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>sum(float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>sum(double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>mean</name>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>mean(long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>mean(float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>mean(double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>sumOfSquares</name>
-     
-     <statistic>
-       <expression>sumofsquares(int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>stddev</name>
-     
-     <statistic>
-       <expression>stddev(int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>stddev(long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>stddev(float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>stddev(double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>median</name>
-     
-     <statistic>
-       <expression>median(int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>median(long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>median(float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>median(double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>perc_20 numeric</name>
-     
-     <statistic>
-       <expression>perc(20,int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>perc_20</name>
-     
-     <statistic>
-       <expression>perc(20,str(string_sd))</expression>
-       <name>str</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,date(date_dtd))</expression>
-       <name>date</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>int_id</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>long_ld</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>perc_60 numeric</name>
-     
-     <statistic>
-       <expression>perc(60,int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>perc(60,long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>perc(60,float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>perc(60,double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>perc_60</name>
-     
-     <statistic>
-       <expression>perc(60,str(string_sd))</expression>
-       <name>str</name>
-     </statistic>
-     <statistic>
-       <expression>perc(60,date(date_dtd))</expression>
-       <name>date</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>int_id</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>long_ld</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>min numeric</name>
-     
-     <statistic>
-       <expression>min(int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>min(long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>min(float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>min(double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>min</name>
-     
-     <statistic>
-       <expression>min(str(string_sd))</expression>
-       <name>str</name>
-     </statistic>
-     <statistic>
-       <expression>min(date(date_dtd))</expression>
-       <name>date</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>int_id</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>long_ld</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>max numeric</name>
-     
-     <statistic>
-       <expression>max(int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>max(long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>max(float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>max(double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>max</name>
-     
-     <statistic>
-       <expression>max(str(string_sd))</expression>
-       <name>str</name>
-     </statistic>
-     <statistic>
-       <expression>max(date(date_dtd))</expression>
-       <name>date</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>int_id</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>long_ld</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>count numeric</name>
-     
-     <statistic>
-       <expression>count(int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>count(long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>count(float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>count(double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>count</name>
-     
-     <statistic>
-       <expression>count(str(string_sd))</expression>
-       <name>str</name>
-     </statistic>
-     <statistic>
-       <expression>count(date(date_dtd))</expression>
-       <name>date</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>int_id</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>long_ld</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>unique numeric</name>
-     
-     <statistic>
-       <expression>unique(int(int_id))</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>unique(long(long_ld))</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>unique(float(float_fd))</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>unique(double(double_dd))</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>unique</name>
-     
-     <statistic>
-       <expression>unique(str(string_sd))</expression>
-       <name>str</name>
-     </statistic>
-     <statistic>
-       <expression>unique(date(date_dtd))</expression>
-       <name>date</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>int_id</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>long_ld</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>missing numeric</name>
-     
-     <statistic>
-       <expression>missing(int{int_id})</expression>
-       <name>int</name>
-     </statistic>
-     <statistic>
-       <expression>missing(long{long_ld})</expression>
-       <name>long</name>
-     </statistic>
-     <statistic>
-       <expression>missing(float{float_fd})</expression>
-       <name>float</name>
-     </statistic>
-     <statistic>
-       <expression>missing(double{double_dd})</expression>
-       <name>double</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>missing</name>
-     
-     <statistic>
-       <expression>missing(str{string_sd})</expression>
-       <name>str</name>
-     </statistic>
-     <statistic>
-       <expression>missing(date{date_dtd})</expression>
-       <name>date</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>int_id</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>long_ld</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>multivalued</name>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>long_ldm</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>string_sdm</field>
-     </fieldFacet>
-     <fieldFacet>
-       <field>date_dtdm</field>
-     </fieldFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>missing facet</name>
-
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     
-     <fieldFacet>
-       <field>date_dtd</field>
-     </fieldFacet>
-     <fieldFacet showMissing="true">
-       <field>string_sd</field>
-     </fieldFacet>
-     <fieldFacet showMissing="true">
-       <field>date_dtdm</field>
-     </fieldFacet>
-   </analyticsRequest>
-</analyticsRequestEnvelope>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/functions.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/functions.xml b/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/functions.xml
deleted file mode 100644
index 8fa92b6..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/functions.xml
+++ /dev/null
@@ -1,246 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<analyticsRequestEnvelope stats="true" olap="true">
-   <analyticsRequest>
-     <name>Add Request</name>
-     
-     <statistic>
-       <expression>sum(add(int(int_id),float(float_fd)))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>sum(double(add_if_dd))</expression>
-       <name>sum calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(add(long(long_ld),double(double_dd),float(float_fd)))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>mean(double(add_ldf_dd))</expression>
-       <name>mean calced</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Multiply Request</name>
-     
-     <statistic>
-       <expression>sum(mult(int(int_id),float(float_fd)))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>sum(double(mult_if_dd))</expression>
-       <name>sum calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(mult(long(long_ld),double(double_dd),float(float_fd)))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>mean(double(mult_ldf_dd))</expression>
-       <name>mean calced</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Divide Request</name>
-     
-     <statistic>
-       <expression>sum(div(int(int_id),float(float_fd)))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>sum(double(div_if_dd))</expression>
-       <name>sum calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(div(long(long_ld),double(double_dd)))</expression>
-       <name>mean</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(double(div_ld_dd))</expression>
-       <name>mean calced</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Power Request</name>
-     
-     <statistic>
-       <expression>sum(pow(int(int_id),float(float_fd))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>sum(double(pow_if_dd))</expression>
-       <name>sum calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(pow(long(long_ld),double(double_dd)))</expression>
-       <name>mean</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(double(pow_ld_dd))</expression>
-       <name>mean calced</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Negate Request</name>
-     
-     <statistic>
-       <expression>sum(neg(int(int_id)))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>sum(double(neg_i_dd))</expression>
-       <name>sum calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(neg(long(long_ld)))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>mean(double(neg_l_dd))</expression>
-       <name>mean calced</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Const Num Request</name>
-     
-     <statistic>
-       <expression>sum(const_num(8))</expression>
-       <name>sum</name>
-     </statistic>
-     <statistic>
-       <expression>sum(double(const_8_dd))</expression>
-       <name>sum calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(const_num(10))</expression>
-       <name>mean</name>
-     </statistic>
-     <statistic>
-       <expression>mean(double(const_10_dd))</expression>
-       <name>mean calced</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Date Math Request</name>
-     
-     <statistic>
-       <expression>median(date_math(date(date_dtd),const_str(+2YEARS)))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>median(date(dm_2y_dtd))</expression>
-       <name>median calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>max(date_math(date(date_dtd),const_str(+2MONTHS)))</expression>
-       <name>max</name>
-     </statistic>
-     <statistic>
-       <expression>max(date(dm_2m_dtd))</expression>
-       <name>max calced</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Constant Date Request</name>
-     
-     <statistic>
-       <expression>median(const_date(1800-06-30T23:59:59Z))</expression>
-       <name>median</name>
-     </statistic>
-     <statistic>
-       <expression>median(date(const_00_dtd))</expression>
-       <name>median calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>max(const_date(1804-06-30T23:59:59Z))</expression>
-       <name>max</name>
-     </statistic>
-     <statistic>
-       <expression>max(date(const_04_dtd))</expression>
-       <name>max calced</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Constant String Request</name>
-     
-     <statistic>
-       <expression>min(const_str(this is the first))</expression>
-       <name>min</name>
-     </statistic>
-     <statistic>
-       <expression>min(str(const_first_sd))</expression>
-       <name>min calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>max(const_str(this is the second))</expression>
-       <name>max</name>
-     </statistic>
-     <statistic>
-       <expression>max(str(const_second_sd))</expression>
-       <name>max calced</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Concatenate Request</name>
-     
-     <statistic>
-       <expression>min(concat(const_str(this is the first),str(string_sd)))</expression>
-       <name>min</name>
-     </statistic>
-     <statistic>
-       <expression>min(str(concat_first_sd))</expression>
-       <name>min calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>max(concat(const_str(this is the second),str(string_sd)))</expression>
-       <name>max</name>
-     </statistic>
-     <statistic>
-       <expression>max(str(concat_second_sd))</expression>
-       <name>max calced</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Reverse Request</name>
-     
-     <statistic>
-       <expression>min(rev(str(string_sd)))</expression>
-       <name>min</name>
-     </statistic>
-     <statistic>
-       <expression>min(str(rev_sd))</expression>
-       <name>min calced</name>
-     </statistic>
-     
-     <statistic>
-       <expression>max(rev(str(string_sd)))</expression>
-       <name>max</name>
-     </statistic>
-     <statistic>
-       <expression>max(str(rev_sd))</expression>
-       <name>max calced</name>
-     </statistic>
-   </analyticsRequest>
-</analyticsRequestEnvelope> 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/noFacets.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/noFacets.xml b/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/noFacets.xml
deleted file mode 100644
index 2813d18..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/noFacets.xml
+++ /dev/null
@@ -1,310 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<analyticsRequestEnvelope stats="true" olap="true">
-   <analyticsRequest>
-     <name>Sum Request</name>
-     
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>sum(long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>sum(float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>sum(double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>SumOfSquares Request</name>
-     
-     <statistic>
-       <expression>sumofsquares(int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>sumofsquares(double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Mean Request</name>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>mean(long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>mean(float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>mean(double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Stddev Request</name>
-     
-     <statistic>
-       <expression>stddev(int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>stddev(long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>stddev(float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>stddev(double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Median Request</name>
-     
-     <statistic>
-       <expression>median(int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>median(long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>median(float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>median(double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Perc 20 Request</name>
-     
-     <statistic>
-       <expression>perc(20,int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,date(date_dtd))</expression>
-       <name>date_dtd</name>
-     </statistic>
-     <statistic>
-       <expression>perc(20,str(string_sd))</expression>
-       <name>string_sd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Perc 60 Request</name>
-     
-     <statistic>
-       <expression>perc(60,int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>perc(60,long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>perc(60,float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>perc(60,double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-     <statistic>
-       <expression>perc(60,date(date_dtd))</expression>
-       <name>date_dtd</name>
-     </statistic>
-     <statistic>
-       <expression>perc(60,str(string_sd))</expression>
-       <name>string_sd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Min Request</name>
-     
-     <statistic>
-       <expression>min(int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>min(long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>min(float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>min(double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-     <statistic>
-       <expression>min(date(date_dtd))</expression>
-       <name>date_dtd</name>
-     </statistic>
-     <statistic>
-       <expression>min(str(string_sd))</expression>
-       <name>string_sd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Max Request</name>
-     
-     <statistic>
-       <expression>max(int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>max(long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>max(float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>max(double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-     <statistic>
-       <expression>max(date(date_dtd))</expression>
-       <name>date_dtd</name>
-     </statistic>
-     <statistic>
-       <expression>max(str(string_sd))</expression>
-       <name>string_sd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Unique Request</name>
-     
-     <statistic>
-       <expression>unique(int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>unique(long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>unique(float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>unique(double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-     <statistic>
-       <expression>unique(date(date_dtd))</expression>
-       <name>date_dtd</name>
-     </statistic>
-     <statistic>
-       <expression>unique(str(string_sd))</expression>
-       <name>string_sd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Count Request</name>
-     
-     <statistic>
-       <expression>count(int(int_id))</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>count(long(long_ld))</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>count(float(float_fd))</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>count(double(double_dd))</expression>
-       <name>double_dd</name>
-     </statistic>
-     <statistic>
-       <expression>count(date(date_dtd))</expression>
-       <name>date_dtd</name>
-     </statistic>
-     <statistic>
-       <expression>count(str(string_sd))</expression>
-       <name>string_sd</name>
-     </statistic>
-   </analyticsRequest>
-   
-   <analyticsRequest>
-     <name>Missing Request</name>
-          
-     <statistic>
-       <expression>missing(int{int_id})</expression>
-       <name>int_id</name>
-     </statistic>
-     <statistic>
-       <expression>missing(long{long_ld})</expression>
-       <name>long_ld</name>
-     </statistic>
-     <statistic>
-       <expression>missing(float{float_fd})</expression>
-       <name>float_fd</name>
-     </statistic>
-     <statistic>
-       <expression>missing(double{double_dd})</expression>
-       <name>double_dd</name>
-     </statistic>
-     <statistic>
-       <expression>missing(date{date_dtd})</expression>
-       <name>date_dtd</name>
-     </statistic>
-     <statistic>
-       <expression>missing(str{string_sd})</expression>
-       <name>string_sd</name>
-     </statistic>
-   </analyticsRequest>
-</analyticsRequestEnvelope> 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/queryFacets.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/queryFacets.xml b/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/queryFacets.xml
deleted file mode 100644
index f5c7191..0000000
--- a/solr/contrib/analytics/src/test-files/analytics/requestXMLFiles/queryFacets.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<analyticsRequestEnvelope stats="true" olap="true">
-   <analyticsRequest>
-     <name>int request</name>
-     
-     <statistic>
-       <expression>sum(int(int_id))</expression>
-       <name>sum</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(int(int_id))</expression>
-       <name>mean</name>
-     </statistic>
-     
-     <statistic>
-       <expression>median(int(int_id))</expression>
-       <name>median</name>
-     </statistic>
-     
-     <statistic>
-       <expression>perc(8,int(int_id))</expression>
-       <name>perc_8</name>
-     </statistic>
-     
-     <queryFacet>
-       <name>float1</name>
-       <query>float_fd:[* TO 50]</query>
-     </queryFacet>
-     <queryFacet>
-       <name>float2</name>
-       <query>float_fd:[* TO 30]</query>
-     </queryFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>long request</name>
-     
-     <statistic>
-       <expression>sum(long(long_ld))</expression>
-       <name>sum</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(long(long_ld))</expression>
-       <name>mean</name>
-     </statistic>
-     
-     <statistic>
-       <expression>median(long(long_ld))</expression>
-       <name>median</name>
-     </statistic>
-     
-     <statistic>
-       <expression>perc(8,long(long_ld))</expression>
-       <name>perc_8</name>
-     </statistic>
-     
-     <queryFacet>
-       <name>string</name>
-       <query>string_sd:abc1</query>
-       <query>string_sd:abc2</query>
-     </queryFacet>
-   </analyticsRequest>
-   <analyticsRequest>
-     <name>float request</name>
-     
-     <statistic>
-       <expression>sum(float(float_fd))</expression>
-       <name>sum</name>
-     </statistic>
-     
-     <statistic>
-       <expression>mean(float(float_fd))</expression>
-       <name>mean</name>
-     </statistic>
-     
-     <statistic>
-       <expression>median(float(float_fd))</expression>
-       <name>median</name>
-     </statistic>
-     
-     <statistic>
-       <expression>perc(8,float(float_fd))</expression>
-       <name>perc_8</name>
-     </statistic>
-     
-     <queryFacet>
-       <name>long and double</name>
-       <query>long_ld:[20 TO *]</query>
-       <query>long_ld:[30 TO *]</query>
-       <query>double_dd:[* TO 50]</query>
-     </queryFacet>
-   </analyticsRequest>
-</analyticsRequestEnvelope>


[24/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-6807: requestDispatcher/@handleSelect now defaults to false; stop using it. Deprecated StandardRequestHandler; stop using it.

Posted by ab...@apache.org.
SOLR-6807: requestDispatcher/@handleSelect now defaults to false; stop using it.
Deprecated StandardRequestHandler; stop using it.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/82a44beb
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/82a44beb
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/82a44beb

Branch: refs/heads/jira/solr-10879
Commit: 82a44beb3cbb685e4d30d55d06eb78f012afb93c
Parents: d5963be
Author: David Smiley <ds...@apache.org>
Authored: Wed Jun 28 17:22:43 2017 -0400
Committer: David Smiley <ds...@apache.org>
Committed: Wed Jun 28 17:22:44 2017 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  12 +
 .../collection1/conf/solrconfig-icucollate.xml  |   2 +-
 .../collection1/conf/solrconfig-analytics.xml   |   2 +-
 .../solr/collection1/conf/solrconfig.xml        |  20 +-
 .../clustering/ClusteringComponentTest.java     |   2 +-
 .../collection1/conf/dataimport-solrconfig.xml  |  40 ++--
 .../conf/contentstream-solrconfig.xml           |  42 ++--
 .../conf/dataimport-nodatasource-solrconfig.xml |  42 ++--
 .../collection1/conf/dataimport-solrconfig.xml  |  42 ++--
 .../solr/collection1/conf/solrconfig.xml        |  37 +--
 .../extraction/TestXLSXResponseWriter.java      |   2 +-
 .../conf/solrconfig-languageidentifier.xml      |   4 +-
 .../uima/solr/collection1/conf/solrconfig.xml   |  25 +-
 .../uima/uima-tokenizers-solrconfig.xml         |  15 +-
 .../java/org/apache/solr/core/SolrConfig.java   |   3 +-
 .../solr/handler/MoreLikeThisHandler.java       |   2 +-
 .../apache/solr/handler/RequestHandlerBase.java |   1 -
 .../solr/handler/StandardRequestHandler.java    |  19 +-
 .../org/apache/solr/util/SolrPluginUtils.java   |  12 +-
 .../resources/SystemCollectionSolrConfig.xml    |   2 +-
 .../collection1/conf/bad-error-solrconfig.xml   |   2 +-
 .../collection1/conf/bad-mpf-solrconfig.xml     |   2 +-
 ...dd-schema-fields-update-processor-chains.xml |   2 +-
 .../conf/solrconfig-altdirectory.xml            |   2 +-
 .../conf/solrconfig-analytics-query.xml         | 227 +------------------
 .../solr/collection1/conf/solrconfig-basic.xml  |   2 +-
 .../conf/solrconfig-blockjoinfacetcomponent.xml |  11 +-
 .../conf/solrconfig-cache-enable-disable.xml    |   4 +-
 .../solr/collection1/conf/solrconfig-cdcr.xml   |   2 +-
 .../conf/solrconfig-cdcrupdatelog.xml           |   2 +-
 .../conf/solrconfig-classification.xml          |   2 +-
 .../conf/solrconfig-collapseqparser.xml         | 125 +---------
 .../conf/solrconfig-components-name.xml         |   4 +-
 .../solrconfig-configurerecoverystrategy.xml    |   2 +-
 .../conf/solrconfig-customrecoverystrategy.xml  |   2 +-
 .../conf/solrconfig-delaying-component.xml      |   2 +-
 .../collection1/conf/solrconfig-delpolicy1.xml  |   2 +-
 .../collection1/conf/solrconfig-delpolicy2.xml  |   2 +-
 ...lrconfig-distrib-update-processor-chains.xml |   3 +-
 .../conf/solrconfig-doctransformers.xml         |   4 +-
 .../collection1/conf/solrconfig-elevate.xml     |   2 +-
 .../solrconfig-externalversionconstraint.xml    |   2 +-
 .../conf/solrconfig-functionquery.xml           |   4 +-
 .../solr/collection1/conf/solrconfig-hash.xml   |   4 +-
 .../collection1/conf/solrconfig-headers.xml     |   2 +-
 .../collection1/conf/solrconfig-highlight.xml   |   2 +-
 .../conf/solrconfig-implicitproperties.xml      |   2 +-
 .../conf/solrconfig-infixsuggesters.xml         |   2 +-
 .../conf/solrconfig-logmergepolicyfactory.xml   |   2 +-
 .../conf/solrconfig-managed-schema-test.xml     |   2 +-
 .../conf/solrconfig-managed-schema.xml          |   4 +-
 .../conf/solrconfig-master-throttled.xml        |   8 +-
 .../solr/collection1/conf/solrconfig-master.xml |   8 +-
 .../conf/solrconfig-master1-keepOneBackup.xml   |   4 +-
 .../collection1/conf/solrconfig-master1.xml     |   8 +-
 .../collection1/conf/solrconfig-master2.xml     |   8 +-
 .../collection1/conf/solrconfig-master3.xml     |   8 +-
 .../conf/solrconfig-mergepolicy-defaults.xml    |   2 +-
 .../conf/solrconfig-mergepolicy-legacy.xml      |   2 +-
 .../solrconfig-mergepolicyfactory-nocfs.xml     |   2 +-
 .../collection1/conf/solrconfig-nocache.xml     |   8 +-
 .../conf/solrconfig-nomergepolicyfactory.xml    |   2 +-
 .../collection1/conf/solrconfig-noopregen.xml   |   2 +-
 .../collection1/conf/solrconfig-paramset.xml    |   2 +-
 ...lrconfig-parsing-update-processor-chains.xml |   2 +-
 .../conf/solrconfig-phrasesuggest.xml           |   2 +-
 .../conf/solrconfig-plugcollector.xml           |  28 +--
 .../conf/solrconfig-postingshighlight.xml       |   2 +-
 .../conf/solrconfig-query-parser-init.xml       |   2 +-
 .../conf/solrconfig-querysender-noquery.xml     |   2 +-
 .../collection1/conf/solrconfig-querysender.xml |   8 +-
 .../collection1/conf/solrconfig-repeater.xml    |   8 +-
 .../collection1/conf/solrconfig-reqHandler.incl |   2 +-
 .../conf/solrconfig-response-log-component.xml  |  16 +-
 .../collection1/conf/solrconfig-schemaless.xml  |   2 +-
 .../conf/solrconfig-script-updateprocessor.xml  |   2 +-
 .../conf/solrconfig-searcher-listeners1.xml     |   2 +-
 .../solr/collection1/conf/solrconfig-slave.xml  |   8 +-
 .../solr/collection1/conf/solrconfig-slave1.xml |   8 +-
 .../conf/solrconfig-solcoreproperties.xml       |   2 +-
 .../solrconfig-sortingmergepolicyfactory.xml    |   4 +-
 .../conf/solrconfig-sortingresponse.xml         |   2 +-
 .../collection1/conf/solrconfig-spatial.xml     |   2 +-
 .../conf/solrconfig-spellcheckcomponent.xml     |  12 +-
 .../conf/solrconfig-spellchecker.xml            |   2 +-
 .../solr/collection1/conf/solrconfig-sql.xml    |   4 +-
 ...-suggestercomponent-context-filter-query.xml |   2 +-
 .../conf/solrconfig-suggestercomponent.xml      |   2 +-
 .../collection1/conf/solrconfig-test-misc.xml   |   4 +-
 .../conf/solrconfig-testxmlparser.xml           |   2 +-
 .../solrconfig-tieredmergepolicyfactory.xml     |   2 +-
 .../solr/collection1/conf/solrconfig-tlog.xml   |   5 +-
 ...nfig-uninvertdocvaluesmergepolicyfactory.xml |   2 +-
 .../conf/solrconfig-update-processor-chains.xml |   2 +-
 ...lrconfig-warmer-randommergepolicyfactory.xml |   2 +-
 .../solr/collection1/conf/solrconfig.xml        |  35 ++-
 .../conf/solrconfig_SimpleTextCodec.xml         |   2 +-
 .../solr/collection1/conf/solrconfig_codec.xml  |   2 +-
 .../solr/collection1/conf/solrconfig_codec2.xml |   2 +-
 .../solr/collection1/conf/solrconfig_perf.xml   |   5 +-
 .../bad-mergepolicy/conf/solrconfig.xml         |   2 +-
 .../configsets/cdcr-source/conf/solrconfig.xml  |   3 +-
 .../configsets/cdcr-target/conf/solrconfig.xml  |   3 +-
 .../exitable-directory/conf/solrconfig.xml      |   2 +-
 .../test-files/solr/crazy-path-to-config.xml    |  10 +-
 .../org/apache/solr/BasicFunctionalityTest.java |   6 +-
 .../org/apache/solr/ConvertedLegacyTest.java    |  46 ++--
 .../apache/solr/DisMaxRequestHandlerTest.java   |   8 +-
 .../test/org/apache/solr/EchoParamsTest.java    |   4 +-
 .../src/test/org/apache/solr/SampleTest.java    |   2 +-
 .../test/org/apache/solr/SolrInfoBeanTest.java  |   4 +-
 .../org/apache/solr/TestDistributedSearch.java  |   6 +-
 .../test/org/apache/solr/cloud/BasicZkTest.java |   2 +-
 .../cloud/TestRandomRequestDistribution.java    |   4 +-
 .../solr/core/AlternateDirectoryTest.java       |   2 +-
 .../apache/solr/core/RequestHandlersTest.java   |   8 +-
 .../test/org/apache/solr/core/SolrCoreTest.java |   2 +-
 .../test/org/apache/solr/core/TestConfig.java   |   4 +-
 .../solr/core/TestQuerySenderListener.java      |   2 +-
 .../solr/core/TestQuerySenderNoQuery.java       |   2 +-
 .../apache/solr/core/TestXIncludeConfig.java    |   2 +-
 .../solr/handler/MoreLikeThisHandlerTest.java   |   1 -
 .../apache/solr/handler/SearchHandlerTest.java  |  80 +++++++
 .../handler/StandardRequestHandlerTest.java     |  88 -------
 .../DistributedSpellCheckComponentTest.java     |  10 +-
 .../handler/component/FacetPivotSmallTest.java  |   1 -
 .../component/ResponseLogComponentTest.java     |  12 +-
 .../component/SpellCheckComponentTest.java      |  10 +-
 .../handler/component/StatsComponentTest.java   |   1 -
 .../handler/component/SuggestComponentTest.java |   2 +-
 .../component/TermVectorComponentTest.java      |   2 +-
 .../highlight/FastVectorHighlighterTest.java    |   2 +-
 .../solr/highlight/HighlighterConfigTest.java   |   2 +-
 .../apache/solr/highlight/HighlighterTest.java  |  84 +++----
 .../metrics/SolrMetricsIntegrationTest.java     |   2 +-
 .../apache/solr/request/SimpleFacetsTest.java   |   4 +-
 .../solr/request/TestIntervalFaceting.java      |   2 +-
 .../search/TestComplexPhraseQParserPlugin.java  |   8 +-
 .../search/join/BlockJoinFacetDistribTest.java  |   2 +-
 .../search/join/BlockJoinFacetRandomTest.java   |   2 +-
 .../search/join/BlockJoinFacetSimpleTest.java   |   2 +-
 .../spelling/DirectSolrSpellCheckerTest.java    |   2 +-
 .../solr/spelling/SpellCheckCollatorTest.java   |  43 ++--
 .../SpellCheckCollatorWithCollapseTest.java     |   2 +-
 .../spelling/WordBreakSolrSpellCheckerTest.java |  16 +-
 .../example-DIH/solr/db/conf/solrconfig.xml     |  24 +-
 .../example-DIH/solr/mail/conf/solrconfig.xml   |  24 +-
 .../example-DIH/solr/solr/conf/solrconfig.xml   |  24 +-
 solr/example/files/conf/solrconfig.xml          |  24 +-
 .../configsets/_default/conf/solrconfig.xml     |  23 +-
 .../conf/solrconfig.xml                         |  23 +-
 .../src/distributed-requests.adoc               |   4 +-
 .../src/the-dismax-query-parser.adoc            |  16 +-
 .../solr/common/params/MoreLikeThisParams.java  |   3 +-
 .../solr/collection1/conf/solrconfig-slave1.xml |   8 +-
 .../solr/collection1/conf/solrconfig-sql.xml    |   4 +-
 .../solrj/solr/collection1/conf/solrconfig.xml  |   4 +-
 .../solr/configsets/ml/conf/solrconfig.xml      |   4 +-
 .../solr/configsets/shared/conf/solrconfig.xml  |   8 +-
 .../configsets/streaming/conf/solrconfig.xml    |   6 +-
 .../solr/multicore/core0/conf/solrconfig.xml    |   8 +-
 .../solr/multicore/core1/conf/solrconfig.xml    |   8 +-
 .../client/solrj/impl/CloudSolrClientTest.java  |   2 +-
 .../java/org/apache/solr/SolrTestCaseJ4.java    |  10 +-
 164 files changed, 561 insertions(+), 1183 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 9578698..be23b3a 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -120,6 +120,13 @@ Upgrading from Solr 6.x
   fields, a new JSON request language, and more. DocValues are now required for any field used in the analytics expression
   whereas previously docValues was not required. Please see SOLR-10123 for details.
 
+* solrconfig.xml: <requestDispatcher handleSelect="..."> now defaults to false when luceneMatchVersion >= 7.0,
+  thus ignoring "qt". Regardless, "qt" is still used as a SolrJ special parameter that specifies the request handler
+  (tail URL path) to use.  If you have request handlers without a leading '/', you can set handleSelect="true"
+  or better yet consider migrating.
+
+* StandardRequestHandler is deprecated. Simply use SearchHandler instead.
+
 New Features
 ----------------------
 * SOLR-9857, SOLR-9858: Collect aggregated metrics from nodes and shard leaders in overseer. (ab)
@@ -351,6 +358,11 @@ Other Changes
   - SOLR-10946: Randomize the usage of Points based numerics in solrj test schemas (hossman)
   - SOLR-10947: Randomize the usage of Points based numerics in contrib test schemas (hossman)
 
+* SOLR-6807: Changed requestDispatcher's handleSelect to default to false, thus ignoring "qt".
+  Simplified configs to not refer to handleSelect or "qt".  Switch all tests that assumed true to assume false
+  (added leading '/' in request handlers). Switch all tests referring to "standard" request handler to
+  instead refer to "/select" with SearchHandler. Deprecated the old StandardRequestHandler. (David Smiley)
+
 ==================  6.7.0 ==================
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/analysis-extras/src/test-files/analysis-extras/solr/collection1/conf/solrconfig-icucollate.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analysis-extras/src/test-files/analysis-extras/solr/collection1/conf/solrconfig-icucollate.xml b/solr/contrib/analysis-extras/src/test-files/analysis-extras/solr/collection1/conf/solrconfig-icucollate.xml
index 8266aae..90c52d7 100644
--- a/solr/contrib/analysis-extras/src/test-files/analysis-extras/solr/collection1/conf/solrconfig-icucollate.xml
+++ b/solr/contrib/analysis-extras/src/test-files/analysis-extras/solr/collection1/conf/solrconfig-icucollate.xml
@@ -22,6 +22,6 @@
   <indexConfig>
     <useCompoundFile>${useCompoundFile:false}</useCompoundFile>
   </indexConfig>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-analytics.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-analytics.xml b/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-analytics.xml
index 31d6437..4c359a6 100644
--- a/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-analytics.xml
+++ b/solr/contrib/analytics/src/test-files/solr/collection1/conf/solrconfig-analytics.xml
@@ -24,7 +24,7 @@
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <arr name="components">
       <str>query</str>
       <str>facet</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/clustering/src/test-files/clustering/solr/collection1/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/clustering/src/test-files/clustering/solr/collection1/conf/solrconfig.xml b/solr/contrib/clustering/src/test-files/clustering/solr/collection1/conf/solrconfig.xml
index 74d903e..8d0f82e 100644
--- a/solr/contrib/clustering/src/test-files/clustering/solr/collection1/conf/solrconfig.xml
+++ b/solr/contrib/clustering/src/test-files/clustering/solr/collection1/conf/solrconfig.xml
@@ -214,12 +214,7 @@
 
   </query>
 
-  <!-- 
-    Let the dispatch filter handler /select?qt=XXX
-    handleSelect=true will use consistent error handling for /select and /update
-    handleSelect=false will use solr1.1 style error formatting
-    -->
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <!--Make sure your system has some authentication before enabling remote streaming!
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     -->
@@ -260,17 +255,8 @@
        <!-- <cacheControl>max-age=30, public</cacheControl> -->
     </httpCaching>
   </requestDispatcher>
-  
-      
-  <!-- requestHandler plugins... incoming queries will be dispatched to the
-     correct handler based on the path or the 'qt' param.
-     Names starting with a '/' are accessed with the a path equal to the 
-     registered name.  Names without a leading '/' are accessed with:
-      http://host/app/select?qt=name
-     If no qt is defined, the requestHandler that declares default="true"
-     will be used.
-  -->
-  <requestHandler name="standard" class="solr.SearchHandler" default="true">
+
+  <requestHandler name="/select" class="solr.SearchHandler">
     <!-- default values for query parameters -->
      <lst name="defaults">
        <str name="echoParams">explicit</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/clustering/src/test/org/apache/solr/handler/clustering/ClusteringComponentTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/clustering/src/test/org/apache/solr/handler/clustering/ClusteringComponentTest.java b/solr/contrib/clustering/src/test/org/apache/solr/handler/clustering/ClusteringComponentTest.java
index bff9f37..8ccc8ed 100644
--- a/solr/contrib/clustering/src/test/org/apache/solr/handler/clustering/ClusteringComponentTest.java
+++ b/solr/contrib/clustering/src/test/org/apache/solr/handler/clustering/ClusteringComponentTest.java
@@ -66,7 +66,7 @@ public class ClusteringComponentTest extends AbstractClusteringTestCase {
     params.add(ClusteringParams.USE_SEARCH_RESULTS, "true");
 
 
-    SolrRequestHandler handler = core.getRequestHandler("standard");
+    SolrRequestHandler handler = core.getRequestHandler("/select");
     SolrQueryResponse rsp;
     rsp = new SolrQueryResponse();
     rsp.addResponseHeader(new SimpleOrderedMap<>());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/dataimporthandler-extras/src/test-files/dihextras/solr/collection1/conf/dataimport-solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/dataimporthandler-extras/src/test-files/dihextras/solr/collection1/conf/dataimport-solrconfig.xml b/solr/contrib/dataimporthandler-extras/src/test-files/dihextras/solr/collection1/conf/dataimport-solrconfig.xml
index 7672cab..d426320 100644
--- a/solr/contrib/dataimporthandler-extras/src/test-files/dihextras/solr/collection1/conf/dataimport-solrconfig.xml
+++ b/solr/contrib/dataimporthandler-extras/src/test-files/dihextras/solr/collection1/conf/dataimport-solrconfig.xml
@@ -144,21 +144,21 @@
          and there is a current searcher handling requests (aka registered). -->
     <!-- QuerySenderListener takes an array of NamedList and executes a
          local query request for each NamedList in sequence. -->
-    <listener event="newSearcher" class="solr.QuerySenderListener">
-      <arr name="queries">
-        <lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst>
-        <lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst>
-        <lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst>
-      </arr>
-    </listener>
+    <!--<listener event="newSearcher" class="solr.QuerySenderListener">-->
+      <!--<arr name="queries">-->
+        <!--<lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst>-->
+        <!--<lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst>-->
+        <!--<lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst>-->
+      <!--</arr>-->
+    <!--</listener>-->
 
     <!-- a firstSearcher event is fired whenever a new searcher is being
          prepared but there is no current registered searcher to handle
          requests or to gain autowarming data from. -->
-    <listener event="firstSearcher" class="solr.QuerySenderListener">
-      <arr name="queries">
-      </arr>
-    </listener>
+    <!--<listener event="firstSearcher" class="solr.QuerySenderListener">-->
+      <!--<arr name="queries">-->
+      <!--</arr>-->
+    <!--</listener>-->
 
     <!-- If a search request comes in and there is no current registered searcher,
          then immediately register the still warming searcher and use it.  If
@@ -173,12 +173,7 @@
 
   </query>
 
-  <!-- 
-    Let the dispatch filter handler /select?qt=XXX
-    handleSelect=true will use consistent error handling for /select and /update
-    handleSelect=false will use solr1.1 style error formatting
-    -->
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <!--Make sure your system has some authentication before enabling remote streaming!
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     -->
@@ -220,16 +215,7 @@
     </httpCaching>
   </requestDispatcher>
   
-      
-  <!-- requestHandler plugins... incoming queries will be dispatched to the
-     correct handler based on the path or the 'qt' param.
-     Names starting with a '/' are accessed with the a path equal to the 
-     registered name.  Names without a leading '/' are accessed with:
-      http://host/app/select?qt=name
-     If no qt is defined, the requestHandler that declares default="true"
-     will be used.
-  -->
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <!-- default values for query parameters -->
      <lst name="defaults">
        <str name="echoParams">explicit</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/contentstream-solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/contentstream-solrconfig.xml b/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/contentstream-solrconfig.xml
index 235b15c..a07ab78 100644
--- a/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/contentstream-solrconfig.xml
+++ b/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/contentstream-solrconfig.xml
@@ -144,21 +144,21 @@
          and there is a current searcher handling requests (aka registered). -->
     <!-- QuerySenderListener takes an array of NamedList and executes a
          local query request for each NamedList in sequence. -->
-    <listener event="newSearcher" class="solr.QuerySenderListener">
-      <arr name="queries">
-        <lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst>
-        <lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst>
-        <lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst>
-      </arr>
-    </listener>
+    <!--<listener event="newSearcher" class="solr.QuerySenderListener">-->
+      <!--<arr name="queries">-->
+        <!--<lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst>-->
+        <!--<lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst>-->
+        <!--<lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst>-->
+      <!--</arr>-->
+    <!--</listener>-->
 
     <!-- a firstSearcher event is fired whenever a new searcher is being
          prepared but there is no current registered searcher to handle
          requests or to gain autowarming data from. -->
-    <listener event="firstSearcher" class="solr.QuerySenderListener">
-      <arr name="queries">
-      </arr>
-    </listener>
+    <!--<listener event="firstSearcher" class="solr.QuerySenderListener">-->
+      <!--<arr name="queries">-->
+      <!--</arr>-->
+    <!--</listener>-->
 
     <!-- If a search request comes in and there is no current registered searcher,
          then immediately register the still warming searcher and use it.  If
@@ -173,12 +173,7 @@
 
   </query>
 
-  <!-- 
-    Let the dispatch filter handler /select?qt=XXX
-    handleSelect=true will use consistent error handling for /select and /update
-    handleSelect=false will use solr1.1 style error formatting
-    -->
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <!--Make sure your system has some authentication before enabling remote streaming!
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     -->
@@ -219,17 +214,8 @@
        <!-- <cacheControl>max-age=30, public</cacheControl> -->
     </httpCaching>
   </requestDispatcher>
-  
-      
-  <!-- requestHandler plugins... incoming queries will be dispatched to the
-     correct handler based on the path or the 'qt' param.
-     Names starting with a '/' are accessed with the a path equal to the 
-     registered name.  Names without a leading '/' are accessed with:
-      http://host/app/select?qt=name
-     If no qt is defined, the requestHandler that declares default="true"
-     will be used.
-  -->
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true">
+
+  <requestHandler name="/select" class="solr.SearchHandler">
     <!-- default values for query parameters -->
      <lst name="defaults">
        <str name="echoParams">explicit</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/dataimport-nodatasource-solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/dataimport-nodatasource-solrconfig.xml b/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/dataimport-nodatasource-solrconfig.xml
index 7f20677..6754f9e 100644
--- a/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/dataimport-nodatasource-solrconfig.xml
+++ b/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/dataimport-nodatasource-solrconfig.xml
@@ -146,21 +146,21 @@
          and there is a current searcher handling requests (aka registered). -->
     <!-- QuerySenderListener takes an array of NamedList and executes a
          local query request for each NamedList in sequence. -->
-    <listener event="newSearcher" class="solr.QuerySenderListener">
-      <arr name="queries">
-        <lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst>
-        <lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst>
-        <lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst>
-      </arr>
-    </listener>
+    <!--<listener event="newSearcher" class="solr.QuerySenderListener">-->
+      <!--<arr name="queries">-->
+        <!--<lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst>-->
+        <!--<lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst>-->
+        <!--<lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst>-->
+      <!--</arr>-->
+    <!--</listener>-->
 
     <!-- a firstSearcher event is fired whenever a new searcher is being
          prepared but there is no current registered searcher to handle
          requests or to gain autowarming data from. -->
-    <listener event="firstSearcher" class="solr.QuerySenderListener">
-      <arr name="queries">
-      </arr>
-    </listener>
+    <!--<listener event="firstSearcher" class="solr.QuerySenderListener">-->
+      <!--<arr name="queries">-->
+      <!--</arr>-->
+    <!--</listener>-->
 
     <!-- If a search request comes in and there is no current registered searcher,
          then immediately register the still warming searcher and use it.  If
@@ -175,12 +175,7 @@
 
   </query>
 
-  <!-- 
-    Let the dispatch filter handler /select?qt=XXX
-    handleSelect=true will use consistent error handling for /select and /update
-    handleSelect=false will use solr1.1 style error formatting
-    -->
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <!--Make sure your system has some authentication before enabling remote streaming!
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     -->
@@ -221,17 +216,8 @@
        <!-- <cacheControl>max-age=30, public</cacheControl> -->
     </httpCaching>
   </requestDispatcher>
-  
-      
-  <!-- requestHandler plugins... incoming queries will be dispatched to the
-     correct handler based on the path or the 'qt' param.
-     Names starting with a '/' are accessed with the a path equal to the 
-     registered name.  Names without a leading '/' are accessed with:
-      http://host/app/select?qt=name
-     If no qt is defined, the requestHandler that declares default="true"
-     will be used.
-  -->
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true">
+
+  <requestHandler name="/select" class="solr.SearchHandler">
     <!-- default values for query parameters -->
      <lst name="defaults">
        <str name="echoParams">explicit</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/dataimport-solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/dataimport-solrconfig.xml b/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/dataimport-solrconfig.xml
index 2eacf8a..a662fd9 100644
--- a/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/dataimport-solrconfig.xml
+++ b/solr/contrib/dataimporthandler/src/test-files/dih/solr/collection1/conf/dataimport-solrconfig.xml
@@ -144,21 +144,21 @@
          and there is a current searcher handling requests (aka registered). -->
     <!-- QuerySenderListener takes an array of NamedList and executes a
          local query request for each NamedList in sequence. -->
-    <listener event="newSearcher" class="solr.QuerySenderListener">
-      <arr name="queries">
-        <lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst>
-        <lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst>
-        <lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst>
-      </arr>
-    </listener>
+    <!--<listener event="newSearcher" class="solr.QuerySenderListener">-->
+      <!--<arr name="queries">-->
+        <!--<lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst>-->
+        <!--<lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst>-->
+        <!--<lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst>-->
+      <!--</arr>-->
+    <!--</listener>-->
 
     <!-- a firstSearcher event is fired whenever a new searcher is being
          prepared but there is no current registered searcher to handle
          requests or to gain autowarming data from. -->
-    <listener event="firstSearcher" class="solr.QuerySenderListener">
-      <arr name="queries">
-      </arr>
-    </listener>
+    <!--<listener event="firstSearcher" class="solr.QuerySenderListener">-->
+      <!--<arr name="queries">-->
+      <!--</arr>-->
+    <!--</listener>-->
 
     <!-- If a search request comes in and there is no current registered searcher,
          then immediately register the still warming searcher and use it.  If
@@ -173,12 +173,7 @@
 
   </query>
 
-  <!-- 
-    Let the dispatch filter handler /select?qt=XXX
-    handleSelect=true will use consistent error handling for /select and /update
-    handleSelect=false will use solr1.1 style error formatting
-    -->
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <!--Make sure your system has some authentication before enabling remote streaming!
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     -->
@@ -219,17 +214,8 @@
        <!-- <cacheControl>max-age=30, public</cacheControl> -->
     </httpCaching>
   </requestDispatcher>
-  
-      
-  <!-- requestHandler plugins... incoming queries will be dispatched to the
-     correct handler based on the path or the 'qt' param.
-     Names starting with a '/' are accessed with the a path equal to the 
-     registered name.  Names without a leading '/' are accessed with:
-      http://host/app/select?qt=name
-     If no qt is defined, the requestHandler that declares default="true"
-     will be used.
-  -->
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true">
+
+  <requestHandler name="/select" class="solr.SearchHandler">
     <!-- default values for query parameters -->
      <lst name="defaults">
        <str name="echoParams">explicit</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/extraction/src/test-files/extraction/solr/collection1/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/extraction/src/test-files/extraction/solr/collection1/conf/solrconfig.xml b/solr/contrib/extraction/src/test-files/extraction/solr/collection1/conf/solrconfig.xml
index 261263e..4dbf082 100644
--- a/solr/contrib/extraction/src/test-files/extraction/solr/collection1/conf/solrconfig.xml
+++ b/solr/contrib/extraction/src/test-files/extraction/solr/collection1/conf/solrconfig.xml
@@ -149,42 +149,9 @@
   </query>
 
 
-  <!-- An alternate set representation that uses an integer hash to store filters (sets of docids).
-       If the set cardinality <= maxSize elements, then HashDocSet will be used instead of the bitset
-       based HashBitset. -->
-
-  <!-- requestHandler plugins... incoming queries will be dispatched to the
-     correct handler based on the 'qt' param matching the
-     name of registered handlers.
-      The "standard" request handler is the default and will be used if qt
-     is not specified in the request.
-  -->
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
-  <requestHandler name="dismax" class="solr.SearchHandler" >
-    <lst name="defaults">
-     <str name="defType">dismax</str>
-    </lst>
-  </requestHandler>
-
-  <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
-    <lst name="defaults">
-      <int name="rows">4</int>
-      <bool name="hl">true</bool>
-      <str name="hl.fl">text,name,subject,title,whitetok</str>
-    </lst>
-  </requestHandler>
-
-  <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
-    <lst name="defaults">
-      <int name="rows">4</int>
-      <bool name="hl">true</bool>
-      <str name="hl.fl">text,name,subject,title,whitetok</str>
-    </lst>
-  </requestHandler>
 
   <requestHandler name="/update/extract" class="org.apache.solr.handler.extraction.ExtractingRequestHandler">
     <str name="parseContext.config">parseContext.xml</str>
@@ -227,7 +194,7 @@
   </highlighting>
 
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/extraction/src/test/org/apache/solr/handler/extraction/TestXLSXResponseWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/extraction/src/test/org/apache/solr/handler/extraction/TestXLSXResponseWriter.java b/solr/contrib/extraction/src/test/org/apache/solr/handler/extraction/TestXLSXResponseWriter.java
index 5c79f0d..7d37844 100644
--- a/solr/contrib/extraction/src/test/org/apache/solr/handler/extraction/TestXLSXResponseWriter.java
+++ b/solr/contrib/extraction/src/test/org/apache/solr/handler/extraction/TestXLSXResponseWriter.java
@@ -228,7 +228,7 @@ public class TestXLSXResponseWriter extends SolrTestCaseJ4 {
 
   // returns first worksheet as XLSXResponseWriter only returns one sheet
   private XSSFSheet getWSResultForQuery(SolrQueryRequest req) throws IOException, Exception {
-    SolrQueryResponse rsp = h.queryAndResponse("standard", req);
+    SolrQueryResponse rsp = h.queryAndResponse("", req);
     return getWSResultForQuery(req, rsp);
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/langid/src/test-files/langid/solr/collection1/conf/solrconfig-languageidentifier.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/langid/src/test-files/langid/solr/collection1/conf/solrconfig-languageidentifier.xml b/solr/contrib/langid/src/test-files/langid/solr/collection1/conf/solrconfig-languageidentifier.xml
index 04b75f2..9ae54ad 100644
--- a/solr/contrib/langid/src/test-files/langid/solr/collection1/conf/solrconfig-languageidentifier.xml
+++ b/solr/contrib/langid/src/test-files/langid/solr/collection1/conf/solrconfig-languageidentifier.xml
@@ -44,11 +44,11 @@
      </lst>
   </requestHandler>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/uima/src/test-files/uima/solr/collection1/conf/solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/uima/src/test-files/uima/solr/collection1/conf/solrconfig.xml b/solr/contrib/uima/src/test-files/uima/solr/collection1/conf/solrconfig.xml
index a79db3f..96392d3 100644
--- a/solr/contrib/uima/src/test-files/uima/solr/collection1/conf/solrconfig.xml
+++ b/solr/contrib/uima/src/test-files/uima/solr/collection1/conf/solrconfig.xml
@@ -315,12 +315,7 @@
 
   </query>
 
-  <!--
-    Let the dispatch filter handler /select?qt=XXX handleSelect=true
-    will use consistent error handling for /select and /update
-    handleSelect=false will use solr1.1 style error formatting
-  -->
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <!--
       Make sure your system has some authentication before enabling
       remote streaming!
@@ -360,17 +355,7 @@
     </httpCaching>
   </requestDispatcher>
 
-
-  <!--
-    requestHandler plugins... incoming queries will be dispatched to the
-    correct handler based on the path or the 'qt' param.
-    Names starting with a '/' are accessed with the a path equal to the
-    registered name. Names without a leading '/' are accessed with:
-    http://host/app/select?qt=name If no qt is defined, the
-    requestHandler that declares default="true" will be used.
-  -->
-  <requestHandler name="standard" class="solr.SearchHandler"
-    default="true">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <!-- default values for query parameters -->
     <lst name="defaults">
       <str name="echoParams">explicit</str>
@@ -387,7 +372,7 @@
     standard SearchHandler with a default query parser of "dismax". see
     http://wiki.apache.org/solr/DisMaxRequestHandler
   -->
-  <requestHandler name="dismax" class="solr.SearchHandler">
+  <requestHandler name="/dismax" class="solr.SearchHandler">
     <lst name="defaults">
       <str name="defType">dismax</str>
       <str name="echoParams">explicit</str>
@@ -427,7 +412,7 @@
     Note how you can register the same handler multiple times with
     different names (and different init parameters)
   -->
-  <requestHandler name="partitioned" class="solr.SearchHandler">
+  <requestHandler name="/partitioned" class="solr.SearchHandler">
     <lst name="defaults">
       <str name="defType">dismax</str>
       <str name="echoParams">explicit</str>
@@ -568,7 +553,7 @@
     example. You will likely want to add the component to your already
     specified request handlers.
   -->
-  <requestHandler name="tvrh"
+  <requestHandler name="/tvrh"
     class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <bool name="tv">true</bool>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/contrib/uima/src/test-files/uima/uima-tokenizers-solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/contrib/uima/src/test-files/uima/uima-tokenizers-solrconfig.xml b/solr/contrib/uima/src/test-files/uima/uima-tokenizers-solrconfig.xml
index 1a0f58b..df7dc1e 100644
--- a/solr/contrib/uima/src/test-files/uima/uima-tokenizers-solrconfig.xml
+++ b/solr/contrib/uima/src/test-files/uima/uima-tokenizers-solrconfig.xml
@@ -314,12 +314,7 @@
 
   </query>
 
-  <!--
-    Let the dispatch filter handler /select?qt=XXX handleSelect=true
-    will use consistent error handling for /select and /update
-    handleSelect=false will use solr1.1 style error formatting
-  -->
-  <requestDispatcher handleSelect="true">
+  <requestDispatcher>
     <!--
       Make sure your system has some authentication before enabling
       remote streaming!
@@ -368,7 +363,7 @@
     http://host/app/select?qt=name If no qt is defined, the
     requestHandler that declares default="true" will be used.
   -->
-  <requestHandler name="standard" class="solr.SearchHandler"
+  <requestHandler name="/select" class="solr.SearchHandler"
     default="true">
     <!-- default values for query parameters -->
     <lst name="defaults">
@@ -386,7 +381,7 @@
     standard SearchHandler with a default query parser of "dismax". see
     http://wiki.apache.org/solr/DisMaxRequestHandler
   -->
-  <requestHandler name="dismax" class="solr.SearchHandler">
+  <requestHandler name="/dismax" class="solr.SearchHandler">
     <lst name="defaults">
       <str name="defType">dismax</str>
       <str name="echoParams">explicit</str>
@@ -426,7 +421,7 @@
     Note how you can register the same handler multiple times with
     different names (and different init parameters)
   -->
-  <requestHandler name="partitioned" class="solr.SearchHandler">
+  <requestHandler name="/partitioned" class="solr.SearchHandler">
     <lst name="defaults">
       <str name="defType">dismax</str>
       <str name="echoParams">explicit</str>
@@ -567,7 +562,7 @@
     example. You will likely want to add the component to your already
     specified request handlers.
   -->
-  <requestHandler name="tvrh"
+  <requestHandler name="/tvrh"
     class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <bool name="tv">true</bool>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/java/org/apache/solr/core/SolrConfig.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/SolrConfig.java b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
index dc7fe28..9942323 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
@@ -308,9 +308,8 @@ public class SolrConfig extends Config implements MapSerializable {
     enableRemoteStreams = getBool(
         "requestDispatcher/requestParsers/@enableRemoteStreaming", false);
 
-    // Let this filter take care of /select?xxx format
     handleSelect = getBool(
-        "requestDispatcher/@handleSelect", true);
+        "requestDispatcher/@handleSelect", !luceneMatchVersion.onOrAfter(Version.LUCENE_7_0_0));
 
     addHttpRequestToContext = getBool(
         "requestDispatcher/requestParsers/@addHttpRequestToContext", false);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java b/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
index 0d12136..62f1016 100644
--- a/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
@@ -249,7 +249,7 @@ public class MoreLikeThisHandler extends RequestHandlerBase
           dbgQuery = true;
           dbgResults = true;
         }
-        // Copied from StandardRequestHandler... perhaps it should be added to doStandardDebug?
+        // TODO resolve duplicated code with DebugComponent.  Perhaps it should be added to doStandardDebug?
         if (dbg == true) {
           try {
             NamedList<Object> dbgInfo = SolrPluginUtils.doStandardDebug(req, q, mlt.getRawMLTQuery(), mltDocs.docList, dbgQuery, dbgResults);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
index 4219768..990d475 100644
--- a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
+++ b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java
@@ -125,7 +125,6 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
   public void init(NamedList args) {
     initArgs = args;
 
-    // Copied from StandardRequestHandler
     if( args != null ) {
       defaults = getSolrParamsFromNamedList(args, "defaults");
       appends = getSolrParamsFromNamedList(args, "appends");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java b/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java
index f167b1d..e87aa68 100644
--- a/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/StandardRequestHandler.java
@@ -18,24 +18,7 @@ package org.apache.solr.handler;
 
 import org.apache.solr.handler.component.*;
 
-/**
- *
- *
- * All of the following options may be configured for this handler
- * in the solrconfig as defaults, and may be overridden as request parameters.
- * (TODO: complete documentation of request parameters here, rather than only
- * on the wiki).
- *
- * <ul>
- * <li> highlight - Set to any value not .equal() to "false" to enable highlight
- * generation</li>
- * <li> highlightFields - Set to a comma- or space-delimited list of fields to
- * highlight.  If unspecified, uses the default query field</li>
- * <li> maxSnippets - maximum number of snippets to generate per field-highlight.
- * </li>
- * </ul>
- *
- */
+@Deprecated
 public class StandardRequestHandler extends SearchHandler 
 {
   //////////////////////// SolrInfoMBeans methods //////////////////////

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
index 1d265c7..01c7c33 100644
--- a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
+++ b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
@@ -88,17 +88,7 @@ import static org.apache.solr.core.PluginInfo.INVARIANTS;
 import static org.apache.solr.core.RequestParams.USEPARAM;
 
 /**
- * <p>Utilities that may be of use to RequestHandlers.</p>
- *
- * <p>
- * Many of these functions have code that was stolen/mutated from
- * StandardRequestHandler.
- * </p>
- *
- * <p>:TODO: refactor StandardRequestHandler to use these utilities</p>
- *
- * <p>:TODO: Many "standard" functionality methods are not cognisant of
- * default parameter settings.
+ * Utilities that may be of use to RequestHandlers.
  */
 public class SolrPluginUtils {
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/resources/SystemCollectionSolrConfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/SystemCollectionSolrConfig.xml b/solr/core/src/resources/SystemCollectionSolrConfig.xml
index 7b1da63..f857561 100644
--- a/solr/core/src/resources/SystemCollectionSolrConfig.xml
+++ b/solr/core/src/resources/SystemCollectionSolrConfig.xml
@@ -10,7 +10,7 @@
       <maxDocs>1</maxDocs>
       <openSearcher>true</openSearcher>
     </autoCommit></updateHandler>
-  <requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
+  <requestHandler name="/select" class="solr.SearchHandler" default="true" />
   <requestHandler name="/blob" class="solr.BlobHandler">
     <lst name="invariants">
       <str name="maxSize">${blob.max.size.mb:5}</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/bad-error-solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-error-solrconfig.xml b/solr/core/src/test-files/solr/collection1/conf/bad-error-solrconfig.xml
index 75014ac..c8bb8cf 100644
--- a/solr/core/src/test-files/solr/collection1/conf/bad-error-solrconfig.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-error-solrconfig.xml
@@ -23,7 +23,7 @@
 
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
 
-  <requestHandler name="my_error_handler" class="solr.ThrowErrorOnInitRequestHandler"></requestHandler>
+  <requestHandler name="/my_error_handler" class="solr.ThrowErrorOnInitRequestHandler"></requestHandler>
 
   <schemaFactory class="ClassicIndexSchemaFactory"/>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/bad-mpf-solrconfig.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-mpf-solrconfig.xml b/solr/core/src/test-files/solr/collection1/conf/bad-mpf-solrconfig.xml
index 0adf321..189d449 100644
--- a/solr/core/src/test-files/solr/collection1/conf/bad-mpf-solrconfig.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-mpf-solrconfig.xml
@@ -30,7 +30,7 @@
   </indexConfig>
 
   <updateHandler class="solr.DirectUpdateHandler2"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
 
   <schemaFactory class="ClassicIndexSchemaFactory"/>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-add-schema-fields-update-processor-chains.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-add-schema-fields-update-processor-chains.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-add-schema-fields-update-processor-chains.xml
index 4541fbc..f2e0f3e 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-add-schema-fields-update-processor-chains.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-add-schema-fields-update-processor-chains.xml
@@ -23,7 +23,7 @@
   -->
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
 
   <schemaFactory class="ManagedIndexSchemaFactory">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-altdirectory.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-altdirectory.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-altdirectory.xml
index cb4cd7c..0c62584 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-altdirectory.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-altdirectory.xml
@@ -20,7 +20,7 @@
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <directoryFactory name="DirectoryFactory" class="org.apache.solr.core.AlternateDirectoryTest$TestFSDirectoryFactory"></directoryFactory>
   <indexReaderFactory name="IndexReaderFactory" class="org.apache.solr.core.AlternateDirectoryTest$TestIndexReaderFactory"></indexReaderFactory >
   <schemaFactory class="ClassicIndexSchemaFactory"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-analytics-query.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-analytics-query.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-analytics-query.xml
index f729afa..fc33e46 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-analytics-query.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-analytics-query.xml
@@ -187,233 +187,12 @@
 If the set cardinality <= maxSize elements, then HashDocSet will be used instead of the bitset
 based HashBitset. -->
 
-  <!-- requestHandler plugins... incoming queries will be dispatched to the
-     correct handler based on the 'qt' param matching the
-     name of registered handlers.
-      The "standard" request handler is the default and will be used if qt
-     is not specified in the request.
+  <!-- requestHandler plugins.
   -->
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
-
-  <requestHandler name="dismax" class="solr.SearchHandler" >
-    <lst name="defaults">
-      <str name="defType">dismax</str>
-      <str name="q.alt">*:*</str>
-      <float name="tie">0.01</float>
-      <str name="qf">
-        text^0.5 features_t^1.0 subject^1.4 title_stemmed^2.0
-      </str>
-      <str name="pf">
-        text^0.2 features_t^1.1 subject^1.4 title_stemmed^2.0 title^1.5
-      </str>
-      <str name="bf">
-        ord(weight)^0.5 recip(rord(iind),1,1000,1000)^0.3
-      </str>
-      <str name="mm">
-        3&lt;-1 5&lt;-2 6&lt;90%
-      </str>
-      <int name="ps">100</int>
-    </lst>
-  </requestHandler>
-
-  <requestHandler name="mock" class="org.apache.solr.core.MockQuerySenderListenerReqHandler"/>
-
-  <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
-    <lst name="defaults">
-      <int name="rows">4</int>
-      <bool name="hl">true</bool>
-      <str name="hl.fl">text,name,subject,title,whitetok</str>
-    </lst>
-  </requestHandler>
-
-  <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
-    <lst name="defaults">
-      <int name="rows">4</int>
-      <bool name="hl">true</bool>
-      <str name="hl.fl">text,name,subject,title,whitetok</str>
-    </lst>
-  </requestHandler>
-
-  <searchComponent name="spellcheck" class="org.apache.solr.handler.component.SpellCheckComponent">
-    <!-- This is slightly different from the field value so we can test dealing with token offset changes -->
-    <str name="queryAnalyzerFieldType">lowerpunctfilt</str>
-
-    <lst name="spellchecker">
-      <str name="name">default</str>
-      <str name="field">lowerfilt</str>
-      <str name="spellcheckIndexDir">spellchecker1</str>
-      <str name="buildOnCommit">false</str>
-    </lst>
-    <lst name="spellchecker">
-      <str name="name">direct</str>
-      <str name="classname">DirectSolrSpellChecker</str>
-      <str name="field">lowerfilt</str>
-      <int name="minQueryLength">3</int>
-    </lst>
-    <lst name="spellchecker">
-      <str name="name">wordbreak</str>
-      <str name="classname">solr.WordBreakSolrSpellChecker</str>
-      <str name="field">lowerfilt</str>
-      <str name="combineWords">true</str>
-      <str name="breakWords">true</str>
-      <int name="maxChanges">10</int>
-    </lst>
-    <lst name="spellchecker">
-      <str name="name">multipleFields</str>
-      <str name="field">lowerfilt1and2</str>
-      <str name="spellcheckIndexDir">spellcheckerMultipleFields</str>
-      <str name="buildOnCommit">false</str>
-    </lst>
-    <!-- Example of using different distance measure -->
-    <lst name="spellchecker">
-      <str name="name">jarowinkler</str>
-      <str name="field">lowerfilt</str>
-      <!-- Use a different Distance Measure -->
-      <str name="distanceMeasure">org.apache.lucene.search.spell.JaroWinklerDistance</str>
-      <str name="spellcheckIndexDir">spellchecker2</str>
-
-    </lst>
-    <lst name="spellchecker">
-      <str name="classname">solr.FileBasedSpellChecker</str>
-      <str name="name">external</str>
-      <str name="sourceLocation">spellings.txt</str>
-      <str name="characterEncoding">UTF-8</str>
-      <str name="spellcheckIndexDir">spellchecker3</str>
-    </lst>
-    <!-- Comparator -->
-    <lst name="spellchecker">
-      <str name="name">freq</str>
-      <str name="field">lowerfilt</str>
-      <str name="spellcheckIndexDir">spellcheckerFreq</str>
-      <!-- comparatorClass be one of:
-        1. score (default)
-        2. freq (Frequency first, then score)
-        3. A fully qualified class name
-       -->
-      <str name="comparatorClass">freq</str>
-      <str name="buildOnCommit">false</str>
-    </lst>
-    <lst name="spellchecker">
-      <str name="name">fqcn</str>
-      <str name="field">lowerfilt</str>
-      <str name="spellcheckIndexDir">spellcheckerFQCN</str>
-      <str name="comparatorClass">org.apache.solr.spelling.SampleComparator</str>
-      <str name="buildOnCommit">false</str>
-    </lst>
-    <lst name="spellchecker">
-      <str name="name">perDict</str>
-      <str name="classname">org.apache.solr.handler.component.DummyCustomParamSpellChecker</str>
-      <str name="field">lowerfilt</str>
-    </lst>
-  </searchComponent>
-
-  <searchComponent name="termsComp" class="org.apache.solr.handler.component.TermsComponent"/>
-
-  <requestHandler name="/terms" class="org.apache.solr.handler.component.SearchHandler">
-    <arr name="components">
-      <str>termsComp</str>
-    </arr>
-  </requestHandler>
-  <!--
-  The SpellingQueryConverter to convert raw (CommonParams.Q) queries into tokens.  Uses a simple regular expression
-   to strip off field markup, boosts, ranges, etc. but it is not guaranteed to match an exact parse from the query parser.
-   -->
-  <queryConverter name="queryConverter" class="org.apache.solr.spelling.SpellingQueryConverter"/>
-
-  <requestHandler name="spellCheckCompRH" class="org.apache.solr.handler.component.SearchHandler">
-    <lst name="defaults">
-      <!-- omp = Only More Popular -->
-      <str name="spellcheck.onlyMorePopular">false</str>
-      <!-- exr = Extended Results -->
-      <str name="spellcheck.extendedResults">false</str>
-      <!--  The number of suggestions to return -->
-      <str name="spellcheck.count">1</str>
-    </lst>
-    <arr name="last-components">
-      <str>spellcheck</str>
-    </arr>
-  </requestHandler>
-  <requestHandler name="spellCheckCompRH_Direct" class="org.apache.solr.handler.component.SearchHandler">
-    <lst name="defaults">
-      <str name="spellcheck.dictionary">direct</str>
-      <str name="spellcheck.onlyMorePopular">false</str>
-      <str name="spellcheck.extendedResults">false</str>
-      <str name="spellcheck.count">1</str>
-    </lst>
-    <arr name="last-components">
-      <str>spellcheck</str>
-    </arr>
-  </requestHandler>
-  <requestHandler name="spellCheckWithWordbreak" class="org.apache.solr.handler.component.SearchHandler">
-    <lst name="defaults">
-      <str name="spellcheck.dictionary">default</str>
-      <str name="spellcheck.dictionary">wordbreak</str>
-      <str name="spellcheck.count">20</str>
-    </lst>
-    <arr name="last-components">
-      <str>spellcheck</str>
-    </arr>
-  </requestHandler>
-  <requestHandler name="spellCheckWithWordbreak_Direct" class="org.apache.solr.handler.component.SearchHandler">
-    <lst name="defaults">
-      <str name="spellcheck.dictionary">direct</str>
-      <str name="spellcheck.dictionary">wordbreak</str>
-      <str name="spellcheck.count">20</str>
-    </lst>
-    <arr name="last-components">
-      <str>spellcheck</str>
-    </arr>
-  </requestHandler>
-  <requestHandler name="spellCheckCompRH1" class="org.apache.solr.handler.component.SearchHandler">
-    <lst name="defaults">
-      <str name="defType">dismax</str>
-      <str name="qf">lowerfilt1^1</str>
-    </lst>
-    <arr name="last-components">
-      <str>spellcheck</str>
-    </arr>
-  </requestHandler>
-
-  <requestHandler name="mltrh" class="org.apache.solr.handler.component.SearchHandler">
-
-  </requestHandler>
-
-  <searchComponent name="tvComponent" class="org.apache.solr.handler.component.TermVectorComponent"/>
-
-  <requestHandler name="tvrh" class="org.apache.solr.handler.component.SearchHandler">
-    <lst name="defaults">
-
-    </lst>
-    <arr name="last-components">
-      <str>tvComponent</str>
-    </arr>
-  </requestHandler>
-
-  <!-- test elevation -->
-  <searchComponent name="elevate" class="org.apache.solr.handler.component.QueryElevationComponent" >
-    <str name="queryFieldType">string</str>
-    <str name="config-file">elevate.xml</str>
-  </searchComponent>
-
-
-  <requestHandler name="/elevate" class="org.apache.solr.handler.component.SearchHandler">
-    <lst name="defaults">
-      <str name="echoParams">explicit</str>
-    </lst>
-    <arr name="last-components">
-      <str>elevate</str>
-    </arr>
-  </requestHandler>
-
-  <requestHandler name="/mlt" class="solr.MoreLikeThisHandler">
-  </requestHandler>
-
-
   <searchComponent class="solr.HighlightComponent" name="highlight">
     <highlighting>
       <!-- Configure the standard fragmenter -->
@@ -461,7 +240,7 @@ based HashBitset. -->
     </highlighting>
   </searchComponent>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-basic.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-basic.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-basic.xml
index ff9fab2..d98ecac 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-basic.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-basic.xml
@@ -25,5 +25,5 @@
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
 </config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-blockjoinfacetcomponent.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-blockjoinfacetcomponent.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-blockjoinfacetcomponent.xml
index b222693..b114535 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-blockjoinfacetcomponent.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-blockjoinfacetcomponent.xml
@@ -24,8 +24,7 @@
   <schemaFactory class="ClassicIndexSchemaFactory"/>
   <dataDir>${solr.data.dir:}</dataDir>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
-  </requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler" />
 
   <requestHandler name="/replication" class="solr.ReplicationHandler" startup="lazy" />
 
@@ -38,18 +37,18 @@
   <searchComponent name="blockJoinFacet" class="org.apache.solr.search.join.BlockJoinFacetComponent"/>
   <searchComponent name="blockJoinDocSetFacet" class="org.apache.solr.search.join.BlockJoinDocSetFacetComponent"/>
 
-  <requestHandler name="blockJoinFacetRH" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/blockJoinFacetRH" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
-      <str name="shards.qt">blockJoinFacetRH</str>
+      <str name="shards.qt">/blockJoinFacetRH</str>
     </lst>
     <arr name="last-components">
       <str>blockJoinFacet</str>
     </arr>
   </requestHandler>
   
-    <requestHandler name="blockJoinDocSetFacetRH" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/blockJoinDocSetFacetRH" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
-      <str name="shards.qt">blockJoinDocSetFacetRH</str>
+      <str name="shards.qt">/blockJoinDocSetFacetRH</str>
     </lst>
     <arr name="last-components">
       <str>blockJoinDocSetFacet</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-cache-enable-disable.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-cache-enable-disable.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-cache-enable-disable.xml
index 5990a81..b8e3dd7 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-cache-enable-disable.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-cache-enable-disable.xml
@@ -23,7 +23,7 @@
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+  <requestHandler name="/select" class="solr.SearchHandler" />
   
   <query>
     <!-- Maximum number of clauses in a boolean query... can affect
@@ -74,7 +74,7 @@
 
   </query>
 
-  <initParams path="standard">
+  <initParams path="/select">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-cdcr.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-cdcr.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-cdcr.xml
index df50f41..c6b360c 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-cdcr.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-cdcr.xml
@@ -37,7 +37,7 @@
 
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
   </requestHandler>
 
   <requestHandler name="/update" class="solr.UpdateRequestHandler">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-cdcrupdatelog.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-cdcrupdatelog.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-cdcrupdatelog.xml
index c9b9d80..86b2d2b 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-cdcrupdatelog.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-cdcrupdatelog.xml
@@ -37,7 +37,7 @@
 
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
   </requestHandler>
 
   <updateHandler class="solr.DirectUpdateHandler2">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-classification.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-classification.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-classification.xml
index f688ed1..3370600 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-classification.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-classification.xml
@@ -23,7 +23,7 @@
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
   <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="solrconfig.snippet.randomindexconfig.xml"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
   

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-collapseqparser.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-collapseqparser.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-collapseqparser.xml
index 8267451..65820e0 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-collapseqparser.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-collapseqparser.xml
@@ -192,77 +192,29 @@ based HashBitset. -->
       The "standard" request handler is the default and will be used if qt
      is not specified in the request.
   -->
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
   </requestHandler>
 
-  <requestHandler name="dismax" class="solr.SearchHandler" >
-    <lst name="defaults">
-      <str name="defType">dismax</str>
-      <str name="q.alt">*:*</str>
-      <float name="tie">0.01</float>
-      <str name="qf">
-        text^0.5 features_t^1.0 subject^1.4 title_stemmed^2.0
-      </str>
-      <str name="pf">
-        text^0.2 features_t^1.1 subject^1.4 title_stemmed^2.0 title^1.5
-      </str>
-      <str name="bf">
-        ord(weight)^0.5 recip(rord(iind),1,1000,1000)^0.3
-      </str>
-      <str name="mm">
-        3&lt;-1 5&lt;-2 6&lt;90%
-      </str>
-      <int name="ps">100</int>
-    </lst>
-  </requestHandler>
-
-  <requestHandler name="mock" class="org.apache.solr.core.MockQuerySenderListenerReqHandler"/>
-
-  <!-- test query parameter defaults -->
-  <requestHandler name="defaults" class="solr.StandardRequestHandler">
-    <lst name="defaults">
-      <int name="rows">4</int>
-      <bool name="hl">true</bool>
-      <str name="hl.fl">text,name,subject,title,whitetok</str>
-    </lst>
-  </requestHandler>
-
-  <!-- test query parameter defaults -->
-  <requestHandler name="lazy" class="solr.StandardRequestHandler" startup="lazy">
-    <lst name="defaults">
-      <int name="rows">4</int>
-      <bool name="hl">true</bool>
-      <str name="hl.fl">text,name,subject,title,whitetok</str>
-    </lst>
-  </requestHandler>
-
   <searchComponent name="spellcheck" class="org.apache.solr.handler.component.SpellCheckComponent">
     <!-- This is slightly different from the field value so we can test dealing with token offset changes -->
     <str name="queryAnalyzerFieldType">a_s</str>
 
-   <lst name="spellchecker">
+    <lst name="spellchecker">
       <str name="name">direct</str>
       <str name="classname">DirectSolrSpellChecker</str>
       <str name="field">a_s</str>
       <int name="minQueryLength">3</int>
-    </lst>    
+    </lst>
   </searchComponent>
 
-  <searchComponent name="termsComp" class="org.apache.solr.handler.component.TermsComponent"/>
-
-  <requestHandler name="/terms" class="org.apache.solr.handler.component.SearchHandler">
-    <arr name="components">
-      <str>termsComp</str>
-    </arr>
-  </requestHandler>
   <!--
   The SpellingQueryConverter to convert raw (CommonParams.Q) queries into tokens.  Uses a simple regular expression
    to strip off field markup, boosts, ranges, etc. but it is not guaranteed to match an exact parse from the query parser.
    -->
   <queryConverter name="queryConverter" class="org.apache.solr.spelling.SpellingQueryConverter"/>
 
-  <requestHandler name="spellCheckCompRH_Direct" class="org.apache.solr.handler.component.SearchHandler">
+  <requestHandler name="/spellCheckCompRH_Direct" class="org.apache.solr.handler.component.SearchHandler">
     <lst name="defaults">
       <str name="spellcheck.dictionary">direct</str>
       <str name="spellcheck.onlyMorePopular">false</str>
@@ -274,21 +226,6 @@ based HashBitset. -->
     </arr>
   </requestHandler>
 
-  <requestHandler name="mltrh" class="org.apache.solr.handler.component.SearchHandler">
-
-  </requestHandler>
-
-  <searchComponent name="tvComponent" class="org.apache.solr.handler.component.TermVectorComponent"/>
-
-  <requestHandler name="tvrh" class="org.apache.solr.handler.component.SearchHandler">
-    <lst name="defaults">
-
-    </lst>
-    <arr name="last-components">
-      <str>tvComponent</str>
-    </arr>
-  </requestHandler>
-
   <!-- test elevation -->
   <searchComponent name="elevate" class="org.apache.solr.handler.component.QueryElevationComponent" >
     <str name="queryFieldType">string</str>
@@ -305,57 +242,7 @@ based HashBitset. -->
     </arr>
   </requestHandler>
 
-  <requestHandler name="/mlt" class="solr.MoreLikeThisHandler">
-  </requestHandler>
-
-  <searchComponent class="solr.HighlightComponent" name="highlight">
-    <highlighting>
-      <!-- Configure the standard fragmenter -->
-      <fragmenter name="gap" class="org.apache.solr.highlight.GapFragmenter" default="true">
-        <lst name="defaults">
-          <int name="hl.fragsize">100</int>
-        </lst>
-      </fragmenter>
-
-      <fragmenter name="regex" class="org.apache.solr.highlight.RegexFragmenter">
-        <lst name="defaults">
-          <int name="hl.fragsize">70</int>
-        </lst>
-      </fragmenter>
-
-      <!-- Configure the standard formatter -->
-      <formatter name="html" class="org.apache.solr.highlight.HtmlFormatter" default="true">
-        <lst name="defaults">
-          <str name="hl.simple.pre"><![CDATA[<em>]]></str>
-          <str name="hl.simple.post"><![CDATA[</em>]]></str>
-        </lst>
-      </formatter>
-
-      <!-- Configure the standard fragListBuilder -->
-      <fragListBuilder name="simple" class="org.apache.solr.highlight.SimpleFragListBuilder" default="true"/>
-
-      <!-- Configure the standard fragmentsBuilder -->
-      <fragmentsBuilder name="simple" class="org.apache.solr.highlight.SimpleFragmentsBuilder" default="true"/>
-      <fragmentsBuilder name="scoreOrder" class="org.apache.solr.highlight.ScoreOrderFragmentsBuilder"/>
-
-      <boundaryScanner name="simple" class="solr.highlight.SimpleBoundaryScanner" default="true">
-        <lst name="defaults">
-          <str name="hl.bs.maxScan">10</str>
-          <str name="hl.bs.chars">.,!? &#9;&#10;&#13;</str>
-        </lst>
-      </boundaryScanner>
-
-      <boundaryScanner name="breakIterator" class="solr.highlight.BreakIteratorBoundaryScanner">
-        <lst name="defaults">
-          <str name="hl.bs.type">WORD</str>
-          <str name="hl.bs.language">en</str>
-          <str name="hl.bs.country">US</str>
-        </lst>
-      </boundaryScanner>
-    </highlighting>
-  </searchComponent>
-
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>
@@ -447,7 +334,7 @@ based HashBitset. -->
     <processor class="solr.RunUpdateProcessorFactory" />
   </updateRequestProcessorChain>
 
-  <initParams path="/elevate,standard">
+  <initParams path="/elevate,/select">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-components-name.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-components-name.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-components-name.xml
index fe0e55c..8d311dd 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-components-name.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-components-name.xml
@@ -42,7 +42,7 @@
   <queryResponseWriter name="xml" default="true"
                        class="solr.XMLResponseWriter" />
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
     <bool name="httpCaching">true</bool>
     <arr name="first-components">
       <str>component1</str>
@@ -52,7 +52,7 @@
     </arr>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-configurerecoverystrategy.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-configurerecoverystrategy.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-configurerecoverystrategy.xml
index 62e671d..d86a6de 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-configurerecoverystrategy.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-configurerecoverystrategy.xml
@@ -20,7 +20,7 @@
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <recoveryStrategy>
     <int name="maxRetries">250</int>
   </recoveryStrategy>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-customrecoverystrategy.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-customrecoverystrategy.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-customrecoverystrategy.xml
index d43ed29..4e8effa 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-customrecoverystrategy.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-customrecoverystrategy.xml
@@ -20,7 +20,7 @@
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
   <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
   <!--
     The RecoveryStrategy and RecoveryStrategy.Builder classes may change in future and customisations
     are not supported between versions in terms of API or back compat behaviour.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-delaying-component.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-delaying-component.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-delaying-component.xml
index 91f1068..c1b1b02 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-delaying-component.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-delaying-component.xml
@@ -34,7 +34,7 @@
     </arr>
   </requestHandler>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher >
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     <httpCaching never304="true" />
   </requestDispatcher>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-delpolicy1.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-delpolicy1.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-delpolicy1.xml
index 36b4b98..424783b 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-delpolicy1.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-delpolicy1.xml
@@ -23,7 +23,7 @@
   <schemaFactory class="ClassicIndexSchemaFactory"/>
 
   <updateHandler class="solr.DirectUpdateHandler2"/>
-  <requestHandler name="standard" class="solr.StandardRequestHandler"/>
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
   <indexConfig>
     <!-- we can't include solrconfig.snippet.randomindexconfig.xml because we need

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-delpolicy2.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-delpolicy2.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-delpolicy2.xml
index 06352f3..bb4d3f8 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-delpolicy2.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-delpolicy2.xml
@@ -43,6 +43,6 @@
     </deletionPolicy>
   </indexConfig>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"></requestHandler>
 </config>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-distrib-update-processor-chains.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-distrib-update-processor-chains.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-distrib-update-processor-chains.xml
index 97ed18b..f91be75 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-distrib-update-processor-chains.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-distrib-update-processor-chains.xml
@@ -43,8 +43,7 @@
    <processor class="solr.RunUpdateProcessorFactory" />
  </updateRequestProcessorChain>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
-  </requestHandler>
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
   <requestHandler name="/get" class="solr.RealTimeGetHandler">
     <lst name="defaults">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-doctransformers.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-doctransformers.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-doctransformers.xml
index b242f11..5a7d65e 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-doctransformers.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-doctransformers.xml
@@ -37,9 +37,9 @@
 
   <transformer name="custom" class="org.apache.solr.response.TestCustomDocTransformer$CustomTransformerFactory" />
 
-  <requestHandler name="/select" class="solr.StandardRequestHandler"/>
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
   </requestDispatcher>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-elevate.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-elevate.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-elevate.xml
index 03efed6..083333c 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-elevate.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-elevate.xml
@@ -150,7 +150,7 @@
     </arr>
   </requestHandler>-->
 
-  <requestDispatcher handleSelect="true" >
+  <requestDispatcher>
     <requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="-1" />
     <httpCaching lastModifiedFrom="openTime" etagSeed="Solr" never304="false">
       <cacheControl>max-age=30, public</cacheControl>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-externalversionconstraint.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-externalversionconstraint.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-externalversionconstraint.xml
index eef941e..3a0adbe 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-externalversionconstraint.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-externalversionconstraint.xml
@@ -109,7 +109,7 @@
     <processor class="solr.RunUpdateProcessorFactory" />
   </updateRequestProcessorChain>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler">
+  <requestHandler name="/select" class="solr.SearchHandler">
   </requestHandler>
 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/82a44beb/solr/core/src/test-files/solr/collection1/conf/solrconfig-functionquery.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-functionquery.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-functionquery.xml
index 10f5e85..ef0c39a 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-functionquery.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-functionquery.xml
@@ -28,7 +28,7 @@
   <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.RAMDirectoryFactory}"/>
   <schemaFactory class="ClassicIndexSchemaFactory"/>
 
-  <requestHandler name="standard" class="solr.StandardRequestHandler"/>
+  <requestHandler name="/select" class="solr.SearchHandler"/>
 
   <updateHandler class="solr.DirectUpdateHandler2"/>
 
@@ -39,7 +39,7 @@
   <valueSourceParser name="nvl" class="org.apache.solr.search.function.NvlValueSourceParser">
     <float name="nvlFloatValue">0.0</float>
   </valueSourceParser>
-  <initParams path="standard">
+  <initParams path="/select">
     <lst name="defaults">
       <str name="df">text</str>
     </lst>


[13/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LogFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LogFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LogFunction.java
new file mode 100644
index 0000000..313f2e2
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LogFunction.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A logarithm mapping function.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If one numeric Value or ValueStream is passed in, a {@link DoubleValue} or {@link DoubleValueStream}
+ * representing the natural logarithm is returned.
+ * <li>If two numeric Values are passed in, a {@link DoubleValue} representing the logarithm of the first with the second as the base is returned.
+ * <li>If a numeric ValueStream and a numeric Value are passed in, a {@link DoubleValueStream} representing the logarithm of 
+ * the Value with each of the values of the ValueStream for a document as the base is returned. 
+ * (Or the other way, since the Value and ValueStream can be used in either order)
+ * </ul>
+ */
+public class LogFunction {
+  public static final String name = "log";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 1.");
+    } else if (params.length == 1) {
+      return LambdaFunction.createDoubleLambdaFunction(name, (a) -> Math.log(a), (DoubleValueStream)params[0]);
+    } else if (params.length == 2) {
+      return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> Math.log(a)/Math.log(b), (DoubleValueStream)params[0], (DoubleValueStream)params[1]);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function accepts at most 2 paramaters, " + params.length + " found.");
+    }
+  });
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LogicFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LogicFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LogicFunction.java
new file mode 100644
index 0000000..806cb0a
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LogicFunction.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.TwoBoolInBoolOutLambda;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.BooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * Contains all logical mapping functions.
+ * <p>
+ * Logical mapping functions can be used in the following ways:
+ * <ul>
+ * <li>If a single {@link BooleanValueStream} is passed in, a {@link BooleanValue} representing the logical operation
+ * on all of the values for each document is returned.
+ * <li>If a {@link BooleanValueStream} and a {@link BooleanValue} are passed in, a {@link BooleanValue} representing the logical operation on 
+ * the {@link BooleanValue} and each of the values of the {@link BooleanValueStream} for a document is returned.
+ * (Or the other way, since the Value and ValueStream can be used in either order)
+ * <li>If multiple {@link BooleanValue}s are passed in, a {@link BooleanValue} representing the logical operation on all values is returned.
+ * </ul>
+ */
+public class LogicFunction {
+  
+  private static BooleanValueStream createBitwiseFunction(String name, TwoBoolInBoolOutLambda comp, AnalyticsValueStream... params) {
+    if (params.length == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires parameters.");
+    } 
+    else if (params.length == 1) {
+      if (params[0] instanceof BooleanValueStream) {
+        return LambdaFunction.createBooleanLambdaFunction(name, comp, (BooleanValueStream)params[0]);
+      }
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires boolean parameters. Incorrect param: "+params[0].getExpressionStr());
+    } 
+    else if (params.length == 2) {
+      AnalyticsValueStream param1 = params[0];
+      AnalyticsValueStream param2 = params[1];
+      if (param1 instanceof BooleanValueStream && param2 instanceof BooleanValueStream) {
+        return LambdaFunction.createBooleanLambdaFunction(name, (a,b) -> a && b, (BooleanValueStream)param1, (BooleanValueStream)param2);
+      }
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires boolean parameters.");
+    }
+    BooleanValue[] castedParams = new BooleanValue[params.length];
+    for (int i = 0; i < params.length; i++) {
+      if (params[i] instanceof BooleanValue) {
+        castedParams[i] = (BooleanValue) params[i];
+      } else {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that all parameters be single-valued if more than 2 are given.");
+      }
+    }
+    return LambdaFunction.createBooleanLambdaFunction(name, comp, castedParams);
+  };
+  
+  /**
+   * A mapping function for the logical operation AND.
+   */
+  public static class AndFunction {
+    public static final String name = "and";
+    public static final CreatorFunction creatorFunction = (params -> {
+      return LogicFunction.createBitwiseFunction(name, (a,b) -> a && b, params);
+    });
+  }
+
+  /**
+   * A mapping function for the logical operation OR.
+   */
+  public static class OrFunction {
+    public static final String name = "or";
+    public static final CreatorFunction creatorFunction = (params -> {
+      return LogicFunction.createBitwiseFunction(name, (a,b) -> a || b, params);
+    });
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/MultFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/MultFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/MultFunction.java
new file mode 100644
index 0000000..4a5b173
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/MultFunction.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+
+/**
+ * An multiplication mapping function.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If a single numeric ValueStream is passed in, a {@link DoubleValue} representing the multiplication of the values for each document is returned.
+ * <li>If a numeric ValueStream and a numeric Value are passed in, a {@link DoubleValueStream} representing the multiplication of 
+ * the Value and each of the values of the ValueStream for a document is returned.
+ * (Or the other way, since the Value and ValueStream can be used in either order)
+ * <li>If multiple numeric Values are passed in, a {@link DoubleValue} representing the multiplication of all values is returned.
+ * </ul>
+ */
+public class MultFunction {
+  public static final String name = "mult";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires parameters.");
+    } 
+    else if (params.length == 1) {
+      if (params[0] instanceof DoubleValueStream) {
+        return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a*b, (DoubleValueStream)params[0]);
+      }
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters. Incorrect param: "+params[0].getExpressionStr());
+    } 
+    else if (params.length == 2) {
+      AnalyticsValueStream param1 = params[0];
+      AnalyticsValueStream param2 = params[1];
+      if (param1 instanceof DoubleValueStream && param2 instanceof DoubleValueStream) {
+        return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a*b, (DoubleValueStream)param1, (DoubleValueStream)param2);
+      }
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters.");
+    }
+    DoubleValue[] castedParams = new DoubleValue[params.length];
+    for (int i = 0; i < params.length; i++) {
+      if (params[i] instanceof DoubleValue) {
+        castedParams[i] = (DoubleValue) params[i];
+      } else {
+        throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that all parameters be single-valued if more than 2 are given.");
+      }
+    }
+    return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a*b, castedParams);
+  });
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/NegateFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/NegateFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/NegateFunction.java
new file mode 100644
index 0000000..65916e6
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/NegateFunction.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.BooleanValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A negation mapping function.
+ * <p>
+ * Takes a numeric or boolean ValueStream or Value and returns a ValueStream or Value of the same numeric type.
+ */
+public class NegateFunction {
+  public static final String name = "neg";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramaters, " + params.length + " found.");
+    }
+    AnalyticsValueStream param = params[0];
+    if (param instanceof BooleanValueStream) {
+      return LambdaFunction.createBooleanLambdaFunction(name, x -> !x, (BooleanValueStream)param);
+    }
+    if (param instanceof IntValueStream) {
+      return LambdaFunction.createIntLambdaFunction(name, x -> x*-1, (IntValueStream)param);
+    }
+    if (param instanceof LongValueStream) {
+      return LambdaFunction.createLongLambdaFunction(name, x -> x*-1, (LongValueStream)param);
+    }
+    if (param instanceof FloatValueStream) {
+      return LambdaFunction.createFloatLambdaFunction(name, x -> x*-1, (FloatValueStream)param);
+    }
+    if (param instanceof DoubleValueStream) {
+      return LambdaFunction.createDoubleLambdaFunction(name, x -> x*-1, (DoubleValueStream)param);
+      }
+    throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a boolean or numeric parameter, "+param.getExpressionStr()+" found.");
+  });
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/NumericConvertFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/NumericConvertFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/NumericConvertFunction.java
new file mode 100644
index 0000000..2381f60
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/NumericConvertFunction.java
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.IntValueStream.AbstractIntValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.LongValueStream.AbstractLongValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * An abstract numeric converting mapping function. For example "round()" would convert a float to an int and a double to a long. 
+ * <p>
+ * Takes a numeric Double or Float ValueStream or Value and returns a Long or Int ValueStream or Value, repectively.
+ */
+public class NumericConvertFunction {
+  
+  private static LongValueStream createConvertFunction(String name, ConvertFloatFunction fconv, ConvertDoubleFunction dconv, AnalyticsValueStream... params) {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramaters, " + params.length + " found.");
+    }
+    AnalyticsValueStream param = params[0];
+    if (param instanceof FloatValueStream) {
+      if (param instanceof FloatValue) {
+        return new ConvertFloatValueFunction(name, (FloatValue)param, fconv);
+      }
+      return new ConvertFloatStreamFunction(name, (FloatValueStream)param, fconv);
+    } else if (param instanceof DoubleValueStream) {
+      if (param instanceof DoubleValue) {
+        return new ConvertDoubleValueFunction(name, (DoubleValue)param, dconv);
+      }
+      return new ConvertDoubleStreamFunction(name, (DoubleValueStream)param, dconv);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a numeric parameter.");
+    }
+  }
+  
+  /**
+   * A numeric mapping function that returns the floor of the input.
+   */
+  public static class FloorFunction {
+    public static final String name = "floor";
+    public static final CreatorFunction creatorFunction = (params -> {
+      return NumericConvertFunction.createConvertFunction(name, val -> (int)Math.floor(val), val -> (long)Math.floor(val), params);
+    });
+  }
+  
+  /**
+   * A numeric mapping function that returns the ceiling of the input.
+   */
+  public static class CeilingFunction {
+    public static final String name = "ceil";
+    public static final CreatorFunction creatorFunction = (params -> {
+      return NumericConvertFunction.createConvertFunction(name, val -> (int)Math.ceil(val), val -> (long)Math.ceil(val), params);
+    });
+  }
+  
+  /**
+   * A numeric mapping function that returns the rounded input.
+   */
+  public static class RoundFunction {
+    public static final String name = "round";
+    public static final CreatorFunction creatorFunction = (params -> {
+      return NumericConvertFunction.createConvertFunction(name, val -> (int)Math.round(val), val -> (long)Math.round(val), params);
+    });
+  }
+
+}
+@FunctionalInterface
+interface ConvertFloatFunction {
+  public int convert(float value);
+}
+@FunctionalInterface
+interface ConvertDoubleFunction {
+  public long convert(double value);
+}
+/**
+ * A function to convert a {@link FloatValue} to a {@link IntValue}.
+ */
+class ConvertFloatValueFunction extends AbstractIntValue {
+  private final String name;
+  private final FloatValue param;
+  private final ConvertFloatFunction conv;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public ConvertFloatValueFunction(String name, FloatValue param, ConvertFloatFunction conv) {
+    this.name = name;
+    this.param = param;
+    this.conv = conv;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,param);
+  }
+
+  @Override
+  public int getInt() {
+    return conv.convert(param.getFloat());
+  }
+  @Override
+  public boolean exists() {
+    return param.exists();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * A function to convert a {@link FloatValueStream} to a {@link IntValueStream}.
+ */
+class ConvertFloatStreamFunction extends AbstractIntValueStream {
+  private final String name;
+  private final FloatValueStream param;
+  private final ConvertFloatFunction conv;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public ConvertFloatStreamFunction(String name, FloatValueStream param, ConvertFloatFunction conv) {
+    this.name = name;
+    this.param = param;
+    this.conv = conv;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,param);
+  }
+
+  @Override
+  public void streamInts(IntConsumer cons) {
+    param.streamFloats( value -> cons.accept(conv.convert(value)));
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * A function to convert a {@link DoubleValue} to a {@link LongValue}.
+ */
+class ConvertDoubleValueFunction extends AbstractLongValue {
+  private final String name;
+  private final DoubleValue param;
+  private final ConvertDoubleFunction conv;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public ConvertDoubleValueFunction(String name, DoubleValue param, ConvertDoubleFunction conv) {
+    this.name = name;
+    this.param = param;
+    this.conv = conv;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,param);
+  }
+
+  @Override
+  public long getLong() {
+    return conv.convert(param.getDouble());
+  }
+  @Override
+  public boolean exists() {
+    return param.exists();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+/**
+ * A function to convert a {@link DoubleValueStream} to a {@link LongValueStream}.
+ */
+class ConvertDoubleStreamFunction extends AbstractLongValueStream {
+  private final String name;
+  private final DoubleValueStream param;
+  private final ConvertDoubleFunction conv;
+  private final String funcStr;
+  private final ExpressionType funcType;
+  
+  public ConvertDoubleStreamFunction(String name, DoubleValueStream param, ConvertDoubleFunction conv) {
+    this.name = name;
+    this.param = param;
+    this.conv = conv;
+    this.funcStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,param);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    param.streamDoubles( value -> cons.accept(conv.convert(value)));
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return funcStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/PowerFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/PowerFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/PowerFunction.java
new file mode 100644
index 0000000..0688ba0
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/PowerFunction.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A power mapping function.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If two numeric Values are passed in, a {@link DoubleValue} representing the first taken to the power of the second is returned.
+ * <li>If a numeric ValueStream and a numeric Value are passed in, a {@link DoubleValueStream} representing the power of 
+ * the Value to each of the values of the ValueStream for a document is returned. 
+ * (Or the other way, since the Value and ValueStream can be used in either order)
+ * </ul>
+ */
+public class PowerFunction {
+  public static final String name = "pow";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramaters, " + params.length + " found.");
+    }
+    AnalyticsValueStream param1 = params[0];
+    AnalyticsValueStream param2 = params[1];
+    if (param1 instanceof DoubleValueStream && param2 instanceof DoubleValueStream) {
+      return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> Math.pow(a,b), (DoubleValueStream)param1, (DoubleValueStream)param2);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters.");
+    }
+  });
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/RemoveFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/RemoveFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/RemoveFunction.java
new file mode 100644
index 0000000..5800a1b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/RemoveFunction.java
@@ -0,0 +1,796 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.AnalyticsValue;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.BooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.AnalyticsValue.AbstractAnalyticsValue;
+import org.apache.solr.analytics.value.BooleanValue.AbstractBooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream.AbstractBooleanValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DateValueStream.AbstractDateValueStream;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream.AbstractDoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.FloatValueStream.AbstractFloatValueStream;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.IntValueStream.AbstractIntValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.LongValueStream.AbstractLongValueStream;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.value.StringValueStream.AbstractStringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A mapping function to remove an {@link AnalyticsValue} from an {@link AnalyticsValue} or an {@link AnalyticsValueStream}.
+ * For each document, the value exists if it doesn't equal the value of the second parameter.
+ * <p>
+ * The first parameter can be any type of analytics expression. If the parameter is multi-valued, then the return will be multi-valued. (Required)
+ * <br>
+ * The second parameter, which is the value to remove from the first parameter, must be an {@link AnalyticsValue}, aka single-valued. (Required)
+ * <p>
+ * The resulting Value or ValueStream will be typed with the closest super-type of the two parameters.
+ * (e.g. {@value #name}(int,float) will return a float)
+ */
+public class RemoveFunction {
+  public static final String name = "remove";
+  
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramaters, " + params.length + " found.");
+    }
+    if (!(params[1] instanceof AnalyticsValue)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires the remove paramater to be single-valued.");
+    }
+
+    AnalyticsValueStream baseExpr = params[0];
+    AnalyticsValue removeExpr = (AnalyticsValue)params[1];
+
+    if (baseExpr instanceof DateValue && removeExpr instanceof DateValue) {
+      return new DateRemoveFunction((DateValue)baseExpr,(DateValue)removeExpr);
+    }
+    if (baseExpr instanceof DateValueStream && removeExpr instanceof DateValue) {
+      return new DateStreamRemoveFunction((DateValueStream)baseExpr,(DateValue)removeExpr);
+    }
+    if (baseExpr instanceof BooleanValue && removeExpr instanceof BooleanValue) {
+      return new BooleanRemoveFunction((BooleanValue)baseExpr,(BooleanValue)removeExpr);
+    }
+    if (baseExpr instanceof BooleanValueStream && removeExpr instanceof BooleanValue) {
+      return new BooleanStreamRemoveFunction((BooleanValueStream)baseExpr,(BooleanValue)removeExpr);
+    }
+    if (baseExpr instanceof IntValue && removeExpr instanceof IntValue) {
+      return new IntRemoveFunction((IntValue)baseExpr,(IntValue)removeExpr);
+    }
+    if (baseExpr instanceof IntValueStream && removeExpr instanceof IntValue) {
+      return new IntStreamRemoveFunction((IntValueStream)baseExpr,(IntValue)removeExpr);
+    }
+    if (baseExpr instanceof LongValue && removeExpr instanceof LongValue) {
+      return new LongRemoveFunction((LongValue)baseExpr,(LongValue)removeExpr);
+    }
+    if (baseExpr instanceof LongValueStream && removeExpr instanceof LongValue) {
+      return new LongStreamRemoveFunction((LongValueStream)baseExpr,(LongValue)removeExpr);
+    }
+    if (baseExpr instanceof FloatValue && removeExpr instanceof FloatValue) {
+      return new FloatRemoveFunction((FloatValue)baseExpr,(FloatValue)removeExpr);
+    }
+    if (baseExpr instanceof FloatValueStream && removeExpr instanceof FloatValue) {
+      return new FloatStreamRemoveFunction((FloatValueStream)baseExpr,(FloatValue)removeExpr);
+    }
+    if (baseExpr instanceof DoubleValue && removeExpr instanceof DoubleValue) {
+      return new DoubleRemoveFunction((DoubleValue)baseExpr,(DoubleValue)removeExpr);
+    }
+    if (baseExpr instanceof DoubleValueStream && removeExpr instanceof DoubleValue) {
+      return new DoubleStreamRemoveFunction((DoubleValueStream)baseExpr,(DoubleValue)removeExpr);
+    }
+    if (baseExpr instanceof StringValue && removeExpr instanceof StringValue) {
+      return new StringRemoveFunction((StringValue)baseExpr,(StringValue)removeExpr);
+    }
+    if (baseExpr instanceof StringValueStream && removeExpr instanceof StringValue) {
+      return new StringStreamRemoveFunction((StringValueStream)baseExpr,(StringValue)removeExpr);
+    }
+    if (baseExpr instanceof AnalyticsValue) {
+      return new ValueRemoveFunction((AnalyticsValue)baseExpr,removeExpr);
+    }
+    return new StreamRemoveFunction(baseExpr,removeExpr);
+  });
+}
+class StreamRemoveFunction implements AnalyticsValueStream {
+  private final AnalyticsValueStream baseExpr;
+  private final AnalyticsValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StreamRemoveFunction(AnalyticsValueStream baseExpr, AnalyticsValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    Object removeValue = removeExpr.getObject();
+    if (removeExpr.exists()) {
+      baseExpr.streamObjects(value -> {
+        if (removeValue.equals(value)) cons.accept(value);
+      });
+    } else {
+      baseExpr.streamObjects(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class ValueRemoveFunction extends AbstractAnalyticsValue {
+  private final AnalyticsValue baseExpr;
+  private final AnalyticsValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public ValueRemoveFunction(AnalyticsValue baseExpr, AnalyticsValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public Object getObject() {
+    Object value = baseExpr.getObject();
+    exists = false;
+    if (baseExpr.exists()) {
+      exists = value.equals(removeExpr.toString()) ? removeExpr.exists()? false : true : true;
+    }
+    return value;
+  }
+  
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanStreamRemoveFunction extends AbstractBooleanValueStream {
+  private final BooleanValueStream baseExpr;
+  private final BooleanValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanStreamRemoveFunction(BooleanValueStream baseExpr, BooleanValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    boolean removeValue = removeExpr.getBoolean();
+    if (removeExpr.exists()) {
+      baseExpr.streamBooleans(value -> {
+        if (removeValue==value) cons.accept(value);
+      });
+    } else {
+      baseExpr.streamBooleans(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanRemoveFunction extends AbstractBooleanValue {
+  private final BooleanValue baseExpr;
+  private final BooleanValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanRemoveFunction(BooleanValue baseExpr, BooleanValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+  
+  boolean exists = false;
+  
+  @Override
+  public boolean getBoolean() {
+    boolean value = baseExpr.getBoolean();
+    exists = false;
+    if (baseExpr.exists()) {
+      exists = value==removeExpr.getBoolean() ? removeExpr.exists()? false : true : true;
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntStreamRemoveFunction extends AbstractIntValueStream {
+  private final IntValueStream baseExpr;
+  private final IntValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntStreamRemoveFunction(IntValueStream baseExpr, IntValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+
+  @Override
+  public void streamInts(IntConsumer cons) {
+    int removeValue = removeExpr.getInt();
+    if (removeExpr.exists()) {
+      baseExpr.streamInts(value -> {
+        if (removeValue==value) cons.accept(value);
+      });
+    } else {
+      baseExpr.streamInts(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntRemoveFunction extends AbstractIntValue {
+  private final IntValue baseExpr;
+  private final IntValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntRemoveFunction(IntValue baseExpr, IntValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+  
+  boolean exists = false;
+  
+  @Override
+  public int getInt() {
+    int value = baseExpr.getInt();
+    exists = false;
+    if (baseExpr.exists()) {
+      exists = value==removeExpr.getInt() ? removeExpr.exists()? false : true : true;
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongStreamRemoveFunction extends AbstractLongValueStream {
+  private final LongValueStream baseExpr;
+  private final LongValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongStreamRemoveFunction(LongValueStream baseExpr, LongValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    long removeValue = removeExpr.getLong();
+    if (removeExpr.exists()) {
+      baseExpr.streamLongs(value -> {
+        if (removeValue==value) cons.accept(value);
+      });
+    } else {
+      baseExpr.streamLongs(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongRemoveFunction extends AbstractLongValue {
+  private final LongValue baseExpr;
+  private final LongValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongRemoveFunction(LongValue baseExpr, LongValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+  
+  boolean exists = false;
+  
+  @Override
+  public long getLong() {
+    long value = baseExpr.getLong();
+    exists = false;
+    if (baseExpr.exists()) {
+      exists = value==removeExpr.getLong() ? removeExpr.exists()? false : true : true;
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatStreamRemoveFunction extends AbstractFloatValueStream {
+  private final FloatValueStream baseExpr;
+  private final FloatValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatStreamRemoveFunction(FloatValueStream baseExpr, FloatValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    float removeValue = removeExpr.getFloat();
+    if (removeExpr.exists()) {
+      baseExpr.streamFloats(value -> {
+        if (removeValue==value) cons.accept(value);
+      });
+    } else {
+      baseExpr.streamFloats(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatRemoveFunction extends AbstractFloatValue {
+  private final FloatValue baseExpr;
+  private final FloatValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatRemoveFunction(FloatValue baseExpr, FloatValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+  
+  boolean exists = false;
+  
+  @Override
+  public float getFloat() {
+    float value = baseExpr.getFloat();
+    exists = false;
+    if (baseExpr.exists()) {
+      exists = value==removeExpr.getFloat() ? removeExpr.exists()? false : true : true;
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DoubleStreamRemoveFunction extends AbstractDoubleValueStream {
+  private final DoubleValueStream baseExpr;
+  private final DoubleValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DoubleStreamRemoveFunction(DoubleValueStream baseExpr, DoubleValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    double removeValue = removeExpr.getDouble();
+    if (removeExpr.exists()) {
+      baseExpr.streamDoubles(value -> {
+        if (removeValue==value) cons.accept(value);
+      });
+    } else {
+      baseExpr.streamDoubles(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DoubleRemoveFunction extends AbstractDoubleValue {
+  private final DoubleValue baseExpr;
+  private final DoubleValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DoubleRemoveFunction(DoubleValue baseExpr, DoubleValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+  
+  boolean exists = false;
+  
+  @Override
+  public double getDouble() {
+    double value = baseExpr.getDouble();
+    exists = false;
+    if (baseExpr.exists()) {
+      exists = value==removeExpr.getDouble() ? removeExpr.exists()? false : true : true;
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DateStreamRemoveFunction extends AbstractDateValueStream {
+  private final DateValueStream baseExpr;
+  private final DateValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateStreamRemoveFunction(DateValueStream baseExpr, DateValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    long removeValue = removeExpr.getLong();
+    if (removeExpr.exists()) {
+      baseExpr.streamLongs(value -> {
+        if (removeValue==value) cons.accept(value);
+      });
+    } else {
+      baseExpr.streamLongs(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DateRemoveFunction extends AbstractDateValue {
+  private final DateValue baseExpr;
+  private final DateValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateRemoveFunction(DateValue baseExpr, DateValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public long getLong() {
+    long value = baseExpr.getLong();
+    exists = false;
+    if (baseExpr.exists()) {
+      exists = value==removeExpr.getLong() ? removeExpr.exists() ? false : true : true;
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringStreamRemoveFunction extends AbstractStringValueStream {
+  private final StringValueStream baseExpr;
+  private final StringValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StringStreamRemoveFunction(StringValueStream baseExpr, StringValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    String removeValue = removeExpr.toString();
+    if (removeExpr.exists()) {
+      baseExpr.streamStrings(value -> {
+        if (removeValue.equals(value)) cons.accept(value);
+      });
+    } else {
+      baseExpr.streamStrings(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringRemoveFunction extends AbstractStringValue {
+  private final StringValue baseExpr;
+  private final StringValue removeExpr;
+  public static final String name = RemoveFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StringRemoveFunction(StringValue baseExpr, StringValue removeExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.removeExpr = removeExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,removeExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,removeExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public String getString() {
+    String value = baseExpr.getString();
+    exists = false;
+    if (baseExpr.exists()) {
+      exists = value.equals(removeExpr.getString()) ? removeExpr.exists()? false : true : true;
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ReplaceFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ReplaceFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ReplaceFunction.java
new file mode 100644
index 0000000..0d9e278
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ReplaceFunction.java
@@ -0,0 +1,914 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.AnalyticsValue;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.BooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.AnalyticsValue.AbstractAnalyticsValue;
+import org.apache.solr.analytics.value.BooleanValue.AbstractBooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream.AbstractBooleanValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DateValueStream.AbstractDateValueStream;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream.AbstractDoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.FloatValueStream.AbstractFloatValueStream;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.IntValueStream.AbstractIntValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.LongValueStream.AbstractLongValueStream;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.value.StringValueStream.AbstractStringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A mapping function to replace an {@link AnalyticsValue} from an {@link AnalyticsValue} or an {@link AnalyticsValueStream}
+ * with a different {@link AnalyticsValue}.
+ * For each document, all values from the base parameter matching the comparison parameter will be replaced with the fill parameter.
+ * <p>
+ * The first parameter can be any type of analytics expression. If the parameter is multi-valued, then the return will be multi-valued. (Required)
+ * <br>
+ * The second parameter, which is the value to compare to the first parameter, must be an {@link AnalyticsValue}, aka single-valued. (Required)
+ * <br>
+ * The third parameter, which is the value to fill the first parameter with, must be an {@link AnalyticsValue}, aka single-valued. (Required)
+ * <p>
+ * The resulting Value or ValueStream will be typed with the closest super-type of the three parameters.
+ * (e.g. {@value #name}(double,int,float) will return a double)
+ */
+public class ReplaceFunction {
+  public static final String name = "replace";
+
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 3) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 3 paramaters, " + params.length + " found.");
+    }
+    if (!(params[1] instanceof AnalyticsValue && params[2] instanceof AnalyticsValue)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires the comparator and fill parameters to be single-valued.");
+    }
+
+    AnalyticsValueStream baseExpr = params[0];
+    AnalyticsValue compExpr = (AnalyticsValue)params[1];
+    AnalyticsValue fillExpr = (AnalyticsValue)params[2];
+
+    if (baseExpr instanceof DateValue && compExpr instanceof DateValue && fillExpr instanceof DateValue) {
+      return new DateReplaceFunction((DateValue)baseExpr,(DateValue)compExpr,(DateValue)fillExpr);
+    }
+    if (baseExpr instanceof DateValueStream && compExpr instanceof DateValue && fillExpr instanceof DateValue) {
+      return new DateStreamReplaceFunction((DateValueStream)baseExpr,(DateValue)compExpr,(DateValue)fillExpr);
+    }
+    if (baseExpr instanceof BooleanValue && compExpr instanceof BooleanValue && fillExpr instanceof BooleanValue) {
+      return new BooleanReplaceFunction((BooleanValue)baseExpr,(BooleanValue)compExpr,(BooleanValue)fillExpr);
+    }
+    if (baseExpr instanceof BooleanValueStream && compExpr instanceof BooleanValue && fillExpr instanceof BooleanValue) {
+      return new BooleanStreamReplaceFunction((BooleanValueStream)baseExpr,(BooleanValue)compExpr,(BooleanValue)fillExpr);
+    }
+    if (baseExpr instanceof IntValue && compExpr instanceof IntValue && fillExpr instanceof IntValue) {
+      return new IntReplaceFunction((IntValue)baseExpr,(IntValue)compExpr,(IntValue)fillExpr);
+    }
+    if (baseExpr instanceof IntValueStream && compExpr instanceof IntValue && fillExpr instanceof IntValue) {
+      return new IntStreamReplaceFunction((IntValueStream)baseExpr,(IntValue)compExpr,(IntValue)fillExpr);
+    }
+    if (baseExpr instanceof LongValue && compExpr instanceof LongValue && fillExpr instanceof LongValue) {
+      return new LongReplaceFunction((LongValue)baseExpr,(LongValue)compExpr,(LongValue)fillExpr);
+    }
+    if (baseExpr instanceof LongValueStream && compExpr instanceof LongValue && fillExpr instanceof LongValue) {
+      return new LongStreamReplaceFunction((LongValueStream)baseExpr,(LongValue)compExpr,(LongValue)fillExpr);
+    }
+    if (baseExpr instanceof FloatValue && compExpr instanceof FloatValue && fillExpr instanceof FloatValue) {
+      return new FloatReplaceFunction((FloatValue)baseExpr,(FloatValue)compExpr,(FloatValue)fillExpr);
+    }
+    if (baseExpr instanceof FloatValueStream && compExpr instanceof FloatValue && fillExpr instanceof FloatValue) {
+      return new FloatStreamReplaceFunction((FloatValueStream)baseExpr,(FloatValue)compExpr,(FloatValue)fillExpr);
+    }
+    if (baseExpr instanceof DoubleValue && compExpr instanceof DoubleValue && fillExpr instanceof DoubleValue) {
+      return new DoubleReplaceFunction((DoubleValue)baseExpr,(DoubleValue)compExpr,(DoubleValue)fillExpr);
+    }
+    if (baseExpr instanceof DoubleValueStream && compExpr instanceof DoubleValue && fillExpr instanceof DoubleValue) {
+      return new DoubleStreamReplaceFunction((DoubleValueStream)baseExpr,(DoubleValue)compExpr,(DoubleValue)fillExpr);
+    }
+    if (baseExpr instanceof StringValue && compExpr instanceof StringValue && fillExpr instanceof StringValue) {
+      return new StringReplaceFunction((StringValue)baseExpr,(StringValue)compExpr,(StringValue)fillExpr);
+    }
+    if (baseExpr instanceof StringValueStream && compExpr instanceof StringValue && fillExpr instanceof StringValue) {
+      return new StringStreamReplaceFunction((StringValueStream)baseExpr,(StringValue)compExpr,(StringValue)fillExpr);
+    }
+    if (baseExpr instanceof AnalyticsValue) {
+      return new ValueReplaceFunction((AnalyticsValue)baseExpr,(AnalyticsValue)compExpr,(AnalyticsValue)fillExpr);
+    }
+    return new StreamReplaceFunction(baseExpr,compExpr,fillExpr); 
+    
+  });
+}
+class StreamReplaceFunction implements AnalyticsValueStream {
+  private final AnalyticsValueStream baseExpr;
+  private final AnalyticsValue compExpr;
+  private final AnalyticsValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StreamReplaceFunction(AnalyticsValueStream baseExpr, AnalyticsValue compExpr, AnalyticsValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    Object compValue = compExpr.getObject();
+    if (compExpr.exists()) {
+      Object fillValue = fillExpr.getObject();
+      boolean fillExists = fillExpr.exists();
+      baseExpr.streamObjects(value -> {
+        if (value.equals(compValue)) {
+          if (fillExists) {
+            cons.accept(fillValue);
+          }
+        } else {
+          cons.accept(value);
+        }
+      });
+    }
+    else {
+      baseExpr.streamObjects(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class ValueReplaceFunction extends AbstractAnalyticsValue {
+  private final AnalyticsValue baseExpr;
+  private final AnalyticsValue compExpr;
+  private final AnalyticsValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public ValueReplaceFunction(AnalyticsValue baseExpr, AnalyticsValue compExpr, AnalyticsValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public Object getObject() {
+    Object value = baseExpr.getObject();
+    exists = baseExpr.exists();
+    Object comp = compExpr.getObject();
+    if (value.equals(comp) && exists==compExpr.exists()) {
+      value = fillExpr.getObject();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanStreamReplaceFunction extends AbstractBooleanValueStream {
+  private final BooleanValueStream baseExpr;
+  private final BooleanValue compExpr;
+  private final BooleanValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanStreamReplaceFunction(BooleanValueStream baseExpr, BooleanValue compExpr, BooleanValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    boolean compValue = compExpr.getBoolean();
+    if (compExpr.exists()) {
+      boolean fillValue = fillExpr.getBoolean();
+      boolean fillExists = fillExpr.exists();
+      baseExpr.streamBooleans(value -> {
+        if (value==compValue) {
+          if (fillExists) {
+            cons.accept(fillValue);
+          }
+        } else {
+          cons.accept(value);
+        }
+      });
+    }
+    else {
+      baseExpr.streamBooleans(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanReplaceFunction extends AbstractBooleanValue {
+  private final BooleanValue baseExpr;
+  private final BooleanValue compExpr;
+  private final BooleanValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanReplaceFunction(BooleanValue baseExpr, BooleanValue compExpr, BooleanValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public boolean getBoolean() {
+    boolean value = baseExpr.getBoolean();
+    exists = baseExpr.exists();
+    boolean comp = compExpr.getBoolean();
+    if (value==comp && exists==compExpr.exists()) {
+      value = fillExpr.getBoolean();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntStreamReplaceFunction extends AbstractIntValueStream {
+  private final IntValueStream baseExpr;
+  private final IntValue compExpr;
+  private final IntValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntStreamReplaceFunction(IntValueStream baseExpr, IntValue compExpr, IntValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+
+  @Override
+  public void streamInts(IntConsumer cons) {
+    int compValue = compExpr.getInt();
+    if (compExpr.exists()) {
+      int fillValue = fillExpr.getInt();
+      boolean fillExists = fillExpr.exists();
+      baseExpr.streamInts(value -> {
+        if (value==compValue) {
+          if (fillExists) {
+            cons.accept(fillValue);
+          }
+        } else {
+          cons.accept(value);
+        }
+      });
+    }
+    else {
+      baseExpr.streamInts(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntReplaceFunction extends AbstractIntValue {
+  private final IntValue baseExpr;
+  private final IntValue compExpr;
+  private final IntValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntReplaceFunction(IntValue baseExpr, IntValue compExpr, IntValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public int getInt() {
+    int value = baseExpr.getInt();
+    exists = baseExpr.exists();
+    int comp = compExpr.getInt();
+    if (value==comp && exists==compExpr.exists()) {
+      value = fillExpr.getInt();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongStreamReplaceFunction extends AbstractLongValueStream {
+  private final LongValueStream baseExpr;
+  private final LongValue compExpr;
+  private final LongValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongStreamReplaceFunction(LongValueStream baseExpr, LongValue compExpr, LongValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    long compValue = compExpr.getLong();
+    if (compExpr.exists()) {
+      long fillValue = fillExpr.getLong();
+      boolean fillExists = fillExpr.exists();
+      baseExpr.streamLongs(value -> {
+        if (value==compValue) {
+          if (fillExists) {
+            cons.accept(fillValue);
+          }
+        } else {
+          cons.accept(value);
+        }
+      });
+    }
+    else {
+      baseExpr.streamLongs(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongReplaceFunction extends AbstractLongValue {
+  private final LongValue baseExpr;
+  private final LongValue compExpr;
+  private final LongValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongReplaceFunction(LongValue baseExpr, LongValue compExpr, LongValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public long getLong() {
+    long value = baseExpr.getLong();
+    exists = baseExpr.exists();
+    long comp = compExpr.getLong();
+    if (value==comp && exists==compExpr.exists()) {
+      value = fillExpr.getLong();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatStreamReplaceFunction extends AbstractFloatValueStream {
+  private final FloatValueStream baseExpr;
+  private final FloatValue compExpr;
+  private final FloatValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatStreamReplaceFunction(FloatValueStream baseExpr, FloatValue compExpr, FloatValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    float compValue = compExpr.getFloat();
+    if (compExpr.exists()) {
+      float fillValue = fillExpr.getFloat();
+      boolean fillExists = fillExpr.exists();
+      baseExpr.streamFloats(value -> {
+        if (value==compValue) {
+          if (fillExists) {
+            cons.accept(fillValue);
+          }
+        } else {
+          cons.accept(value);
+        }
+      });
+    }
+    else {
+      baseExpr.streamFloats(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatReplaceFunction extends AbstractFloatValue {
+  private final FloatValue baseExpr;
+  private final FloatValue compExpr;
+  private final FloatValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatReplaceFunction(FloatValue baseExpr, FloatValue compExpr, FloatValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public float getFloat() {
+    float value = baseExpr.getFloat();
+    exists = baseExpr.exists();
+    float comp = compExpr.getFloat();
+    if (value==comp && exists==compExpr.exists()) {
+      value = fillExpr.getFloat();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DoubleStreamReplaceFunction extends AbstractDoubleValueStream {
+  private final DoubleValueStream baseExpr;
+  private final DoubleValue compExpr;
+  private final DoubleValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DoubleStreamReplaceFunction(DoubleValueStream baseExpr, DoubleValue compExpr, DoubleValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    double compValue = compExpr.getDouble();
+    if (compExpr.exists()) {
+      double fillValue = fillExpr.getDouble();
+      boolean fillExists = fillExpr.exists();
+      baseExpr.streamDoubles(value -> {
+        if (value==compValue) {
+          if (fillExists) {
+            cons.accept(fillValue);
+          }
+        } else {
+          cons.accept(value);
+        }
+      });
+    }
+    else {
+      baseExpr.streamDoubles(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DoubleReplaceFunction extends AbstractDoubleValue {
+  private final DoubleValue baseExpr;
+  private final DoubleValue compExpr;
+  private final DoubleValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DoubleReplaceFunction(DoubleValue baseExpr, DoubleValue compExpr, DoubleValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public double getDouble() {
+    double value = baseExpr.getDouble();
+    exists = baseExpr.exists();
+    double comp = compExpr.getDouble();
+    if (value==comp && exists==compExpr.exists()) {
+      value = fillExpr.getDouble();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DateStreamReplaceFunction extends AbstractDateValueStream {
+  private final DateValueStream baseExpr;
+  private final DateValue compExpr;
+  private final DateValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateStreamReplaceFunction(DateValueStream baseExpr, DateValue compExpr, DateValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    long compValue = compExpr.getLong();
+    if (compExpr.exists()) {
+      long fillValue = fillExpr.getLong();
+      boolean fillExists = fillExpr.exists();
+      baseExpr.streamLongs(value -> {
+        if (value==compValue) {
+          if (fillExists) {
+            cons.accept(fillValue);
+          }
+        } else {
+          cons.accept(value);
+        }
+      });
+    }
+    else {
+      baseExpr.streamLongs(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DateReplaceFunction extends AbstractDateValue {
+  private final DateValue baseExpr;
+  private final DateValue compExpr;
+  private final DateValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateReplaceFunction(DateValue baseExpr, DateValue compExpr, DateValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public long getLong() {
+    long value = baseExpr.getLong();
+    exists = baseExpr.exists();
+    long comp = compExpr.getLong();
+    if (value==comp && exists==compExpr.exists()) {
+      value = fillExpr.getLong();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringStreamReplaceFunction extends AbstractStringValueStream {
+  private final StringValueStream baseExpr;
+  private final StringValue compExpr;
+  private final StringValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StringStreamReplaceFunction(StringValueStream baseExpr, StringValue compExpr, StringValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    String compValue = compExpr.toString();
+    if (compExpr.exists()) {
+      String fillValue = fillExpr.toString();
+      boolean fillExists = fillExpr.exists();
+      baseExpr.streamStrings(value -> {
+        if (value.equals(compValue)) {
+          if (fillExists) {
+            cons.accept(fillValue);
+          }
+        } else {
+          cons.accept(value);
+        }
+      });
+    }
+    else {
+      baseExpr.streamStrings(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringReplaceFunction extends AbstractStringValue {
+  private final StringValue baseExpr;
+  private final StringValue compExpr;
+  private final StringValue fillExpr;
+  public static final String name = ReplaceFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StringReplaceFunction(StringValue baseExpr, StringValue compExpr, StringValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.compExpr = compExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,compExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public String getString() {
+    String value = baseExpr.getString();
+    exists = baseExpr.exists();
+    String comp = compExpr.getString();
+    if (value.equals(comp) && exists==compExpr.exists()) {
+      value = fillExpr.getString();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
\ No newline at end of file


[33/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10272: Adding user _default configset to test-files, fixing solr & solr.cmd script bugs

Posted by ab...@apache.org.
SOLR-10272: Adding user _default configset to test-files, fixing solr & solr.cmd script bugs


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/85069cac
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/85069cac
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/85069cac

Branch: refs/heads/jira/solr-10879
Commit: 85069cacf40e757b3eb4d4d211b1783faf800bc5
Parents: 8f71bb4
Author: Ishan Chattopadhyaya <is...@apache.org>
Authored: Thu Jun 29 10:46:14 2017 +0530
Committer: Ishan Chattopadhyaya <is...@apache.org>
Committed: Thu Jun 29 10:46:14 2017 +0530

----------------------------------------------------------------------
 solr/bin/solr                                   |   12 +-
 solr/bin/solr.cmd                               |    4 +-
 .../solr/configsets/_default/conf/currency.xml  |   67 +
 .../solr/configsets/_default/conf/elevate.xml   |   42 +
 .../_default/conf/lang/contractions_ca.txt      |    8 +
 .../_default/conf/lang/contractions_fr.txt      |   15 +
 .../_default/conf/lang/contractions_ga.txt      |    5 +
 .../_default/conf/lang/contractions_it.txt      |   23 +
 .../_default/conf/lang/hyphenations_ga.txt      |    5 +
 .../_default/conf/lang/stemdict_nl.txt          |    6 +
 .../_default/conf/lang/stoptags_ja.txt          |  420 ++++++
 .../_default/conf/lang/stopwords_ar.txt         |  125 ++
 .../_default/conf/lang/stopwords_bg.txt         |  193 +++
 .../_default/conf/lang/stopwords_ca.txt         |  220 +++
 .../_default/conf/lang/stopwords_cz.txt         |  172 +++
 .../_default/conf/lang/stopwords_da.txt         |  110 ++
 .../_default/conf/lang/stopwords_de.txt         |  294 ++++
 .../_default/conf/lang/stopwords_el.txt         |   78 +
 .../_default/conf/lang/stopwords_en.txt         |   54 +
 .../_default/conf/lang/stopwords_es.txt         |  356 +++++
 .../_default/conf/lang/stopwords_eu.txt         |   99 ++
 .../_default/conf/lang/stopwords_fa.txt         |  313 ++++
 .../_default/conf/lang/stopwords_fi.txt         |   97 ++
 .../_default/conf/lang/stopwords_fr.txt         |  186 +++
 .../_default/conf/lang/stopwords_ga.txt         |  110 ++
 .../_default/conf/lang/stopwords_gl.txt         |  161 +++
 .../_default/conf/lang/stopwords_hi.txt         |  235 +++
 .../_default/conf/lang/stopwords_hu.txt         |  211 +++
 .../_default/conf/lang/stopwords_hy.txt         |   46 +
 .../_default/conf/lang/stopwords_id.txt         |  359 +++++
 .../_default/conf/lang/stopwords_it.txt         |  303 ++++
 .../_default/conf/lang/stopwords_ja.txt         |  127 ++
 .../_default/conf/lang/stopwords_lv.txt         |  172 +++
 .../_default/conf/lang/stopwords_nl.txt         |  119 ++
 .../_default/conf/lang/stopwords_no.txt         |  194 +++
 .../_default/conf/lang/stopwords_pt.txt         |  253 ++++
 .../_default/conf/lang/stopwords_ro.txt         |  233 +++
 .../_default/conf/lang/stopwords_ru.txt         |  243 ++++
 .../_default/conf/lang/stopwords_sv.txt         |  133 ++
 .../_default/conf/lang/stopwords_th.txt         |  119 ++
 .../_default/conf/lang/stopwords_tr.txt         |  212 +++
 .../_default/conf/lang/userdict_ja.txt          |   29 +
 .../configsets/_default/conf/managed-schema     | 1076 ++++++++++++++
 .../solr/configsets/_default/conf/params.json   |   20 +
 .../solr/configsets/_default/conf/protwords.txt |   21 +
 .../solr/configsets/_default/conf/schema.xml    |   37 -
 .../configsets/_default/conf/solrconfig.xml     | 1355 +++++++++++++++++-
 .../solr/configsets/_default/conf/stopwords.txt |   14 +
 .../solr/configsets/_default/conf/synonyms.txt  |   29 +
 .../solr/cloud/CollectionsAPISolrJTest.java     |   27 +-
 .../apache/solr/cloud/TestConfigSetsAPI.java    |   45 +
 51 files changed, 8729 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/bin/solr
----------------------------------------------------------------------
diff --git a/solr/bin/solr b/solr/bin/solr
index cd27fda..c9aad2f 100755
--- a/solr/bin/solr
+++ b/solr/bin/solr
@@ -943,12 +943,14 @@ if [[ "$SCRIPT_CMD" == "create" || "$SCRIPT_CMD" == "create_core" || "$SCRIPT_CM
     done
   fi
 
+  if [ -z "$CREATE_CONFDIR" ]; then
+    CREATE_CONFDIR='_default'
+  fi
+  
   # validate the confdir arg (if provided)
-  if ! [ -z "$CREATE_CONFDIR" ]; then
-    if [[ ! -d "$SOLR_TIP/server/solr/configsets/$CREATE_CONFDIR" && ! -d "$CREATE_CONFDIR" ]]; then
-      echo -e "\nSpecified configuration directory $CREATE_CONFDIR not found!\n"
-      exit 1
-    fi
+  if [[ ! -d "$SOLR_TIP/server/solr/configsets/$CREATE_CONFDIR" && ! -d "$CREATE_CONFDIR" ]]; then
+    echo -e "\nSpecified configuration directory $CREATE_CONFDIR not found!\n"
+    exit 1
   fi
 
   if [ -z "$CREATE_NAME" ]; then

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/bin/solr.cmd
----------------------------------------------------------------------
diff --git a/solr/bin/solr.cmd b/solr/bin/solr.cmd
index 99bd815..b268f90 100644
--- a/solr/bin/solr.cmd
+++ b/solr/bin/solr.cmd
@@ -1404,8 +1404,10 @@ IF "!CREATE_NAME!"=="" (
   set "SCRIPT_ERROR=Name (-c) is a required parameter for %SCRIPT_CMD%"
   goto invalid_cmd_line
 )
+IF "!CREATE_CONFDIR!"=="" set CREATE_CONFDIR=_default
 IF "!CREATE_NUM_SHARDS!"=="" set CREATE_NUM_SHARDS=1
 IF "!CREATE_REPFACT!"=="" set CREATE_REPFACT=1
+IF "!CREATE_CONFNAME!"=="" set CREATE_CONFNAME=!CREATE_NAME!
 
 REM Find a port that Solr is running on
 if "!CREATE_PORT!"=="" (
@@ -1431,7 +1433,7 @@ if "%SCRIPT_CMD%"=="create_core" (
     org.apache.solr.util.SolrCLI create_core -name !CREATE_NAME! -solrUrl !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!CREATE_PORT!/solr ^
     -confdir !CREATE_CONFDIR! -configsetsDir "%SOLR_TIP%\server\solr\configsets"
 ) else (
-+  "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%"^
+  "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%"^
     -Dlog4j.configuration="file:%DEFAULT_SERVER_DIR%\scripts\cloud-scripts\log4j.properties" ^
     -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^
     org.apache.solr.util.SolrCLI create -name !CREATE_NAME! -shards !CREATE_NUM_SHARDS! -replicationFactor !CREATE_REPFACT! ^

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/currency.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/currency.xml b/solr/core/src/test-files/solr/configsets/_default/conf/currency.xml
new file mode 100644
index 0000000..532221a
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/currency.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Example exchange rates file for CurrencyFieldType named "currency" in example schema -->
+
+<currencyConfig version="1.0">
+  <rates>
+    <!-- Updated from http://www.exchangerate.com/ at 2011-09-27 -->
+    <rate from="USD" to="ARS" rate="4.333871" comment="ARGENTINA Peso" />
+    <rate from="USD" to="AUD" rate="1.025768" comment="AUSTRALIA Dollar" />
+    <rate from="USD" to="EUR" rate="0.743676" comment="European Euro" />
+    <rate from="USD" to="BRL" rate="1.881093" comment="BRAZIL Real" />
+    <rate from="USD" to="CAD" rate="1.030815" comment="CANADA Dollar" />
+    <rate from="USD" to="CLP" rate="519.0996" comment="CHILE Peso" />
+    <rate from="USD" to="CNY" rate="6.387310" comment="CHINA Yuan" />
+    <rate from="USD" to="CZK" rate="18.47134" comment="CZECH REP. Koruna" />
+    <rate from="USD" to="DKK" rate="5.515436" comment="DENMARK Krone" />
+    <rate from="USD" to="HKD" rate="7.801922" comment="HONG KONG Dollar" />
+    <rate from="USD" to="HUF" rate="215.6169" comment="HUNGARY Forint" />
+    <rate from="USD" to="ISK" rate="118.1280" comment="ICELAND Krona" />
+    <rate from="USD" to="INR" rate="49.49088" comment="INDIA Rupee" />
+    <rate from="USD" to="XDR" rate="0.641358" comment="INTNL MON. FUND SDR" />
+    <rate from="USD" to="ILS" rate="3.709739" comment="ISRAEL Sheqel" />
+    <rate from="USD" to="JPY" rate="76.32419" comment="JAPAN Yen" />
+    <rate from="USD" to="KRW" rate="1169.173" comment="KOREA (SOUTH) Won" />
+    <rate from="USD" to="KWD" rate="0.275142" comment="KUWAIT Dinar" />
+    <rate from="USD" to="MXN" rate="13.85895" comment="MEXICO Peso" />
+    <rate from="USD" to="NZD" rate="1.285159" comment="NEW ZEALAND Dollar" />
+    <rate from="USD" to="NOK" rate="5.859035" comment="NORWAY Krone" />
+    <rate from="USD" to="PKR" rate="87.57007" comment="PAKISTAN Rupee" />
+    <rate from="USD" to="PEN" rate="2.730683" comment="PERU Sol" />
+    <rate from="USD" to="PHP" rate="43.62039" comment="PHILIPPINES Peso" />
+    <rate from="USD" to="PLN" rate="3.310139" comment="POLAND Zloty" />
+    <rate from="USD" to="RON" rate="3.100932" comment="ROMANIA Leu" />
+    <rate from="USD" to="RUB" rate="32.14663" comment="RUSSIA Ruble" />
+    <rate from="USD" to="SAR" rate="3.750465" comment="SAUDI ARABIA Riyal" />
+    <rate from="USD" to="SGD" rate="1.299352" comment="SINGAPORE Dollar" />
+    <rate from="USD" to="ZAR" rate="8.329761" comment="SOUTH AFRICA Rand" />
+    <rate from="USD" to="SEK" rate="6.883442" comment="SWEDEN Krona" />
+    <rate from="USD" to="CHF" rate="0.906035" comment="SWITZERLAND Franc" />
+    <rate from="USD" to="TWD" rate="30.40283" comment="TAIWAN Dollar" />
+    <rate from="USD" to="THB" rate="30.89487" comment="THAILAND Baht" />
+    <rate from="USD" to="AED" rate="3.672955" comment="U.A.E. Dirham" />
+    <rate from="USD" to="UAH" rate="7.988582" comment="UKRAINE Hryvnia" />
+    <rate from="USD" to="GBP" rate="0.647910" comment="UNITED KINGDOM Pound" />
+    
+    <!-- Cross-rates for some common currencies -->
+    <rate from="EUR" to="GBP" rate="0.869914" />  
+    <rate from="EUR" to="NOK" rate="7.800095" />  
+    <rate from="GBP" to="NOK" rate="8.966508" />  
+  </rates>
+</currencyConfig>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/elevate.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/elevate.xml b/solr/core/src/test-files/solr/configsets/_default/conf/elevate.xml
new file mode 100644
index 0000000..2c09ebe
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/elevate.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- If this file is found in the config directory, it will only be
+     loaded once at startup.  If it is found in Solr's data
+     directory, it will be re-loaded every commit.
+
+   See http://wiki.apache.org/solr/QueryElevationComponent for more info
+
+-->
+<elevate>
+ <!-- Query elevation examples
+  <query text="foo bar">
+    <doc id="1" />
+    <doc id="2" />
+    <doc id="3" />
+  </query>
+
+for use with techproducts example
+ 
+  <query text="ipod">
+    <doc id="MA147LL/A" />  put the actual ipod at the top 
+    <doc id="IW-02" exclude="true" /> exclude this cable
+  </query>
+-->
+
+</elevate>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_ca.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_ca.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_ca.txt
new file mode 100644
index 0000000..307a85f
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_ca.txt
@@ -0,0 +1,8 @@
+# Set of Catalan contractions for ElisionFilter
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+d
+l
+m
+n
+s
+t

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_fr.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_fr.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_fr.txt
new file mode 100644
index 0000000..f1bba51
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_fr.txt
@@ -0,0 +1,15 @@
+# Set of French contractions for ElisionFilter
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+l
+m
+t
+qu
+n
+s
+j
+d
+c
+jusqu
+quoiqu
+lorsqu
+puisqu

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_ga.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_ga.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_ga.txt
new file mode 100644
index 0000000..9ebe7fa
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_ga.txt
@@ -0,0 +1,5 @@
+# Set of Irish contractions for ElisionFilter
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+d
+m
+b

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_it.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_it.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_it.txt
new file mode 100644
index 0000000..cac0409
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/contractions_it.txt
@@ -0,0 +1,23 @@
+# Set of Italian contractions for ElisionFilter
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+c
+l 
+all 
+dall 
+dell 
+nell 
+sull 
+coll 
+pell 
+gl 
+agl 
+dagl 
+degl 
+negl 
+sugl 
+un 
+m 
+t 
+s 
+v 
+d

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/hyphenations_ga.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/hyphenations_ga.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/hyphenations_ga.txt
new file mode 100644
index 0000000..4d2642c
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/hyphenations_ga.txt
@@ -0,0 +1,5 @@
+# Set of Irish hyphenations for StopFilter
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+h
+n
+t

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stemdict_nl.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stemdict_nl.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stemdict_nl.txt
new file mode 100644
index 0000000..4410729
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stemdict_nl.txt
@@ -0,0 +1,6 @@
+# Set of overrides for the dutch stemmer
+# TODO: load this as a resource from the analyzer and sync it in build.xml
+fiets	fiets
+bromfiets	bromfiets
+ei	eier
+kind	kinder

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stoptags_ja.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stoptags_ja.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stoptags_ja.txt
new file mode 100644
index 0000000..71b7508
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stoptags_ja.txt
@@ -0,0 +1,420 @@
+#
+# This file defines a Japanese stoptag set for JapanesePartOfSpeechStopFilter.
+#
+# Any token with a part-of-speech tag that exactly matches those defined in this
+# file are removed from the token stream.
+#
+# Set your own stoptags by uncommenting the lines below.  Note that comments are
+# not allowed on the same line as a stoptag.  See LUCENE-3745 for frequency lists,
+# etc. that can be useful for building you own stoptag set.
+#
+# The entire possible tagset is provided below for convenience.
+#
+#####
+#  noun: unclassified nouns
+#名詞
+#
+#  noun-common: Common nouns or nouns where the sub-classification is undefined
+#名詞-一般
+#
+#  noun-proper: Proper nouns where the sub-classification is undefined 
+#名詞-固有名詞
+#
+#  noun-proper-misc: miscellaneous proper nouns
+#名詞-固有名詞-一般
+#
+#  noun-proper-person: Personal names where the sub-classification is undefined
+#名詞-固有名詞-人名
+#
+#  noun-proper-person-misc: names that cannot be divided into surname and 
+#  given name; foreign names; names where the surname or given name is unknown.
+#  e.g. お市の方
+#名詞-固有名詞-人名-一般
+#
+#  noun-proper-person-surname: Mainly Japanese surnames.
+#  e.g. 山田
+#名詞-固有名詞-人名-姓
+#
+#  noun-proper-person-given_name: Mainly Japanese given names.
+#  e.g. 太郎
+#名詞-固有名詞-人名-名
+#
+#  noun-proper-organization: Names representing organizations.
+#  e.g. 通産省, NHK
+#名詞-固有名詞-組織
+#
+#  noun-proper-place: Place names where the sub-classification is undefined
+#名詞-固有名詞-地域
+#
+#  noun-proper-place-misc: Place names excluding countries.
+#  e.g. アジア, バルセロナ, 京都
+#名詞-固有名詞-地域-一般
+#
+#  noun-proper-place-country: Country names. 
+#  e.g. 日本, オーストラリア
+#名詞-固有名詞-地域-国
+#
+#  noun-pronoun: Pronouns where the sub-classification is undefined
+#名詞-代名詞
+#
+#  noun-pronoun-misc: miscellaneous pronouns: 
+#  e.g. それ, ここ, あいつ, あなた, あちこち, いくつ, どこか, なに, みなさん, みんな, わたくし, われわれ
+#名詞-代名詞-一般
+#
+#  noun-pronoun-contraction: Spoken language contraction made by combining a 
+#  pronoun and the particle 'wa'.
+#  e.g. ありゃ, こりゃ, こりゃあ, そりゃ, そりゃあ 
+#名詞-代名詞-縮約
+#
+#  noun-adverbial: Temporal nouns such as names of days or months that behave 
+#  like adverbs. Nouns that represent amount or ratios and can be used adverbially,
+#  e.g. 金曜, 一月, 午後, 少量
+#名詞-副詞可能
+#
+#  noun-verbal: Nouns that take arguments with case and can appear followed by 
+#  'suru' and related verbs (する, できる, なさる, くださる)
+#  e.g. インプット, 愛着, 悪化, 悪戦苦闘, 一安心, 下取り
+#名詞-サ変接続
+#
+#  noun-adjective-base: The base form of adjectives, words that appear before な ("na")
+#  e.g. 健康, 安易, 駄目, だめ
+#名詞-形容動詞語幹
+#
+#  noun-numeric: Arabic numbers, Chinese numerals, and counters like 何 (回), 数.
+#  e.g. 0, 1, 2, 何, 数, 幾
+#名詞-数
+#
+#  noun-affix: noun affixes where the sub-classification is undefined
+#名詞-非自立
+#
+#  noun-affix-misc: Of adnominalizers, the case-marker の ("no"), and words that 
+#  attach to the base form of inflectional words, words that cannot be classified 
+#  into any of the other categories below. This category includes indefinite nouns.
+#  e.g. あかつき, 暁, かい, 甲斐, 気, きらい, 嫌い, くせ, 癖, こと, 事, ごと, 毎, しだい, 次第, 
+#       順, せい, 所為, ついで, 序で, つもり, 積もり, 点, どころ, の, はず, 筈, はずみ, 弾み, 
+#       拍子, ふう, ふり, 振り, ほう, 方, 旨, もの, 物, 者, ゆえ, 故, ゆえん, 所以, わけ, 訳,
+#       わり, 割り, 割, ん-口語/, もん-口語/
+#名詞-非自立-一般
+#
+#  noun-affix-adverbial: noun affixes that that can behave as adverbs.
+#  e.g. あいだ, 間, あげく, 挙げ句, あと, 後, 余り, 以外, 以降, 以後, 以上, 以前, 一方, うえ, 
+#       上, うち, 内, おり, 折り, かぎり, 限り, きり, っきり, 結果, ころ, 頃, さい, 際, 最中, さなか, 
+#       最中, じたい, 自体, たび, 度, ため, 為, つど, 都度, とおり, 通り, とき, 時, ところ, 所, 
+#       とたん, 途端, なか, 中, のち, 後, ばあい, 場合, 日, ぶん, 分, ほか, 他, まえ, 前, まま, 
+#       儘, 侭, みぎり, 矢先
+#名詞-非自立-副詞可能
+#
+#  noun-affix-aux: noun affixes treated as 助動詞 ("auxiliary verb") in school grammars 
+#  with the stem よう(だ) ("you(da)").
+#  e.g.  よう, やう, 様 (よう)
+#名詞-非自立-助動詞語幹
+#  
+#  noun-affix-adjective-base: noun affixes that can connect to the indeclinable
+#  connection form な (aux "da").
+#  e.g. みたい, ふう
+#名詞-非自立-形容動詞語幹
+#
+#  noun-special: special nouns where the sub-classification is undefined.
+#名詞-特殊
+#
+#  noun-special-aux: The そうだ ("souda") stem form that is used for reporting news, is 
+#  treated as 助動詞 ("auxiliary verb") in school grammars, and attach to the base 
+#  form of inflectional words.
+#  e.g. そう
+#名詞-特殊-助動詞語幹
+#
+#  noun-suffix: noun suffixes where the sub-classification is undefined.
+#名詞-接尾
+#
+#  noun-suffix-misc: Of the nouns or stem forms of other parts of speech that connect 
+#  to ガル or タイ and can combine into compound nouns, words that cannot be classified into
+#  any of the other categories below. In general, this category is more inclusive than 
+#  接尾語 ("suffix") and is usually the last element in a compound noun.
+#  e.g. おき, かた, 方, 甲斐 (がい), がかり, ぎみ, 気味, ぐるみ, (~した) さ, 次第, 済 (ず) み,
+#       よう, (でき)っこ, 感, 観, 性, 学, 類, 面, 用
+#名詞-接尾-一般
+#
+#  noun-suffix-person: Suffixes that form nouns and attach to person names more often
+#  than other nouns.
+#  e.g. 君, 様, 著
+#名詞-接尾-人名
+#
+#  noun-suffix-place: Suffixes that form nouns and attach to place names more often 
+#  than other nouns.
+#  e.g. 町, 市, 県
+#名詞-接尾-地域
+#
+#  noun-suffix-verbal: Of the suffixes that attach to nouns and form nouns, those that 
+#  can appear before スル ("suru").
+#  e.g. 化, 視, 分け, 入り, 落ち, 買い
+#名詞-接尾-サ変接続
+#
+#  noun-suffix-aux: The stem form of そうだ (様態) that is used to indicate conditions, 
+#  is treated as 助動詞 ("auxiliary verb") in school grammars, and attach to the 
+#  conjunctive form of inflectional words.
+#  e.g. そう
+#名詞-接尾-助動詞語幹
+#
+#  noun-suffix-adjective-base: Suffixes that attach to other nouns or the conjunctive 
+#  form of inflectional words and appear before the copula だ ("da").
+#  e.g. 的, げ, がち
+#名詞-接尾-形容動詞語幹
+#
+#  noun-suffix-adverbial: Suffixes that attach to other nouns and can behave as adverbs.
+#  e.g. 後 (ご), 以後, 以降, 以前, 前後, 中, 末, 上, 時 (じ)
+#名詞-接尾-副詞可能
+#
+#  noun-suffix-classifier: Suffixes that attach to numbers and form nouns. This category 
+#  is more inclusive than 助数詞 ("classifier") and includes common nouns that attach 
+#  to numbers.
+#  e.g. 個, つ, 本, 冊, パーセント, cm, kg, カ月, か国, 区画, 時間, 時半
+#名詞-接尾-助数詞
+#
+#  noun-suffix-special: Special suffixes that mainly attach to inflecting words.
+#  e.g. (楽し) さ, (考え) 方
+#名詞-接尾-特殊
+#
+#  noun-suffix-conjunctive: Nouns that behave like conjunctions and join two words 
+#  together.
+#  e.g. (日本) 対 (アメリカ), 対 (アメリカ), (3) 対 (5), (女優) 兼 (主婦)
+#名詞-接続詞的
+#
+#  noun-verbal_aux: Nouns that attach to the conjunctive particle て ("te") and are 
+#  semantically verb-like.
+#  e.g. ごらん, ご覧, 御覧, 頂戴
+#名詞-動詞非自立的
+#
+#  noun-quotation: text that cannot be segmented into words, proverbs, Chinese poetry, 
+#  dialects, English, etc. Currently, the only entry for 名詞 引用文字列 ("noun quotation") 
+#  is いわく ("iwaku").
+#名詞-引用文字列
+#
+#  noun-nai_adjective: Words that appear before the auxiliary verb ない ("nai") and
+#  behave like an adjective.
+#  e.g. 申し訳, 仕方, とんでも, 違い
+#名詞-ナイ形容詞語幹
+#
+#####
+#  prefix: unclassified prefixes
+#接頭詞
+#
+#  prefix-nominal: Prefixes that attach to nouns (including adjective stem forms) 
+#  excluding numerical expressions.
+#  e.g. お (水), 某 (氏), 同 (社), 故 (~氏), 高 (品質), お (見事), ご (立派)
+#接頭詞-名詞接続
+#
+#  prefix-verbal: Prefixes that attach to the imperative form of a verb or a verb
+#  in conjunctive form followed by なる/なさる/くださる.
+#  e.g. お (読みなさい), お (座り)
+#接頭詞-動詞接続
+#
+#  prefix-adjectival: Prefixes that attach to adjectives.
+#  e.g. お (寒いですねえ), バカ (でかい)
+#接頭詞-形容詞接続
+#
+#  prefix-numerical: Prefixes that attach to numerical expressions.
+#  e.g. 約, およそ, 毎時
+#接頭詞-数接続
+#
+#####
+#  verb: unclassified verbs
+#動詞
+#
+#  verb-main:
+#動詞-自立
+#
+#  verb-auxiliary:
+#動詞-非自立
+#
+#  verb-suffix:
+#動詞-接尾
+#
+#####
+#  adjective: unclassified adjectives
+#形容詞
+#
+#  adjective-main:
+#形容詞-自立
+#
+#  adjective-auxiliary:
+#形容詞-非自立
+#
+#  adjective-suffix:
+#形容詞-接尾
+#
+#####
+#  adverb: unclassified adverbs
+#副詞
+#
+#  adverb-misc: Words that can be segmented into one unit and where adnominal 
+#  modification is not possible.
+#  e.g. あいかわらず, 多分
+#副詞-一般
+#
+#  adverb-particle_conjunction: Adverbs that can be followed by の, は, に, 
+#  な, する, だ, etc.
+#  e.g. こんなに, そんなに, あんなに, なにか, なんでも
+#副詞-助詞類接続
+#
+#####
+#  adnominal: Words that only have noun-modifying forms.
+#  e.g. この, その, あの, どの, いわゆる, なんらかの, 何らかの, いろんな, こういう, そういう, ああいう, 
+#       どういう, こんな, そんな, あんな, どんな, 大きな, 小さな, おかしな, ほんの, たいした, 
+#       「(, も) さる (ことながら)」, 微々たる, 堂々たる, 単なる, いかなる, 我が」「同じ, 亡き
+#連体詞
+#
+#####
+#  conjunction: Conjunctions that can occur independently.
+#  e.g. が, けれども, そして, じゃあ, それどころか
+接続詞
+#
+#####
+#  particle: unclassified particles.
+助詞
+#
+#  particle-case: case particles where the subclassification is undefined.
+助詞-格助詞
+#
+#  particle-case-misc: Case particles.
+#  e.g. から, が, で, と, に, へ, より, を, の, にて
+助詞-格助詞-一般
+#
+#  particle-case-quote: the "to" that appears after nouns, a person’s speech, 
+#  quotation marks, expressions of decisions from a meeting, reasons, judgements,
+#  conjectures, etc.
+#  e.g. ( だ) と (述べた.), ( である) と (して執行猶予...)
+助詞-格助詞-引用
+#
+#  particle-case-compound: Compounds of particles and verbs that mainly behave 
+#  like case particles.
+#  e.g. という, といった, とかいう, として, とともに, と共に, でもって, にあたって, に当たって, に当って,
+#       にあたり, に当たり, に当り, に当たる, にあたる, において, に於いて,に於て, における, に於ける, 
+#       にかけ, にかけて, にかんし, に関し, にかんして, に関して, にかんする, に関する, に際し, 
+#       に際して, にしたがい, に従い, に従う, にしたがって, に従って, にたいし, に対し, にたいして, 
+#       に対して, にたいする, に対する, について, につき, につけ, につけて, につれ, につれて, にとって,
+#       にとり, にまつわる, によって, に依って, に因って, により, に依り, に因り, による, に依る, に因る, 
+#       にわたって, にわたる, をもって, を以って, を通じ, を通じて, を通して, をめぐって, をめぐり, をめぐる,
+#       って-口語/, ちゅう-関西弁「という」/, (何) ていう (人)-口語/, っていう-口語/, といふ, とかいふ
+助詞-格助詞-連語
+#
+#  particle-conjunctive:
+#  e.g. から, からには, が, けれど, けれども, けど, し, つつ, て, で, と, ところが, どころか, とも, ども, 
+#       ながら, なり, ので, のに, ば, ものの, や ( した), やいなや, (ころん) じゃ(いけない)-口語/, 
+#       (行っ) ちゃ(いけない)-口語/, (言っ) たって (しかたがない)-口語/, (それがなく)ったって (平気)-口語/
+助詞-接続助詞
+#
+#  particle-dependency:
+#  e.g. こそ, さえ, しか, すら, は, も, ぞ
+助詞-係助詞
+#
+#  particle-adverbial:
+#  e.g. がてら, かも, くらい, 位, ぐらい, しも, (学校) じゃ(これが流行っている)-口語/, 
+#       (それ)じゃあ (よくない)-口語/, ずつ, (私) なぞ, など, (私) なり (に), (先生) なんか (大嫌い)-口語/,
+#       (私) なんぞ, (先生) なんて (大嫌い)-口語/, のみ, だけ, (私) だって-口語/, だに, 
+#       (彼)ったら-口語/, (お茶) でも (いかが), 等 (とう), (今後) とも, ばかり, ばっか-口語/, ばっかり-口語/,
+#       ほど, 程, まで, 迄, (誰) も (が)([助詞-格助詞] および [助詞-係助詞] の前に位置する「も」)
+助詞-副助詞
+#
+#  particle-interjective: particles with interjective grammatical roles.
+#  e.g. (松島) や
+助詞-間投助詞
+#
+#  particle-coordinate:
+#  e.g. と, たり, だの, だり, とか, なり, や, やら
+助詞-並立助詞
+#
+#  particle-final:
+#  e.g. かい, かしら, さ, ぜ, (だ)っけ-口語/, (とまってる) で-方言/, な, ナ, なあ-口語/, ぞ, ね, ネ, 
+#       ねぇ-口語/, ねえ-口語/, ねん-方言/, の, のう-口語/, や, よ, ヨ, よぉ-口語/, わ, わい-口語/
+助詞-終助詞
+#
+#  particle-adverbial/conjunctive/final: The particle "ka" when unknown whether it is 
+#  adverbial, conjunctive, or sentence final. For example:
+#       (a) 「A か B か」. Ex:「(国内で運用する) か,(海外で運用する) か (.)」
+#       (b) Inside an adverb phrase. Ex:「(幸いという) か (, 死者はいなかった.)」
+#           「(祈りが届いたせい) か (, 試験に合格した.)」
+#       (c) 「かのように」. Ex:「(何もなかった) か (のように振る舞った.)」
+#  e.g. か
+助詞-副助詞/並立助詞/終助詞
+#
+#  particle-adnominalizer: The "no" that attaches to nouns and modifies 
+#  non-inflectional words.
+助詞-連体化
+#
+#  particle-adnominalizer: The "ni" and "to" that appear following nouns and adverbs 
+#  that are giongo, giseigo, or gitaigo.
+#  e.g. に, と
+助詞-副詞化
+#
+#  particle-special: A particle that does not fit into one of the above classifications. 
+#  This includes particles that are used in Tanka, Haiku, and other poetry.
+#  e.g. かな, けむ, ( しただろう) に, (あんた) にゃ(わからん), (俺) ん (家)
+助詞-特殊
+#
+#####
+#  auxiliary-verb:
+助動詞
+#
+#####
+#  interjection: Greetings and other exclamations.
+#  e.g. おはよう, おはようございます, こんにちは, こんばんは, ありがとう, どうもありがとう, ありがとうございます, 
+#       いただきます, ごちそうさま, さよなら, さようなら, はい, いいえ, ごめん, ごめんなさい
+#感動詞
+#
+#####
+#  symbol: unclassified Symbols.
+記号
+#
+#  symbol-misc: A general symbol not in one of the categories below.
+#  e.g. [○◎@$〒→+]
+記号-一般
+#
+#  symbol-comma: Commas
+#  e.g. [,、]
+記号-読点
+#
+#  symbol-period: Periods and full stops.
+#  e.g. [..。]
+記号-句点
+#
+#  symbol-space: Full-width whitespace.
+記号-空白
+#
+#  symbol-open_bracket:
+#  e.g. [({‘“『【]
+記号-括弧開
+#
+#  symbol-close_bracket:
+#  e.g. [)}’”』」】]
+記号-括弧閉
+#
+#  symbol-alphabetic:
+#記号-アルファベット
+#
+#####
+#  other: unclassified other
+#その他
+#
+#  other-interjection: Words that are hard to classify as noun-suffixes or 
+#  sentence-final particles.
+#  e.g. (だ)ァ
+その他-間投
+#
+#####
+#  filler: Aizuchi that occurs during a conversation or sounds inserted as filler.
+#  e.g. あの, うんと, えと
+フィラー
+#
+#####
+#  non-verbal: non-verbal sound.
+非言語音
+#
+#####
+#  fragment:
+#語断片
+#
+#####
+#  unknown: unknown part of speech.
+#未知語
+#
+##### End of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ar.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ar.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ar.txt
new file mode 100644
index 0000000..046829d
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ar.txt
@@ -0,0 +1,125 @@
+# This file was created by Jacques Savoy and is distributed under the BSD license.
+# See http://members.unine.ch/jacques.savoy/clef/index.html.
+# Also see http://www.opensource.org/licenses/bsd-license.html
+# Cleaned on October 11, 2009 (not normalized, so use before normalization)
+# This means that when modifying this list, you might need to add some 
+# redundant entries, for example containing forms with both أ and ا
+من
+ومن
+منها
+منه
+في
+وفي
+فيها
+فيه
+و
+ف
+ثم
+او
+أو
+ب
+بها
+به
+ا
+أ
+اى
+اي
+أي
+أى
+لا
+ولا
+الا
+ألا
+إلا
+لكن
+ما
+وما
+كما
+فما
+عن
+مع
+اذا
+إذا
+ان
+أن
+إن
+انها
+أنها
+إنها
+انه
+أنه
+إنه
+بان
+بأن
+فان
+فأن
+وان
+وأن
+وإن
+التى
+التي
+الذى
+الذي
+الذين
+الى
+الي
+إلى
+إلي
+على
+عليها
+عليه
+اما
+أما
+إما
+ايضا
+أيضا
+كل
+وكل
+لم
+ولم
+لن
+ولن
+هى
+هي
+هو
+وهى
+وهي
+وهو
+فهى
+فهي
+فهو
+انت
+أنت
+لك
+لها
+له
+هذه
+هذا
+تلك
+ذلك
+هناك
+كانت
+كان
+يكون
+تكون
+وكانت
+وكان
+غير
+بعض
+قد
+نحو
+بين
+بينما
+منذ
+ضمن
+حيث
+الان
+الآن
+خلال
+بعد
+قبل
+حتى
+عند
+عندما
+لدى
+جميع

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_bg.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_bg.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_bg.txt
new file mode 100644
index 0000000..1ae4ba2
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_bg.txt
@@ -0,0 +1,193 @@
+# This file was created by Jacques Savoy and is distributed under the BSD license.
+# See http://members.unine.ch/jacques.savoy/clef/index.html.
+# Also see http://www.opensource.org/licenses/bsd-license.html
+а
+аз
+ако
+ала
+бе
+без
+беше
+би
+бил
+била
+били
+било
+близо
+бъдат
+бъде
+бяха
+в
+вас
+ваш
+ваша
+вероятно
+вече
+взема
+ви
+вие
+винаги
+все
+всеки
+всички
+всичко
+всяка
+във
+въпреки
+върху
+г
+ги
+главно
+го
+д
+да
+дали
+до
+докато
+докога
+дори
+досега
+доста
+е
+едва
+един
+ето
+за
+зад
+заедно
+заради
+засега
+затова
+защо
+защото
+и
+из
+или
+им
+има
+имат
+иска
+й
+каза
+как
+каква
+какво
+както
+какъв
+като
+кога
+когато
+което
+които
+кой
+който
+колко
+която
+къде
+където
+към
+ли
+м
+ме
+между
+мен
+ми
+мнозина
+мога
+могат
+може
+моля
+момента
+му
+н
+на
+над
+назад
+най
+направи
+напред
+например
+нас
+не
+него
+нея
+ни
+ние
+никой
+нито
+но
+някои
+някой
+няма
+обаче
+около
+освен
+особено
+от
+отгоре
+отново
+още
+пак
+по
+повече
+повечето
+под
+поне
+поради
+после
+почти
+прави
+пред
+преди
+през
+при
+пък
+първо
+с
+са
+само
+се
+сега
+си
+скоро
+след
+сме
+според
+сред
+срещу
+сте
+съм
+със
+също
+т
+тази
+така
+такива
+такъв
+там
+твой
+те
+тези
+ти
+тн
+то
+това
+тогава
+този
+той
+толкова
+точно
+трябва
+тук
+тъй
+тя
+тях
+у
+харесва
+ч
+че
+често
+чрез
+ще
+щом
+я

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ca.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ca.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ca.txt
new file mode 100644
index 0000000..3da65de
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ca.txt
@@ -0,0 +1,220 @@
+# Catalan stopwords from http://github.com/vcl/cue.language (Apache 2 Licensed)
+a
+abans
+ací
+ah
+així
+això
+al
+als
+aleshores
+algun
+alguna
+algunes
+alguns
+alhora
+allà
+allí
+allò
+altra
+altre
+altres
+amb
+ambdós
+ambdues
+apa
+aquell
+aquella
+aquelles
+aquells
+aquest
+aquesta
+aquestes
+aquests
+aquí
+baix
+cada
+cadascú
+cadascuna
+cadascunes
+cadascuns
+com
+contra
+d'un
+d'una
+d'unes
+d'uns
+dalt
+de
+del
+dels
+des
+després
+dins
+dintre
+donat
+doncs
+durant
+e
+eh
+el
+els
+em
+en
+encara
+ens
+entre
+érem
+eren
+éreu
+es
+és
+esta
+està
+estàvem
+estaven
+estàveu
+esteu
+et
+etc
+ets
+fins
+fora
+gairebé
+ha
+han
+has
+havia
+he
+hem
+heu
+hi 
+ho
+i
+igual
+iguals
+ja
+l'hi
+la
+les
+li
+li'n
+llavors
+m'he
+ma
+mal
+malgrat
+mateix
+mateixa
+mateixes
+mateixos
+me
+mentre
+més
+meu
+meus
+meva
+meves
+molt
+molta
+moltes
+molts
+mon
+mons
+n'he
+n'hi
+ne
+ni
+no
+nogensmenys
+només
+nosaltres
+nostra
+nostre
+nostres
+o
+oh
+oi
+on
+pas
+pel
+pels
+per
+però
+perquè
+poc 
+poca
+pocs
+poques
+potser
+propi
+qual
+quals
+quan
+quant 
+que
+què
+quelcom
+qui
+quin
+quina
+quines
+quins
+s'ha
+s'han
+sa
+semblant
+semblants
+ses
+seu 
+seus
+seva
+seva
+seves
+si
+sobre
+sobretot
+sóc
+solament
+sols
+son 
+són
+sons 
+sota
+sou
+t'ha
+t'han
+t'he
+ta
+tal
+també
+tampoc
+tan
+tant
+tanta
+tantes
+teu
+teus
+teva
+teves
+ton
+tons
+tot
+tota
+totes
+tots
+un
+una
+unes
+uns
+us
+va
+vaig
+vam
+van
+vas
+veu
+vosaltres
+vostra
+vostre
+vostres

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_cz.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_cz.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_cz.txt
new file mode 100644
index 0000000..53c6097
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_cz.txt
@@ -0,0 +1,172 @@
+a
+s
+k
+o
+i
+u
+v
+z
+dnes
+cz
+tímto
+budeš
+budem
+byli
+jseš
+můj
+svým
+ta
+tomto
+tohle
+tuto
+tyto
+jej
+zda
+proč
+máte
+tato
+kam
+tohoto
+kdo
+kteří
+mi
+nám
+tom
+tomuto
+mít
+nic
+proto
+kterou
+byla
+toho
+protože
+asi
+ho
+naši
+napište
+re
+což
+tím
+takže
+svých
+její
+svými
+jste
+aj
+tu
+tedy
+teto
+bylo
+kde
+ke
+pravé
+ji
+nad
+nejsou
+či
+pod
+téma
+mezi
+přes
+ty
+pak
+vám
+ani
+když
+však
+neg
+jsem
+tento
+článku
+články
+aby
+jsme
+před
+pta
+jejich
+byl
+ještě
+až
+bez
+také
+pouze
+první
+vaše
+která
+nás
+nový
+tipy
+pokud
+může
+strana
+jeho
+své
+jiné
+zprávy
+nové
+není
+vás
+jen
+podle
+zde
+už
+být
+více
+bude
+již
+než
+který
+by
+které
+co
+nebo
+ten
+tak
+má
+při
+od
+po
+jsou
+jak
+další
+ale
+si
+se
+ve
+to
+jako
+za
+zpět
+ze
+do
+pro
+je
+na
+atd
+atp
+jakmile
+přičemž
+já
+on
+ona
+ono
+oni
+ony
+my
+vy
+jí
+ji
+mě
+mne
+jemu
+tomu
+těm
+těmu
+němu
+němuž
+jehož
+jíž
+jelikož
+jež
+jakož
+načež

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_da.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_da.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_da.txt
new file mode 100644
index 0000000..42e6145
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_da.txt
@@ -0,0 +1,110 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/danish/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Danish stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ | This is a ranked list (commonest to rarest) of stopwords derived from
+ | a large text sample.
+
+
+og           | and
+i            | in
+jeg          | I
+det          | that (dem. pronoun)/it (pers. pronoun)
+at           | that (in front of a sentence)/to (with infinitive)
+en           | a/an
+den          | it (pers. pronoun)/that (dem. pronoun)
+til          | to/at/for/until/against/by/of/into, more
+er           | present tense of "to be"
+som          | who, as
+på           | on/upon/in/on/at/to/after/of/with/for, on
+de           | they
+med          | with/by/in, along
+han          | he
+af           | of/by/from/off/for/in/with/on, off
+for          | at/for/to/from/by/of/ago, in front/before, because
+ikke         | not
+der          | who/which, there/those
+var          | past tense of "to be"
+mig          | me/myself
+sig          | oneself/himself/herself/itself/themselves
+men          | but
+et           | a/an/one, one (number), someone/somebody/one
+har          | present tense of "to have"
+om           | round/about/for/in/a, about/around/down, if
+vi           | we
+min          | my
+havde        | past tense of "to have"
+ham          | him
+hun          | she
+nu           | now
+over         | over/above/across/by/beyond/past/on/about, over/past
+da           | then, when/as/since
+fra          | from/off/since, off, since
+du           | you
+ud           | out
+sin          | his/her/its/one's
+dem          | them
+os           | us/ourselves
+op           | up
+man          | you/one
+hans         | his
+hvor         | where
+eller        | or
+hvad         | what
+skal         | must/shall etc.
+selv         | myself/youself/herself/ourselves etc., even
+her          | here
+alle         | all/everyone/everybody etc.
+vil          | will (verb)
+blev         | past tense of "to stay/to remain/to get/to become"
+kunne        | could
+ind          | in
+når          | when
+være         | present tense of "to be"
+dog          | however/yet/after all
+noget        | something
+ville        | would
+jo           | you know/you see (adv), yes
+deres        | their/theirs
+efter        | after/behind/according to/for/by/from, later/afterwards
+ned          | down
+skulle       | should
+denne        | this
+end          | than
+dette        | this
+mit          | my/mine
+også         | also
+under        | under/beneath/below/during, below/underneath
+have         | have
+dig          | you
+anden        | other
+hende        | her
+mine         | my
+alt          | everything
+meget        | much/very, plenty of
+sit          | his, her, its, one's
+sine         | his, her, its, one's
+vor          | our
+mod          | against
+disse        | these
+hvis         | if
+din          | your/yours
+nogle        | some
+hos          | by/at
+blive        | be/become
+mange        | many
+ad           | by/through
+bliver       | present tense of "to be/to become"
+hendes       | her/hers
+været        | be
+thi          | for (conj)
+jer          | you
+sådan        | such, like this/like that

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_de.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_de.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_de.txt
new file mode 100644
index 0000000..86525e7
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_de.txt
@@ -0,0 +1,294 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/german/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A German stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+ | The number of forms in this list is reduced significantly by passing it
+ | through the German stemmer.
+
+
+aber           |  but
+
+alle           |  all
+allem
+allen
+aller
+alles
+
+als            |  than, as
+also           |  so
+am             |  an + dem
+an             |  at
+
+ander          |  other
+andere
+anderem
+anderen
+anderer
+anderes
+anderm
+andern
+anderr
+anders
+
+auch           |  also
+auf            |  on
+aus            |  out of
+bei            |  by
+bin            |  am
+bis            |  until
+bist           |  art
+da             |  there
+damit          |  with it
+dann           |  then
+
+der            |  the
+den
+des
+dem
+die
+das
+
+daß            |  that
+
+derselbe       |  the same
+derselben
+denselben
+desselben
+demselben
+dieselbe
+dieselben
+dasselbe
+
+dazu           |  to that
+
+dein           |  thy
+deine
+deinem
+deinen
+deiner
+deines
+
+denn           |  because
+
+derer          |  of those
+dessen         |  of him
+
+dich           |  thee
+dir            |  to thee
+du             |  thou
+
+dies           |  this
+diese
+diesem
+diesen
+dieser
+dieses
+
+
+doch           |  (several meanings)
+dort           |  (over) there
+
+
+durch          |  through
+
+ein            |  a
+eine
+einem
+einen
+einer
+eines
+
+einig          |  some
+einige
+einigem
+einigen
+einiger
+einiges
+
+einmal         |  once
+
+er             |  he
+ihn            |  him
+ihm            |  to him
+
+es             |  it
+etwas          |  something
+
+euer           |  your
+eure
+eurem
+euren
+eurer
+eures
+
+für            |  for
+gegen          |  towards
+gewesen        |  p.p. of sein
+hab            |  have
+habe           |  have
+haben          |  have
+hat            |  has
+hatte          |  had
+hatten         |  had
+hier           |  here
+hin            |  there
+hinter         |  behind
+
+ich            |  I
+mich           |  me
+mir            |  to me
+
+
+ihr            |  you, to her
+ihre
+ihrem
+ihren
+ihrer
+ihres
+euch           |  to you
+
+im             |  in + dem
+in             |  in
+indem          |  while
+ins            |  in + das
+ist            |  is
+
+jede           |  each, every
+jedem
+jeden
+jeder
+jedes
+
+jene           |  that
+jenem
+jenen
+jener
+jenes
+
+jetzt          |  now
+kann           |  can
+
+kein           |  no
+keine
+keinem
+keinen
+keiner
+keines
+
+können         |  can
+könnte         |  could
+machen         |  do
+man            |  one
+
+manche         |  some, many a
+manchem
+manchen
+mancher
+manches
+
+mein           |  my
+meine
+meinem
+meinen
+meiner
+meines
+
+mit            |  with
+muss           |  must
+musste         |  had to
+nach           |  to(wards)
+nicht          |  not
+nichts         |  nothing
+noch           |  still, yet
+nun            |  now
+nur            |  only
+ob             |  whether
+oder           |  or
+ohne           |  without
+sehr           |  very
+
+sein           |  his
+seine
+seinem
+seinen
+seiner
+seines
+
+selbst         |  self
+sich           |  herself
+
+sie            |  they, she
+ihnen          |  to them
+
+sind           |  are
+so             |  so
+
+solche         |  such
+solchem
+solchen
+solcher
+solches
+
+soll           |  shall
+sollte         |  should
+sondern        |  but
+sonst          |  else
+über           |  over
+um             |  about, around
+und            |  and
+
+uns            |  us
+unse
+unsem
+unsen
+unser
+unses
+
+unter          |  under
+viel           |  much
+vom            |  von + dem
+von            |  from
+vor            |  before
+während        |  while
+war            |  was
+waren          |  were
+warst          |  wast
+was            |  what
+weg            |  away, off
+weil           |  because
+weiter         |  further
+
+welche         |  which
+welchem
+welchen
+welcher
+welches
+
+wenn           |  when
+werde          |  will
+werden         |  will
+wie            |  how
+wieder         |  again
+will           |  want
+wir            |  we
+wird           |  will
+wirst          |  willst
+wo             |  where
+wollen         |  want
+wollte         |  wanted
+würde          |  would
+würden         |  would
+zu             |  to
+zum            |  zu + dem
+zur            |  zu + der
+zwar           |  indeed
+zwischen       |  between
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_el.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_el.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_el.txt
new file mode 100644
index 0000000..232681f
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_el.txt
@@ -0,0 +1,78 @@
+# Lucene Greek Stopwords list
+# Note: by default this file is used after GreekLowerCaseFilter,
+# so when modifying this file use 'σ' instead of 'ς' 
+ο
+η
+το
+οι
+τα
+του
+τησ
+των
+τον
+την
+και 
+κι
+κ
+ειμαι
+εισαι
+ειναι
+ειμαστε
+ειστε
+στο
+στον
+στη
+στην
+μα
+αλλα
+απο
+για
+προσ
+με
+σε
+ωσ
+παρα
+αντι
+κατα
+μετα
+θα
+να
+δε
+δεν
+μη
+μην
+επι
+ενω
+εαν
+αν
+τοτε
+που
+πωσ
+ποιοσ
+ποια
+ποιο
+ποιοι
+ποιεσ
+ποιων
+ποιουσ
+αυτοσ
+αυτη
+αυτο
+αυτοι
+αυτων
+αυτουσ
+αυτεσ
+αυτα
+εκεινοσ
+εκεινη
+εκεινο
+εκεινοι
+εκεινεσ
+εκεινα
+εκεινων
+εκεινουσ
+οπωσ
+ομωσ
+ισωσ
+οσο
+οτι

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_en.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_en.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_en.txt
new file mode 100644
index 0000000..2c164c0
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_en.txt
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# a couple of test stopwords to test that the words are really being
+# configured from this file:
+stopworda
+stopwordb
+
+# Standard english stop words taken from Lucene's StopAnalyzer
+a
+an
+and
+are
+as
+at
+be
+but
+by
+for
+if
+in
+into
+is
+it
+no
+not
+of
+on
+or
+such
+that
+the
+their
+then
+there
+these
+they
+this
+to
+was
+will
+with

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_es.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_es.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_es.txt
new file mode 100644
index 0000000..487d78c
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_es.txt
@@ -0,0 +1,356 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/spanish/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A Spanish stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+
+ | The following is a ranked list (commonest to rarest) of stopwords
+ | deriving from a large sample of text.
+
+ | Extra words have been added at the end.
+
+de             |  from, of
+la             |  the, her
+que            |  who, that
+el             |  the
+en             |  in
+y              |  and
+a              |  to
+los            |  the, them
+del            |  de + el
+se             |  himself, from him etc
+las            |  the, them
+por            |  for, by, etc
+un             |  a
+para           |  for
+con            |  with
+no             |  no
+una            |  a
+su             |  his, her
+al             |  a + el
+  | es         from SER
+lo             |  him
+como           |  how
+más            |  more
+pero           |  pero
+sus            |  su plural
+le             |  to him, her
+ya             |  already
+o              |  or
+  | fue        from SER
+este           |  this
+  | ha         from HABER
+sí             |  himself etc
+porque         |  because
+esta           |  this
+  | son        from SER
+entre          |  between
+  | está     from ESTAR
+cuando         |  when
+muy            |  very
+sin            |  without
+sobre          |  on
+  | ser        from SER
+  | tiene      from TENER
+también        |  also
+me             |  me
+hasta          |  until
+hay            |  there is/are
+donde          |  where
+  | han        from HABER
+quien          |  whom, that
+  | están      from ESTAR
+  | estado     from ESTAR
+desde          |  from
+todo           |  all
+nos            |  us
+durante        |  during
+  | estados    from ESTAR
+todos          |  all
+uno            |  a
+les            |  to them
+ni             |  nor
+contra         |  against
+otros          |  other
+  | fueron     from SER
+ese            |  that
+eso            |  that
+  | había      from HABER
+ante           |  before
+ellos          |  they
+e              |  and (variant of y)
+esto           |  this
+mí             |  me
+antes          |  before
+algunos        |  some
+qué            |  what?
+unos           |  a
+yo             |  I
+otro           |  other
+otras          |  other
+otra           |  other
+él             |  he
+tanto          |  so much, many
+esa            |  that
+estos          |  these
+mucho          |  much, many
+quienes        |  who
+nada           |  nothing
+muchos         |  many
+cual           |  who
+  | sea        from SER
+poco           |  few
+ella           |  she
+estar          |  to be
+  | haber      from HABER
+estas          |  these
+  | estaba     from ESTAR
+  | estamos    from ESTAR
+algunas        |  some
+algo           |  something
+nosotros       |  we
+
+      | other forms
+
+mi             |  me
+mis            |  mi plural
+tú             |  thou
+te             |  thee
+ti             |  thee
+tu             |  thy
+tus            |  tu plural
+ellas          |  they
+nosotras       |  we
+vosotros       |  you
+vosotras       |  you
+os             |  you
+mío            |  mine
+mía            |
+míos           |
+mías           |
+tuyo           |  thine
+tuya           |
+tuyos          |
+tuyas          |
+suyo           |  his, hers, theirs
+suya           |
+suyos          |
+suyas          |
+nuestro        |  ours
+nuestra        |
+nuestros       |
+nuestras       |
+vuestro        |  yours
+vuestra        |
+vuestros       |
+vuestras       |
+esos           |  those
+esas           |  those
+
+               | forms of estar, to be (not including the infinitive):
+estoy
+estás
+está
+estamos
+estáis
+están
+esté
+estés
+estemos
+estéis
+estén
+estaré
+estarás
+estará
+estaremos
+estaréis
+estarán
+estaría
+estarías
+estaríamos
+estaríais
+estarían
+estaba
+estabas
+estábamos
+estabais
+estaban
+estuve
+estuviste
+estuvo
+estuvimos
+estuvisteis
+estuvieron
+estuviera
+estuvieras
+estuviéramos
+estuvierais
+estuvieran
+estuviese
+estuvieses
+estuviésemos
+estuvieseis
+estuviesen
+estando
+estado
+estada
+estados
+estadas
+estad
+
+               | forms of haber, to have (not including the infinitive):
+he
+has
+ha
+hemos
+habéis
+han
+haya
+hayas
+hayamos
+hayáis
+hayan
+habré
+habrás
+habrá
+habremos
+habréis
+habrán
+habría
+habrías
+habríamos
+habríais
+habrían
+había
+habías
+habíamos
+habíais
+habían
+hube
+hubiste
+hubo
+hubimos
+hubisteis
+hubieron
+hubiera
+hubieras
+hubiéramos
+hubierais
+hubieran
+hubiese
+hubieses
+hubiésemos
+hubieseis
+hubiesen
+habiendo
+habido
+habida
+habidos
+habidas
+
+               | forms of ser, to be (not including the infinitive):
+soy
+eres
+es
+somos
+sois
+son
+sea
+seas
+seamos
+seáis
+sean
+seré
+serás
+será
+seremos
+seréis
+serán
+sería
+serías
+seríamos
+seríais
+serían
+era
+eras
+éramos
+erais
+eran
+fui
+fuiste
+fue
+fuimos
+fuisteis
+fueron
+fuera
+fueras
+fuéramos
+fuerais
+fueran
+fuese
+fueses
+fuésemos
+fueseis
+fuesen
+siendo
+sido
+  |  sed also means 'thirst'
+
+               | forms of tener, to have (not including the infinitive):
+tengo
+tienes
+tiene
+tenemos
+tenéis
+tienen
+tenga
+tengas
+tengamos
+tengáis
+tengan
+tendré
+tendrás
+tendrá
+tendremos
+tendréis
+tendrán
+tendría
+tendrías
+tendríamos
+tendríais
+tendrían
+tenía
+tenías
+teníamos
+teníais
+tenían
+tuve
+tuviste
+tuvo
+tuvimos
+tuvisteis
+tuvieron
+tuviera
+tuvieras
+tuviéramos
+tuvierais
+tuvieran
+tuviese
+tuvieses
+tuviésemos
+tuvieseis
+tuviesen
+teniendo
+tenido
+tenida
+tenidos
+tenidas
+tened
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_eu.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_eu.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_eu.txt
new file mode 100644
index 0000000..25f1db9
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_eu.txt
@@ -0,0 +1,99 @@
+# example set of basque stopwords
+al
+anitz
+arabera
+asko
+baina
+bat
+batean
+batek
+bati
+batzuei
+batzuek
+batzuetan
+batzuk
+bera
+beraiek
+berau
+berauek
+bere
+berori
+beroriek
+beste
+bezala
+da
+dago
+dira
+ditu
+du
+dute
+edo
+egin
+ere
+eta
+eurak
+ez
+gainera
+gu
+gutxi
+guzti
+haiei
+haiek
+haietan
+hainbeste
+hala
+han
+handik
+hango
+hara
+hari
+hark
+hartan
+hau
+hauei
+hauek
+hauetan
+hemen
+hemendik
+hemengo
+hi
+hona
+honek
+honela
+honetan
+honi
+hor
+hori
+horiei
+horiek
+horietan
+horko
+horra
+horrek
+horrela
+horretan
+horri
+hortik
+hura
+izan
+ni
+noiz
+nola
+non
+nondik
+nongo
+nor
+nora
+ze
+zein
+zen
+zenbait
+zenbat
+zer
+zergatik
+ziren
+zituen
+zu
+zuek
+zuen
+zuten

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fa.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fa.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fa.txt
new file mode 100644
index 0000000..723641c
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fa.txt
@@ -0,0 +1,313 @@
+# This file was created by Jacques Savoy and is distributed under the BSD license.
+# See http://members.unine.ch/jacques.savoy/clef/index.html.
+# Also see http://www.opensource.org/licenses/bsd-license.html
+# Note: by default this file is used after normalization, so when adding entries
+# to this file, use the arabic 'ي' instead of 'ی'
+انان
+نداشته
+سراسر
+خياه
+ايشان
+وي
+تاكنون
+بيشتري
+دوم
+پس
+ناشي
+وگو
+يا
+داشتند
+سپس
+هنگام
+هرگز
+پنج
+نشان
+امسال
+ديگر
+گروهي
+شدند
+چطور
+ده
+و
+دو
+نخستين
+ولي
+چرا
+چه
+وسط
+ه
+كدام
+قابل
+يك
+رفت
+هفت
+همچنين
+در
+هزار
+بله
+بلي
+شايد
+اما
+شناسي
+گرفته
+دهد
+داشته
+دانست
+داشتن
+خواهيم
+ميليارد
+وقتيكه
+امد
+خواهد
+جز
+اورده
+شده
+بلكه
+خدمات
+شدن
+برخي
+نبود
+بسياري
+جلوگيري
+حق
+كردند
+نوعي
+بعري
+نكرده
+نظير
+نبايد
+بوده
+بودن
+داد
+اورد
+هست
+جايي
+شود
+دنبال
+داده
+بايد
+سابق
+هيچ
+همان
+انجا
+كمتر
+كجاست
+گردد
+كسي
+تر
+مردم
+تان
+دادن
+بودند
+سري
+جدا
+ندارند
+مگر
+يكديگر
+دارد
+دهند
+بنابراين
+هنگامي
+سمت
+جا
+انچه
+خود
+دادند
+زياد
+دارند
+اثر
+بدون
+بهترين
+بيشتر
+البته
+به
+براساس
+بيرون
+كرد
+بعضي
+گرفت
+توي
+اي
+ميليون
+او
+جريان
+تول
+بر
+مانند
+برابر
+باشيم
+مدتي
+گويند
+اكنون
+تا
+تنها
+جديد
+چند
+بي
+نشده
+كردن
+كردم
+گويد
+كرده
+كنيم
+نمي
+نزد
+روي
+قصد
+فقط
+بالاي
+ديگران
+اين
+ديروز
+توسط
+سوم
+ايم
+دانند
+سوي
+استفاده
+شما
+كنار
+داريم
+ساخته
+طور
+امده
+رفته
+نخست
+بيست
+نزديك
+طي
+كنيد
+از
+انها
+تمامي
+داشت
+يكي
+طريق
+اش
+چيست
+روب
+نمايد
+گفت
+چندين
+چيزي
+تواند
+ام
+ايا
+با
+ان
+ايد
+ترين
+اينكه
+ديگري
+راه
+هايي
+بروز
+همچنان
+پاعين
+كس
+حدود
+مختلف
+مقابل
+چيز
+گيرد
+ندارد
+ضد
+همچون
+سازي
+شان
+مورد
+باره
+مرسي
+خويش
+برخوردار
+چون
+خارج
+شش
+هنوز
+تحت
+ضمن
+هستيم
+گفته
+فكر
+بسيار
+پيش
+براي
+روزهاي
+انكه
+نخواهد
+بالا
+كل
+وقتي
+كي
+چنين
+كه
+گيري
+نيست
+است
+كجا
+كند
+نيز
+يابد
+بندي
+حتي
+توانند
+عقب
+خواست
+كنند
+بين
+تمام
+همه
+ما
+باشند
+مثل
+شد
+اري
+باشد
+اره
+طبق
+بعد
+اگر
+صورت
+غير
+جاي
+بيش
+ريزي
+اند
+زيرا
+چگونه
+بار
+لطفا
+مي
+درباره
+من
+ديده
+همين
+گذاري
+برداري
+علت
+گذاشته
+هم
+فوق
+نه
+ها
+شوند
+اباد
+همواره
+هر
+اول
+خواهند
+چهار
+نام
+امروز
+مان
+هاي
+قبل
+كنم
+سعي
+تازه
+را
+هستند
+زير
+جلوي
+عنوان
+بود

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fi.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fi.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fi.txt
new file mode 100644
index 0000000..4372c9a
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fi.txt
@@ -0,0 +1,97 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/finnish/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+ 
+| forms of BE
+
+olla
+olen
+olet
+on
+olemme
+olette
+ovat
+ole        | negative form
+
+oli
+olisi
+olisit
+olisin
+olisimme
+olisitte
+olisivat
+olit
+olin
+olimme
+olitte
+olivat
+ollut
+olleet
+
+en         | negation
+et
+ei
+emme
+ette
+eivät
+
+|Nom   Gen    Acc    Part   Iness   Elat    Illat  Adess   Ablat   Allat   Ess    Trans
+minä   minun  minut  minua  minussa minusta minuun minulla minulta minulle               | I
+sinä   sinun  sinut  sinua  sinussa sinusta sinuun sinulla sinulta sinulle               | you
+hän    hänen  hänet  häntä  hänessä hänestä häneen hänellä häneltä hänelle               | he she
+me     meidän meidät meitä  meissä  meistä  meihin meillä  meiltä  meille                | we
+te     teidän teidät teitä  teissä  teistä  teihin teillä  teiltä  teille                | you
+he     heidän heidät heitä  heissä  heistä  heihin heillä  heiltä  heille                | they
+
+tämä   tämän         tätä   tässä   tästä   tähän  tallä   tältä   tälle   tänä   täksi  | this
+tuo    tuon          tuotä  tuossa  tuosta  tuohon tuolla  tuolta  tuolle  tuona  tuoksi | that
+se     sen           sitä   siinä   siitä   siihen sillä   siltä   sille   sinä   siksi  | it
+nämä   näiden        näitä  näissä  näistä  näihin näillä  näiltä  näille  näinä  näiksi | these
+nuo    noiden        noita  noissa  noista  noihin noilla  noilta  noille  noina  noiksi | those
+ne     niiden        niitä  niissä  niistä  niihin niillä  niiltä  niille  niinä  niiksi | they
+
+kuka   kenen kenet   ketä   kenessä kenestä keneen kenellä keneltä kenelle kenenä keneksi| who
+ketkä  keiden ketkä  keitä  keissä  keistä  keihin keillä  keiltä  keille  keinä  keiksi | (pl)
+mikä   minkä minkä   mitä   missä   mistä   mihin  millä   miltä   mille   minä   miksi  | which what
+mitkä                                                                                    | (pl)
+
+joka   jonka         jota   jossa   josta   johon  jolla   jolta   jolle   jona   joksi  | who which
+jotka  joiden        joita  joissa  joista  joihin joilla  joilta  joille  joina  joiksi | (pl)
+
+| conjunctions
+
+että   | that
+ja     | and
+jos    | if
+koska  | because
+kuin   | than
+mutta  | but
+niin   | so
+sekä   | and
+sillä  | for
+tai    | or
+vaan   | but
+vai    | or
+vaikka | although
+
+
+| prepositions
+
+kanssa  | with
+mukaan  | according to
+noin    | about
+poikki  | across
+yli     | over, across
+
+| other
+
+kun    | when
+niin   | so
+nyt    | now
+itse   | self
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fr.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fr.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fr.txt
new file mode 100644
index 0000000..749abae
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_fr.txt
@@ -0,0 +1,186 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/french/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+
+ | A French stop word list. Comments begin with vertical bar. Each stop
+ | word is at the start of a line.
+
+au             |  a + le
+aux            |  a + les
+avec           |  with
+ce             |  this
+ces            |  these
+dans           |  with
+de             |  of
+des            |  de + les
+du             |  de + le
+elle           |  she
+en             |  `of them' etc
+et             |  and
+eux            |  them
+il             |  he
+je             |  I
+la             |  the
+le             |  the
+leur           |  their
+lui            |  him
+ma             |  my (fem)
+mais           |  but
+me             |  me
+même           |  same; as in moi-même (myself) etc
+mes            |  me (pl)
+moi            |  me
+mon            |  my (masc)
+ne             |  not
+nos            |  our (pl)
+notre          |  our
+nous           |  we
+on             |  one
+ou             |  where
+par            |  by
+pas            |  not
+pour           |  for
+qu             |  que before vowel
+que            |  that
+qui            |  who
+sa             |  his, her (fem)
+se             |  oneself
+ses            |  his (pl)
+son            |  his, her (masc)
+sur            |  on
+ta             |  thy (fem)
+te             |  thee
+tes            |  thy (pl)
+toi            |  thee
+ton            |  thy (masc)
+tu             |  thou
+un             |  a
+une            |  a
+vos            |  your (pl)
+votre          |  your
+vous           |  you
+
+               |  single letter forms
+
+c              |  c'
+d              |  d'
+j              |  j'
+l              |  l'
+à              |  to, at
+m              |  m'
+n              |  n'
+s              |  s'
+t              |  t'
+y              |  there
+
+               | forms of être (not including the infinitive):
+été
+étée
+étées
+étés
+étant
+suis
+es
+est
+sommes
+êtes
+sont
+serai
+seras
+sera
+serons
+serez
+seront
+serais
+serait
+serions
+seriez
+seraient
+étais
+était
+étions
+étiez
+étaient
+fus
+fut
+fûmes
+fûtes
+furent
+sois
+soit
+soyons
+soyez
+soient
+fusse
+fusses
+fût
+fussions
+fussiez
+fussent
+
+               | forms of avoir (not including the infinitive):
+ayant
+eu
+eue
+eues
+eus
+ai
+as
+avons
+avez
+ont
+aurai
+auras
+aura
+aurons
+aurez
+auront
+aurais
+aurait
+aurions
+auriez
+auraient
+avais
+avait
+avions
+aviez
+avaient
+eut
+eûmes
+eûtes
+eurent
+aie
+aies
+ait
+ayons
+ayez
+aient
+eusse
+eusses
+eût
+eussions
+eussiez
+eussent
+
+               | Later additions (from Jean-Christophe Deschamps)
+ceci           |  this
+cela           |  that
+celà           |  that
+cet            |  this
+cette          |  this
+ici            |  here
+ils            |  they
+les            |  the (pl)
+leurs          |  their (pl)
+quel           |  which
+quels          |  which
+quelle         |  which
+quelles        |  which
+sans           |  without
+soi            |  oneself
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ga.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ga.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ga.txt
new file mode 100644
index 0000000..9ff88d7
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_ga.txt
@@ -0,0 +1,110 @@
+
+a
+ach
+ag
+agus
+an
+aon
+ar
+arna
+as
+b'
+ba
+beirt
+bhúr
+caoga
+ceathair
+ceathrar
+chomh
+chtó
+chuig
+chun
+cois
+céad
+cúig
+cúigear
+d'
+daichead
+dar
+de
+deich
+deichniúr
+den
+dhá
+do
+don
+dtí
+dá
+dár
+dó
+faoi
+faoin
+faoina
+faoinár
+fara
+fiche
+gach
+gan
+go
+gur
+haon
+hocht
+i
+iad
+idir
+in
+ina
+ins
+inár
+is
+le
+leis
+lena
+lenár
+m'
+mar
+mo
+mé
+na
+nach
+naoi
+naonúr
+ná
+ní
+níor
+nó
+nócha
+ocht
+ochtar
+os
+roimh
+sa
+seacht
+seachtar
+seachtó
+seasca
+seisear
+siad
+sibh
+sinn
+sna
+sé
+sí
+tar
+thar
+thú
+triúr
+trí
+trína
+trínár
+tríocha
+tú
+um
+ár
+é
+éis
+í
+ó
+ón
+óna
+ónár

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_gl.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_gl.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_gl.txt
new file mode 100644
index 0000000..d8760b1
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_gl.txt
@@ -0,0 +1,161 @@
+# galican stopwords
+a
+aínda
+alí
+aquel
+aquela
+aquelas
+aqueles
+aquilo
+aquí
+ao
+aos
+as
+así
+á
+ben
+cando
+che
+co
+coa
+comigo
+con
+connosco
+contigo
+convosco
+coas
+cos
+cun
+cuns
+cunha
+cunhas
+da
+dalgunha
+dalgunhas
+dalgún
+dalgúns
+das
+de
+del
+dela
+delas
+deles
+desde
+deste
+do
+dos
+dun
+duns
+dunha
+dunhas
+e
+el
+ela
+elas
+eles
+en
+era
+eran
+esa
+esas
+ese
+eses
+esta
+estar
+estaba
+está
+están
+este
+estes
+estiven
+estou
+eu
+é
+facer
+foi
+foron
+fun
+había
+hai
+iso
+isto
+la
+las
+lle
+lles
+lo
+los
+mais
+me
+meu
+meus
+min
+miña
+miñas
+moi
+na
+nas
+neste
+nin
+no
+non
+nos
+nosa
+nosas
+noso
+nosos
+nós
+nun
+nunha
+nuns
+nunhas
+o
+os
+ou
+ó
+ós
+para
+pero
+pode
+pois
+pola
+polas
+polo
+polos
+por
+que
+se
+senón
+ser
+seu
+seus
+sexa
+sido
+sobre
+súa
+súas
+tamén
+tan
+te
+ten
+teñen
+teño
+ter
+teu
+teus
+ti
+tido
+tiña
+tiven
+túa
+túas
+un
+unha
+unhas
+uns
+vos
+vosa
+vosas
+voso
+vosos
+vós

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hi.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hi.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hi.txt
new file mode 100644
index 0000000..86286bb
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hi.txt
@@ -0,0 +1,235 @@
+# Also see http://www.opensource.org/licenses/bsd-license.html
+# See http://members.unine.ch/jacques.savoy/clef/index.html.
+# This file was created by Jacques Savoy and is distributed under the BSD license.
+# Note: by default this file also contains forms normalized by HindiNormalizer 
+# for spelling variation (see section below), such that it can be used whether or 
+# not you enable that feature. When adding additional entries to this list,
+# please add the normalized form as well. 
+अंदर
+अत
+अपना
+अपनी
+अपने
+अभी
+आदि
+आप
+इत्यादि
+इन 
+इनका
+इन्हीं
+इन्हें
+इन्हों
+इस
+इसका
+इसकी
+इसके
+इसमें
+इसी
+इसे
+उन
+उनका
+उनकी
+उनके
+उनको
+उन्हीं
+उन्हें
+उन्हों
+उस
+उसके
+उसी
+उसे
+एक
+एवं
+एस
+ऐसे
+और
+कई
+कर
+करता
+करते
+करना
+करने
+करें
+कहते
+कहा
+का
+काफ़ी
+कि
+कितना
+किन्हें
+किन्हों
+किया
+किर
+किस
+किसी
+किसे
+की
+कुछ
+कुल
+के
+को
+कोई
+कौन
+कौनसा
+गया
+घर
+जब
+जहाँ
+जा
+जितना
+जिन
+जिन्हें
+जिन्हों
+जिस
+जिसे
+जीधर
+जैसा
+जैसे
+जो
+तक
+तब
+तरह
+तिन
+तिन्हें
+तिन्हों
+तिस
+तिसे
+तो
+था
+थी
+थे
+दबारा
+दिया
+दुसरा
+दूसरे
+दो
+द्वारा
+न
+नहीं
+ना
+निहायत
+नीचे
+ने
+पर
+पर  
+पहले
+पूरा
+पे
+फिर
+बनी
+बही
+बहुत
+बाद
+बाला
+बिलकुल
+भी
+भीतर
+मगर
+मानो
+मे
+में
+यदि
+यह
+यहाँ
+यही
+या
+यिह 
+ये
+रखें
+रहा
+रहे
+ऱ्वासा
+लिए
+लिये
+लेकिन
+व
+वर्ग
+वह
+वह 
+वहाँ
+वहीं
+वाले
+वुह 
+वे
+वग़ैरह
+संग
+सकता
+सकते
+सबसे
+सभी
+साथ
+साबुत
+साभ
+सारा
+से
+सो
+ही
+हुआ
+हुई
+हुए
+है
+हैं
+हो
+होता
+होती
+होते
+होना
+होने
+# additional normalized forms of the above
+अपनि
+जेसे
+होति
+सभि
+तिंहों
+इंहों
+दवारा
+इसि
+किंहें
+थि
+उंहों
+ओर
+जिंहें
+वहिं
+अभि
+बनि
+हि
+उंहिं
+उंहें
+हें
+वगेरह
+एसे
+रवासा
+कोन
+निचे
+काफि
+उसि
+पुरा
+भितर
+हे
+बहि
+वहां
+कोइ
+यहां
+जिंहों
+तिंहें
+किसि
+कइ
+यहि
+इंहिं
+जिधर
+इंहें
+अदि
+इतयादि
+हुइ
+कोनसा
+इसकि
+दुसरे
+जहां
+अप
+किंहों
+उनकि
+भि
+वरग
+हुअ
+जेसा
+नहिं

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hu.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hu.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hu.txt
new file mode 100644
index 0000000..37526da
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hu.txt
@@ -0,0 +1,211 @@
+ | From svn.tartarus.org/snowball/trunk/website/algorithms/hungarian/stop.txt
+ | This file is distributed under the BSD License.
+ | See http://snowball.tartarus.org/license.php
+ | Also see http://www.opensource.org/licenses/bsd-license.html
+ |  - Encoding was converted to UTF-8.
+ |  - This notice was added.
+ |
+ | NOTE: To use this file with StopFilterFactory, you must specify format="snowball"
+ 
+| Hungarian stop word list
+| prepared by Anna Tordai
+
+a
+ahogy
+ahol
+aki
+akik
+akkor
+alatt
+által
+általában
+amely
+amelyek
+amelyekben
+amelyeket
+amelyet
+amelynek
+ami
+amit
+amolyan
+amíg
+amikor
+át
+abban
+ahhoz
+annak
+arra
+arról
+az
+azok
+azon
+azt
+azzal
+azért
+aztán
+azután
+azonban
+bár
+be
+belül
+benne
+cikk
+cikkek
+cikkeket
+csak
+de
+e
+eddig
+egész
+egy
+egyes
+egyetlen
+egyéb
+egyik
+egyre
+ekkor
+el
+elég
+ellen
+elő
+először
+előtt
+első
+én
+éppen
+ebben
+ehhez
+emilyen
+ennek
+erre
+ez
+ezt
+ezek
+ezen
+ezzel
+ezért
+és
+fel
+felé
+hanem
+hiszen
+hogy
+hogyan
+igen
+így
+illetve
+ill.
+ill
+ilyen
+ilyenkor
+ison
+ismét
+itt
+jó
+jól
+jobban
+kell
+kellett
+keresztül
+keressünk
+ki
+kívül
+között
+közül
+legalább
+lehet
+lehetett
+legyen
+lenne
+lenni
+lesz
+lett
+maga
+magát
+majd
+majd
+már
+más
+másik
+meg
+még
+mellett
+mert
+mely
+melyek
+mi
+mit
+míg
+miért
+milyen
+mikor
+minden
+mindent
+mindenki
+mindig
+mint
+mintha
+mivel
+most
+nagy
+nagyobb
+nagyon
+ne
+néha
+nekem
+neki
+nem
+néhány
+nélkül
+nincs
+olyan
+ott
+össze
+ő
+ők
+őket
+pedig
+persze
+rá
+s
+saját
+sem
+semmi
+sok
+sokat
+sokkal
+számára
+szemben
+szerint
+szinte
+talán
+tehát
+teljes
+tovább
+továbbá
+több
+úgy
+ugyanis
+új
+újabb
+újra
+után
+utána
+utolsó
+vagy
+vagyis
+valaki
+valami
+valamint
+való
+vagyok
+van
+vannak
+volt
+voltam
+voltak
+voltunk
+vissza
+vele
+viszont
+volna

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hy.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hy.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hy.txt
new file mode 100644
index 0000000..60c1c50
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_hy.txt
@@ -0,0 +1,46 @@
+# example set of Armenian stopwords.
+այդ
+այլ
+այն
+այս
+դու
+դուք
+եմ
+են
+ենք
+ես
+եք
+է
+էի
+էին
+էինք
+էիր
+էիք
+էր
+ըստ
+թ
+ի
+ին
+իսկ
+իր
+կամ
+համար
+հետ
+հետո
+մենք
+մեջ
+մի
+ն
+նա
+նաև
+նրա
+նրանք
+որ
+որը
+որոնք
+որպես
+ու
+ում
+պիտի
+վրա
+և

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_id.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_id.txt b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_id.txt
new file mode 100644
index 0000000..4617f83
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/lang/stopwords_id.txt
@@ -0,0 +1,359 @@
+# from appendix D of: A Study of Stemming Effects on Information
+# Retrieval in Bahasa Indonesia
+ada
+adanya
+adalah
+adapun
+agak
+agaknya
+agar
+akan
+akankah
+akhirnya
+aku
+akulah
+amat
+amatlah
+anda
+andalah
+antar
+diantaranya
+antara
+antaranya
+diantara
+apa
+apaan
+mengapa
+apabila
+apakah
+apalagi
+apatah
+atau
+ataukah
+ataupun
+bagai
+bagaikan
+sebagai
+sebagainya
+bagaimana
+bagaimanapun
+sebagaimana
+bagaimanakah
+bagi
+bahkan
+bahwa
+bahwasanya
+sebaliknya
+banyak
+sebanyak
+beberapa
+seberapa
+begini
+beginian
+beginikah
+beginilah
+sebegini
+begitu
+begitukah
+begitulah
+begitupun
+sebegitu
+belum
+belumlah
+sebelum
+sebelumnya
+sebenarnya
+berapa
+berapakah
+berapalah
+berapapun
+betulkah
+sebetulnya
+biasa
+biasanya
+bila
+bilakah
+bisa
+bisakah
+sebisanya
+boleh
+bolehkah
+bolehlah
+buat
+bukan
+bukankah
+bukanlah
+bukannya
+cuma
+percuma
+dahulu
+dalam
+dan
+dapat
+dari
+daripada
+dekat
+demi
+demikian
+demikianlah
+sedemikian
+dengan
+depan
+di
+dia
+dialah
+dini
+diri
+dirinya
+terdiri
+dong
+dulu
+enggak
+enggaknya
+entah
+entahlah
+terhadap
+terhadapnya
+hal
+hampir
+hanya
+hanyalah
+harus
+haruslah
+harusnya
+seharusnya
+hendak
+hendaklah
+hendaknya
+hingga
+sehingga
+ia
+ialah
+ibarat
+ingin
+inginkah
+inginkan
+ini
+inikah
+inilah
+itu
+itukah
+itulah
+jangan
+jangankan
+janganlah
+jika
+jikalau
+juga
+justru
+kala
+kalau
+kalaulah
+kalaupun
+kalian
+kami
+kamilah
+kamu
+kamulah
+kan
+kapan
+kapankah
+kapanpun
+dikarenakan
+karena
+karenanya
+ke
+kecil
+kemudian
+kenapa
+kepada
+kepadanya
+ketika
+seketika
+khususnya
+kini
+kinilah
+kiranya
+sekiranya
+kita
+kitalah
+kok
+lagi
+lagian
+selagi
+lah
+lain
+lainnya
+melainkan
+selaku
+lalu
+melalui
+terlalu
+lama
+lamanya
+selama
+selama
+selamanya
+lebih
+terlebih
+bermacam
+macam
+semacam
+maka
+makanya
+makin
+malah
+malahan
+mampu
+mampukah
+mana
+manakala
+manalagi
+masih
+masihkah
+semasih
+masing
+mau
+maupun
+semaunya
+memang
+mereka
+merekalah
+meski
+meskipun
+semula
+mungkin
+mungkinkah
+nah
+namun
+nanti
+nantinya
+nyaris
+oleh
+olehnya
+seorang
+seseorang
+pada
+padanya
+padahal
+paling
+sepanjang
+pantas
+sepantasnya
+sepantasnyalah
+para
+pasti
+pastilah
+per
+pernah
+pula
+pun
+merupakan
+rupanya
+serupa
+saat
+saatnya
+sesaat
+saja
+sajalah
+saling
+bersama
+sama
+sesama
+sambil
+sampai
+sana
+sangat
+sangatlah
+saya
+sayalah
+se
+sebab
+sebabnya
+sebuah
+tersebut
+tersebutlah
+sedang
+sedangkan
+sedikit
+sedikitnya
+segala
+segalanya
+segera
+sesegera
+sejak
+sejenak
+sekali
+sekalian
+sekalipun
+sesekali
+sekaligus
+sekarang
+sekarang
+sekitar
+sekitarnya
+sela
+selain
+selalu
+seluruh
+seluruhnya
+semakin
+sementara
+sempat
+semua
+semuanya
+sendiri
+sendirinya
+seolah
+seperti
+sepertinya
+sering
+seringnya
+serta
+siapa
+siapakah
+siapapun
+disini
+disinilah
+sini
+sinilah
+sesuatu
+sesuatunya
+suatu
+sesudah
+sesudahnya
+sudah
+sudahkah
+sudahlah
+supaya
+tadi
+tadinya
+tak
+tanpa
+setelah
+telah
+tentang
+tentu
+tentulah
+tentunya
+tertentu
+seterusnya
+tapi
+tetapi
+setiap
+tiap
+setidaknya
+tidak
+tidakkah
+tidaklah
+toh
+waduh
+wah
+wahai
+sewaktu
+walau
+walaupun
+wong
+yaitu
+yakni
+yang


[47/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10989: Randomize PointFields and general cleanup in schema files where some Trie fields were unused

Posted by ab...@apache.org.
SOLR-10989: Randomize PointFields and general cleanup in schema files where some Trie fields were unused


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/26d2ed7c
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/26d2ed7c
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/26d2ed7c

Branch: refs/heads/jira/solr-10879
Commit: 26d2ed7c4ddd2b8c714c2742dc9c42393bdb5d31
Parents: 2e1c506
Author: Chris Hostetter <ho...@apache.org>
Authored: Fri Jun 30 10:39:28 2017 -0700
Committer: Chris Hostetter <ho...@apache.org>
Committed: Fri Jun 30 10:39:28 2017 -0700

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  1 +
 .../conf/bad-schema-dup-fieldType.xml           |  4 +-
 .../collection1/conf/schema-binaryfield.xml     | 36 ---------------
 .../collection1/conf/schema-copyfield-test.xml  | 34 +++-----------
 .../collection1/conf/schema-customfield.xml     | 29 +-----------
 .../conf/schema-non-stored-docvalues.xml        | 47 +++-----------------
 .../conf/schema-not-required-unique-key.xml     |  1 -
 .../collection1/conf/schema-replication1.xml    |  1 -
 .../collection1/conf/schema-replication2.xml    |  1 -
 .../collection1/conf/schema-required-fields.xml | 34 +++-----------
 .../solr/collection1/conf/schema-reversed.xml   |  5 +--
 .../collection1/conf/schema-tokenizer-test.xml  | 21 +--------
 .../solr/collection1/conf/schema-version-dv.xml |  5 +--
 .../collection1/conf/schema-version-indexed.xml |  5 +--
 14 files changed, 26 insertions(+), 198 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 0d2226f..aadc6db 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -364,6 +364,7 @@ Other Changes
   - SOLR-10971: Randomize PointFields in CdcrBootstrapTest (hossman)
   - SOLR-10977: Randomize the usage of Points based numerics in schema15.xml and all impacted tests (hossman)
   - SOLR-10979: Randomize PointFields in schema-docValues*.xml and all affected tests (hossman)
+  - SOLR-10989: Randomize PointFields and general cleanup in schema files where some Trie fields were unused (hossman)
 
 * SOLR-6807: Changed requestDispatcher's handleSelect to default to false, thus ignoring "qt".
   Simplified configs to not refer to handleSelect or "qt".  Switch all tests that assumed true to assume false

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/bad-schema-dup-fieldType.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/bad-schema-dup-fieldType.xml b/solr/core/src/test-files/solr/collection1/conf/bad-schema-dup-fieldType.xml
index cd60df5..ac48c51 100644
--- a/solr/core/src/test-files/solr/collection1/conf/bad-schema-dup-fieldType.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/bad-schema-dup-fieldType.xml
@@ -22,8 +22,8 @@
   <fieldType name="string" class="solr.StrField"/>
 
   <!-- BEGIN BAD STUFF -->
-  <fieldType name="ftAgain" class="solr.TrieIntField"/>
-  <fieldType name="ftAgain" class="solr.TrieIntField"/>
+  <fieldType name="ftAgain" class="solr.StrField"/>
+  <fieldType name="ftAgain" class="solr.StrField"/>
   <!-- END BAD STUFF -->
 
   <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="false"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-binaryfield.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-binaryfield.xml b/solr/core/src/test-files/solr/collection1/conf/schema-binaryfield.xml
index 26a428d..f0f216b 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-binaryfield.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-binaryfield.xml
@@ -27,46 +27,10 @@
 
 <schema name="test" version="1.2">
 
-  <!-- field type definitions... note that the "name" attribute is
-       just a label to be used by field definitions.  The "class"
-       attribute and any other attributes determine the real type and
-       behavior of the fieldType.
-    -->
-
-  <!--
-    Default numeric field types. For faster range queries, consider the tint/tfloat/tlong/tdouble types.
-  -->
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
-
-  <!--
-   Numeric field types that index each value at various levels of precision
-   to accelerate range queries when the number of values between the range
-   endpoints is large. See the javadoc for LegacyNumericRangeQuery for internal
-   implementation details.
-
-   Smaller precisionStep values (specified in bits) will lead to more tokens
-   indexed per value, slightly larger index size, and faster range queries.
-   A precisionStep of 0 disables indexing at different precision levels.
-  -->
-  <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
-
-
   <fieldType name="binary" class="solr.BinaryField"/>
   <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
   <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
 
-  <!-- format for date is 1995-12-31T23:59:59.999Z and only the fractional
-       seconds part (.999) is optional.
-    -->
-  <fieldType name="date" class="solr.TrieDateField" sortMissingLast="true"/>
-
-
   <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
   <field name="data" type="binary" stored="true"/>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-copyfield-test.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-copyfield-test.xml b/solr/core/src/test-files/solr/collection1/conf/schema-copyfield-test.xml
index 96adf2d..adea3c1 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-copyfield-test.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-copyfield-test.xml
@@ -27,34 +27,10 @@
 
 <schema name="test" version="1.0">
 
-  <!-- field type definitions... note that the "name" attribute is
-       just a label to be used by field definitions.  The "class"
-       attribute and any other attributes determine the real type and
-       behavior of the fieldType.
-    -->
-
-  <!--
-    Default numeric field types. For faster range queries, consider the tint/tfloat/tlong/tdouble types.
-  -->
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
-
-  <!--
-   Numeric field types that index each value at various levels of precision
-   to accelerate range queries when the number of values between the range
-   endpoints is large. See the javadoc for LegacyNumericRangeQuery for internal
-   implementation details.
-
-   Smaller precisionStep values (specified in bits) will lead to more tokens
-   indexed per value, slightly larger index size, and faster range queries.
-   A precisionStep of 0 disables indexing at different precision levels.
-  -->
-  <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+  <fieldType name="float" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+  <fieldType name="double" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
 
   <!-- Field type demonstrating an Analyzer failure -->
   <fieldType name="failtype1" class="solr.TextField">
@@ -94,7 +70,7 @@
   <!-- format for date is 1995-12-31T23:59:59.999Z and only the fractional
        seconds part (.999) is optional.
     -->
-  <fieldType name="date" class="solr.TrieDateField" sortMissingLast="true"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" sortMissingLast="true"/>
 
   <!-- solr.TextField allows the specification of custom
        text analyzers specified as a tokenizer and a list

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-customfield.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-customfield.xml b/solr/core/src/test-files/solr/collection1/conf/schema-customfield.xml
index 83948b7..cfb147a 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-customfield.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-customfield.xml
@@ -27,35 +27,10 @@
 
 <schema name="test" version="1.2">
 
-  <!-- field type definitions... note that the "name" attribute is
-       just a label to be used by field definitions.  The "class"
-       attribute and any other attributes determine the real type and
-       behavior of the fieldType.
-    -->
   <fieldType name="string" class="solr.StrField"/>
 
-  <!--
-    Default numeric field types. For faster range queries, consider the tint/tfloat/tlong/tdouble types.
-  -->
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
-
-  <!--
-   Numeric field types that index each value at various levels of precision
-   to accelerate range queries when the number of values between the range
-   endpoints is large. See the javadoc for LegacyNumericRangeQuery for internal
-   implementation details.
-
-   Smaller precisionStep values (specified in bits) will lead to more tokens
-   indexed per value, slightly larger index size, and faster range queries.
-   A precisionStep of 0 disables indexing at different precision levels.
-  -->
-  <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
 
   <fieldType name="customfield" class="org.apache.solr.schema.MyCrazyCustomField" multiValued="true"
              positionIncrementGap="100">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-non-stored-docvalues.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-non-stored-docvalues.xml b/solr/core/src/test-files/solr/collection1/conf/schema-non-stored-docvalues.xml
index f700e60..4e631be 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-non-stored-docvalues.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-non-stored-docvalues.xml
@@ -17,52 +17,15 @@
 -->
 
 <schema name="test-non-stored-docvalues" version="1.6">
-  <!-- attribute "name" is the name of this schema and is only used for display purposes.
-       version="x.y" is Solr's version number for the schema syntax and 
-       semantics.  It should not normally be changed by applications.
-
-       1.0: multiValued attribute did not exist, all fields are multiValued 
-            by nature
-       1.1: multiValued attribute introduced, false by default 
-       1.2: omitTermFreqAndPositions attribute introduced, true by default 
-            except for text fields.
-       1.3: removed optional field compress feature
-       1.4: autoGeneratePhraseQueries attribute introduced to drive QueryParser
-            behavior when a single string produces multiple tokens.  Defaults 
-            to off for version >= 1.4
-       1.5: omitNorms defaults to true for primitive field types 
-            (int, float, boolean, string...)
-       1.6: useDocValuesAsStored defaults to true.
-     -->
-
-
-  <!-- field type definitions... note that the "name" attribute is
-       just a label to be used by field definitions.  The "class"
-       attribute and any other attributes determine the real type and
-       behavior of the fieldType.
-    -->
-
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-
-
-  <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
 
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="float" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="double" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
 
   <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
   <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
-
-  <!-- format for date is 1995-12-31T23:59:59.999Z and only the fractional
-       seconds part (.999) is optional.
-    -->
-  <fieldType name="date" class="solr.TrieDateField" precisionStep="0"/>
-  <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6"/>
-  <fieldType name="tdatedv" class="solr.TrieDateField" precisionStep="6" docValues="true"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0"/>
   <fieldType name="enumField" class="solr.EnumField" enumsConfig="enumsConfig.xml" enumName="severity"/>
 
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-not-required-unique-key.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-not-required-unique-key.xml b/solr/core/src/test-files/solr/collection1/conf/schema-not-required-unique-key.xml
index d38952f..ba8bbd5 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-not-required-unique-key.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-not-required-unique-key.xml
@@ -23,7 +23,6 @@
   -->
 <schema name="test" version="1.0">
   <fieldType name="string" class="solr.StrField"/>
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0"/>
   <fieldType name="text" class="solr.TextField">
     <analyzer>
       <tokenizer class="solr.StandardTokenizerFactory"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-replication1.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-replication1.xml b/solr/core/src/test-files/solr/collection1/conf/schema-replication1.xml
index eeb51bd..1a4e32e 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-replication1.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-replication1.xml
@@ -27,7 +27,6 @@
 
 <schema name="test" version="1.2">
 
-  <fieldType name="integer" class="solr.TrieIntField" precisionStep="0"/>
   <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
 
   <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="false"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-replication2.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-replication2.xml b/solr/core/src/test-files/solr/collection1/conf/schema-replication2.xml
index ade7bf5..8b83127 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-replication2.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-replication2.xml
@@ -27,7 +27,6 @@
 
 <schema name="test" version="1.2">
 
-  <fieldType name="integer" class="solr.TrieIntField" precisionStep="0"/>
   <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
 
   <field name="id" type="string" indexed="true" stored="true" multiValued="false" required="false"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-required-fields.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-required-fields.xml b/solr/core/src/test-files/solr/collection1/conf/schema-required-fields.xml
index 551ac1d..66add46 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-required-fields.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-required-fields.xml
@@ -27,34 +27,10 @@
 
 <schema name="test" version="1.0">
 
-  <!-- field type definitions... note that the "name" attribute is
-       just a label to be used by field definitions.  The "class"
-       attribute and any other attributes determine the real type and
-       behavior of the fieldType.
-    -->
-
-  <!--
-    Default numeric field types. For faster range queries, consider the tint/tfloat/tlong/tdouble types.
-  -->
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
-
-  <!--
-   Numeric field types that index each value at various levels of precision
-   to accelerate range queries when the number of values between the range
-   endpoints is large. See the javadoc for LegacyNumericRangeQuery for internal
-   implementation details.
-
-   Smaller precisionStep values (specified in bits) will lead to more tokens
-   indexed per value, slightly larger index size, and faster range queries.
-   A precisionStep of 0 disables indexing at different precision levels.
-  -->
-  <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0"/>
-  <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+  <fieldType name="float" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
+  <fieldType name="double" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
 
   <!-- Field type demonstrating an Analyzer failure -->
   <fieldType name="failtype1" class="solr.TextField">
@@ -77,7 +53,7 @@
   <!-- format for date is 1995-12-31T23:59:59.999Z and only the fractional
        seconds part (.999) is optional.
     -->
-  <fieldType name="date" class="solr.TrieDateField" sortMissingLast="true"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" sortMissingLast="true"/>
 
   <!-- solr.TextField allows the specification of custom
        text analyzers specified as a tokenizer and a list

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-reversed.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-reversed.xml b/solr/core/src/test-files/solr/collection1/conf/schema-reversed.xml
index 3bb52eb..bb9f981 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-reversed.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-reversed.xml
@@ -22,10 +22,7 @@
   -->
 
 <schema name="test" version="1.0">
-
-
-  <fieldType name="long" class="solr.TrieLongField"/>
-  <fieldType name="integer" class="solr.TrieIntField" precisionStep="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}"/>
   <fieldType name="string" class="solr.StrField"/>
 
   <fieldType name="text" class="solr.TextField">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-tokenizer-test.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-tokenizer-test.xml b/solr/core/src/test-files/solr/collection1/conf/schema-tokenizer-test.xml
index 174787e..6c33504 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-tokenizer-test.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-tokenizer-test.xml
@@ -27,27 +27,8 @@ more concise example.
 
 <schema name="test" version="1.0">
 
-  <!-- field type definitions... note that the "name" attribute is
-  just a label to be used by field definitions.  The "class"
-  attribute and any other attributes determine the real type and
-  behavior of the fieldType.
-  -->
   <fieldType name="string" class="solr.StrField" />
-             
-  <!--
-  Default numeric field types. For faster range queries, consider the tint/tfloat/tlong/tdouble types.
-  -->
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
-
-  <!--
-  Numeric field types that index each value at various levels of precision
-  to accelerate range queries when the number of values between the range
-  endpoints is large. See the javadoc for LegacyNumericRangeQuery for internal
-  implementation details.
-  -->
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
 
   <!-- Seperate analyzers for index and query time -->
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-version-dv.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-version-dv.xml b/solr/core/src/test-files/solr/collection1/conf/schema-version-dv.xml
index 593b2a2..375311a 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-version-dv.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-version-dv.xml
@@ -16,15 +16,14 @@
  limitations under the License.
 -->
 <schema name="example" version="1.6">
-  <field name="_version_" type="${solr.tests.longClass:plong}" indexed="false" docValues="true" stored="true"/>
+  <field name="_version_" type="long" indexed="false" docValues="true" stored="true"/>
   <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false"/>
   <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
   <field name="signatureField" type="string" indexed="true" stored="false"/>
   <dynamicField name="*_sS" type="string" indexed="false" stored="true"/>
   <uniqueKey>id</uniqueKey>
   <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="plong" class="solr.LongPointField" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
   <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
     <analyzer>
       <tokenizer class="solr.StandardTokenizerFactory"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/26d2ed7c/solr/core/src/test-files/solr/collection1/conf/schema-version-indexed.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-version-indexed.xml b/solr/core/src/test-files/solr/collection1/conf/schema-version-indexed.xml
index 06d6b65..4523d50 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-version-indexed.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-version-indexed.xml
@@ -16,15 +16,14 @@
  limitations under the License.
 -->
 <schema name="example" version="1.6">
-  <field name="_version_" type="${solr.tests.longClass:plong}" indexed="true" docValues="false" stored="true" />
+  <field name="_version_" type="long" indexed="true" docValues="false" stored="true" />
   <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false"/>
   <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
   <field name="signatureField" type="string" indexed="true" stored="false"/>
   <dynamicField name="*_sS" type="string" indexed="false" stored="true"/>
   <uniqueKey>id</uniqueKey>
   <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
-  <fieldType name="plong" class="solr.LongPointField" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
   <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
     <analyzer>
       <tokenizer class="solr.StandardTokenizerFactory"/>


[10/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsRequest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsRequest.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsRequest.java
deleted file mode 100644
index d147e6e..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsRequest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.request;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Contains the specifications of an Analytics Request, specifically a name,
- * a list of Expressions, a list of field facets, a list of range facets, a list of query facets
- * and the list of expressions and their results calculated in previous AnalyticsRequests.
- */
-public class AnalyticsRequest {
-  
-  private String name;
-  private List<ExpressionRequest> expressions;
-  private Set<String> hiddenExpressions;
-  private List<FieldFacetRequest> fieldFacets;
-  private List<RangeFacetRequest> rangeFacets;
-  private List<QueryFacetRequest> queryFacets;
-  
-  public AnalyticsRequest(String name) {
-    this.name = name;
-    expressions = new ArrayList<>();
-    hiddenExpressions = new HashSet<>();
-    fieldFacets = new ArrayList<>();
-    rangeFacets = new ArrayList<>();
-    queryFacets = new ArrayList<>();
-  }
-  
-  public String getName() {
-    return name;
-  }
-  
-  public void setExpressions(List<ExpressionRequest> expressions) {
-    this.expressions = expressions;
-  }
-
-  public void addExpression(ExpressionRequest expressionRequest) {
-    expressions.add(expressionRequest);
-  }
-  
-  public List<ExpressionRequest> getExpressions() {
-    return expressions;
-  }
-
-  public void addHiddenExpression(ExpressionRequest expressionRequest) {
-    expressions.add(expressionRequest);
-    hiddenExpressions.add(expressionRequest.getName());
-  }
-  
-  public Set<String> getHiddenExpressions() {
-    return hiddenExpressions;
-  }
-  
-  public void setFieldFacets(List<FieldFacetRequest> fieldFacets) {
-    this.fieldFacets = fieldFacets;
-  }
-  
-  public List<FieldFacetRequest> getFieldFacets() {
-    return fieldFacets;
-  }
-  
-  public void setRangeFacets(List<RangeFacetRequest> rangeFacets) {
-    this.rangeFacets = rangeFacets;
-  }
-  
-  public List<RangeFacetRequest> getRangeFacets() {
-    return rangeFacets;
-  }
-  
-  public void setQueryFacets(List<QueryFacetRequest> queryFacets) {
-    this.queryFacets = queryFacets;
-  }
-  
-  public List<QueryFacetRequest> getQueryFacets() {
-    return queryFacets;
-  }
-  
-  @Override
-  public String toString() {
-    StringBuilder builder = new StringBuilder("<AnalyticsRequest name=" + name + ">");
-    for (ExpressionRequest exp : expressions) {
-      builder.append(exp.toString());
-    }
-    for (FieldFacetRequest facet : fieldFacets) {
-      builder.append(facet.toString());
-    }
-    for (RangeFacetRequest facet : rangeFacets) {
-      builder.append(facet.toString());
-    }
-    for (QueryFacetRequest facet : queryFacets) {
-      builder.append(facet.toString());
-    }
-    builder.append("</AnalyticsRequest>");
-    return builder.toString();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsRequestFactory.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsRequestFactory.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsRequestFactory.java
deleted file mode 100644
index 3773ff6..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsRequestFactory.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.request;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.solr.analytics.request.FieldFacetRequest.FacetSortSpecification;
-import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.common.params.FacetParams.FacetRangeInclude;
-import org.apache.solr.common.params.FacetParams.FacetRangeOther;
-import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.schema.IndexSchema;
-
-/**
- * Parses the SolrParams to create a list of analytics requests.
- */
-public class AnalyticsRequestFactory implements AnalyticsParams {
-
-  public static final Pattern statPattern = Pattern.compile("^o(?:lap)?\\.([^\\.]+)\\.(?:"+EXPRESSION+")\\.([^\\.]+)$", Pattern.CASE_INSENSITIVE);
-  public static final Pattern hiddenStatPattern = Pattern.compile("^o(?:lap)?\\.([^\\.]+)\\.(?:"+HIDDEN_EXPRESSION+")\\.([^\\.]+)$", Pattern.CASE_INSENSITIVE);
-  public static final Pattern fieldFacetPattern = Pattern.compile("^o(?:lap)?\\.([^\\.]+)\\.(?:"+FIELD_FACET+")$", Pattern.CASE_INSENSITIVE);
-  public static final Pattern fieldFacetParamPattern = Pattern.compile("^o(?:lap)?\\.([^\\.]+)\\.(?:"+FIELD_FACET+")\\.([^\\.]+)\\.("+LIMIT+"|"+OFFSET+"|"+HIDDEN+"|"+SHOW_MISSING+"|"+SORT_STATISTIC+"|"+SORT_DIRECTION+")$", Pattern.CASE_INSENSITIVE);
-  public static final Pattern rangeFacetPattern = Pattern.compile("^o(?:lap)?\\.([^\\.]+)\\.(?:"+RANGE_FACET+")$", Pattern.CASE_INSENSITIVE);
-  public static final Pattern rangeFacetParamPattern = Pattern.compile("^o(?:lap)?\\.([^\\.]+)\\.(?:"+RANGE_FACET+")\\.([^\\.]+)\\.("+START+"|"+END+"|"+GAP+"|"+HARDEND+"|"+INCLUDE_BOUNDARY+"|"+OTHER_RANGE+")$", Pattern.CASE_INSENSITIVE);
-  public static final Pattern queryFacetPattern = Pattern.compile("^o(?:lap)?\\.([^\\.]+)\\.(?:"+QUERY_FACET+")$", Pattern.CASE_INSENSITIVE);
-  public static final Pattern queryFacetParamPattern = Pattern.compile("^o(?:lap)?\\.([^\\.]+)\\.(?:"+QUERY_FACET+")\\.([^\\.]+)\\.("+QUERY+"|"+DEPENDENCY+")$", Pattern.CASE_INSENSITIVE);
-  
-  public static List<AnalyticsRequest> parse(IndexSchema schema, SolrParams params) {
-    Map<String, AnalyticsRequest> requestMap = new HashMap<>();
-    Map<String, Map<String,FieldFacetRequest>> fieldFacetMap = new HashMap<>();
-    Map<String, Set<String>> fieldFacetSet = new HashMap<>();
-    Map<String, Map<String,RangeFacetRequest>> rangeFacetMap = new HashMap<>();
-    Map<String, Set<String>> rangeFacetSet = new HashMap<>();
-    Map<String, Map<String,QueryFacetRequest>> queryFacetMap = new HashMap<>();
-    Map<String, Set<String>> queryFacetSet = new HashMap<>();
-    List<AnalyticsRequest> requestList = new ArrayList<>();
-    
-    Iterator<String> paramsIterator = params.getParameterNamesIterator();
-    while (paramsIterator.hasNext()) {
-      String param = paramsIterator.next();
-      CharSequence paramSequence = param.subSequence(0, param.length());
-      
-      // Check if stat
-      Matcher m = statPattern.matcher(paramSequence);
-      if (m.matches()) {
-        makeExpression(requestMap,m.group(1),m.group(2),params.get(param));
-      } else {
-        // Check if hidden stat
-        m = hiddenStatPattern.matcher(paramSequence);
-        if (m.matches()) {
-          makeHiddenExpression(requestMap,m.group(1),m.group(2),params.get(param));
-        } else {
-          // Check if field facet
-          m = fieldFacetPattern.matcher(paramSequence);
-          if (m.matches()) {
-            makeFieldFacet(schema,fieldFacetMap,fieldFacetSet,m.group(1),params.getParams(param));
-          } else {
-            // Check if field facet parameter
-            m = fieldFacetParamPattern.matcher(paramSequence);
-            if (m.matches()) {
-              setFieldFacetParam(schema,fieldFacetMap,m.group(1),m.group(2),m.group(3),params.getParams(param));
-            } else {
-              // Check if range facet
-              m = rangeFacetPattern.matcher(paramSequence);
-              if (m.matches()) {
-                makeRangeFacet(schema,rangeFacetSet,m.group(1),params.getParams(param));
-              }  else {
-                // Check if range facet parameter
-                m = rangeFacetParamPattern.matcher(paramSequence);
-                if (m.matches()) {
-                  setRangeFacetParam(schema,rangeFacetMap,m.group(1),m.group(2),m.group(3),params.getParams(param));
-                }  else {
-                  // Check if query facet
-                  m = queryFacetPattern.matcher(paramSequence);
-                  if (m.matches()) {
-                    makeQueryFacet(schema,queryFacetSet,m.group(1),params.getParams(param));
-                  }  else {
-                    // Check if query
-                    m = queryFacetParamPattern.matcher(paramSequence);
-                    if (m.matches()) {
-                      setQueryFacetParam(schema,queryFacetMap,m.group(1),m.group(2),m.group(3),params.getParams(param));
-                    } 
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-    for (String reqName : requestMap.keySet()) {
-      AnalyticsRequest ar = requestMap.get(reqName);
-      List<FieldFacetRequest> ffrs = new ArrayList<>();
-      if (fieldFacetSet.get(reqName)!=null) {
-        for (String field : fieldFacetSet.get(reqName)) {
-          ffrs.add(fieldFacetMap.get(reqName).get(field));
-        }
-      }
-      ar.setFieldFacets(ffrs);
-      
-      List<RangeFacetRequest> rfrs = new ArrayList<>();
-      if (rangeFacetSet.get(reqName)!=null) {
-        for (String field : rangeFacetSet.get(reqName)) {
-          RangeFacetRequest rfr = rangeFacetMap.get(reqName).get(field);
-          if (rfr != null) {
-            rfrs.add(rfr);
-          }
-        }
-      }
-      ar.setRangeFacets(rfrs);
-      
-      List<QueryFacetRequest> qfrs = new ArrayList<>();
-      if (queryFacetSet.get(reqName)!=null) {
-        for (String name : queryFacetSet.get(reqName)) {
-          QueryFacetRequest qfr = queryFacetMap.get(reqName).get(name);
-          if (qfr != null) {
-            addQueryFacet(qfrs,qfr);
-          }
-        }
-      }
-      for (QueryFacetRequest qfr : qfrs) {
-        if (qfr.getDependencies().size()>0) {
-          throw new SolrException(ErrorCode.BAD_REQUEST,"The query facet dependencies "+qfr.getDependencies().toString()+" either do not exist or are defined in a dependency looop.");
-        }
-      }
-      ar.setQueryFacets(qfrs);
-      requestList.add(ar);
-    }
-    return requestList; 
-  }
-
-  private static void makeFieldFacet(IndexSchema schema, Map<String, Map<String, FieldFacetRequest>> fieldFacetMap, Map<String, Set<String>> fieldFacetSet, String requestName, String[] fields) {
-    Map<String, FieldFacetRequest> facetMap = fieldFacetMap.get(requestName);
-    if (facetMap == null) {
-      facetMap = new HashMap<>();
-      fieldFacetMap.put(requestName, facetMap);
-    }
-    Set<String> set = fieldFacetSet.get(requestName);
-    if (set == null) {
-      set = new HashSet<>();
-      fieldFacetSet.put(requestName, set);
-    }
-    for (String field : fields) {
-      if (facetMap.get(field) == null) {
-        facetMap.put(field,new FieldFacetRequest(schema.getField(field)));
-      }
-      set.add(field);
-    }
-  }
-
-  private static void setFieldFacetParam(IndexSchema schema, Map<String, Map<String, FieldFacetRequest>> fieldFacetMap, String requestName, String field, String paramType, String[] params) {
-    Map<String, FieldFacetRequest> facetMap = fieldFacetMap.get(requestName);
-    if (facetMap == null) {
-      facetMap = new HashMap<>();
-      fieldFacetMap.put(requestName, facetMap);
-    }
-    FieldFacetRequest fr = facetMap.get(field);
-    if (fr == null) {
-      fr = new FieldFacetRequest(schema.getField(field));
-      facetMap.put(field,fr);
-    }
-    if (paramType.equals("limit")||paramType.equals("l")) {
-      fr.setLimit(Integer.parseInt(params[0]));
-    } else if (paramType.equals("offset")||paramType.equals("off")) {
-      fr.setOffset(Integer.parseInt(params[0]));
-    } else if (paramType.equals("hidden")||paramType.equals("h")) {
-      fr.setHidden(Boolean.parseBoolean(params[0]));
-    } else if (paramType.equals("showmissing")||paramType.equals("sm")) {
-      fr.showMissing(Boolean.parseBoolean(params[0]));
-    } else if (paramType.equals("sortstatistic")||paramType.equals("sortstat")||paramType.equals("ss")) {
-      fr.setSort(new FacetSortSpecification(params[0],fr.getDirection()));
-    } else if (paramType.equals("sortdirection")||paramType.equals("sd")) {
-      fr.setDirection(params[0]);
-    } 
-  }
-
-  private static void makeRangeFacet(IndexSchema schema, Map<String, Set<String>> rangeFacetSet, String requestName, String[] fields) {
-    Set<String> set = rangeFacetSet.get(requestName);
-    if (set == null) {
-      set = new HashSet<>();
-      rangeFacetSet.put(requestName, set);
-    }
-    for (String field : fields) {
-      set.add(field);
-    }
-  }
-
-  private static void setRangeFacetParam(IndexSchema schema, Map<String, Map<String, RangeFacetRequest>> rangeFacetMap, String requestName, String field, String paramType, String[] params) {
-    Map<String, RangeFacetRequest> facetMap = rangeFacetMap.get(requestName);
-    if (facetMap == null) {
-      facetMap = new HashMap<>();
-      rangeFacetMap.put(requestName, facetMap);
-    }
-    RangeFacetRequest rr = facetMap.get(field);
-    if (rr == null) {
-      rr = new RangeFacetRequest(schema.getField(field));
-      facetMap.put(field,rr);
-    }
-    if (paramType.equals("start")||paramType.equals("st")) {
-      rr.setStart(params[0]);
-    } else if (paramType.equals("end")||paramType.equals("e")) {
-      rr.setEnd(params[0]);
-    } else if (paramType.equals("gap")||paramType.equals("g")) {
-      rr.setGaps(params[0].split(","));
-    } else if (paramType.equals("hardend")||paramType.equals("he")) {
-      rr.setHardEnd(Boolean.parseBoolean(params[0]));
-    } else if (paramType.equals("includebound")||paramType.equals("ib")) {
-      for (String param : params) {
-        rr.addInclude(FacetRangeInclude.get(param));
-      }
-    } else if (paramType.equals("otherrange")||paramType.equals("or")) {
-      for (String param : params) {
-        rr.addOther(FacetRangeOther.get(param));
-      }
-    } 
-  }
-
-  private static void makeQueryFacet(IndexSchema schema,Map<String, Set<String>> queryFacetSet, String requestName, String[] names) {
-    Set<String> set = queryFacetSet.get(requestName);
-    if (set == null) {
-      set = new HashSet<>();
-      queryFacetSet.put(requestName, set);
-    }
-    for (String name : names) {
-      set.add(name);
-    }
-  }
-
-  private static void setQueryFacetParam(IndexSchema schema, Map<String, Map<String, QueryFacetRequest>> queryFacetMap, String requestName, String name, String paramType, String[] params) {
-    Map<String, QueryFacetRequest> facetMap = queryFacetMap.get(requestName);
-    if (facetMap == null) {
-      facetMap = new HashMap<>();
-      queryFacetMap.put(requestName, facetMap);
-    }
-    QueryFacetRequest qr = facetMap.get(name);
-    if (qr == null) {
-      qr = new QueryFacetRequest(name);
-      facetMap.put(name,qr);
-    }
-    if (paramType.equals("query")||paramType.equals("q")) {
-      for (String query : params) {
-        qr.addQuery(query);
-      }
-    } else if (paramType.equals("dependency")||paramType.equals("d")) {
-      for (String depend : params) {
-        qr.addDependency(depend);
-      }
-    }
-  }
-
-  private static void makeHiddenExpression(Map<String, AnalyticsRequest> requestMap, String requestName, String expressionName, String expression) {
-    AnalyticsRequest req = requestMap.get(requestName);
-    if (req == null) {
-      req = new AnalyticsRequest(requestName);
-      requestMap.put(requestName, req);
-    }
-    req.addHiddenExpression(new ExpressionRequest(expressionName,expression));
-  }
-
-  private static void makeExpression(Map<String, AnalyticsRequest> requestMap, String requestName, String expressionName, String expression) {
-    AnalyticsRequest req = requestMap.get(requestName);
-    if (req == null) {
-      req = new AnalyticsRequest(requestName);
-      requestMap.put(requestName, req);
-    }
-    req.addExpression(new ExpressionRequest(expressionName,expression));
-  }
-  
-  private static void addQueryFacet(List<QueryFacetRequest> currentList, QueryFacetRequest queryFacet) {
-    Set<String> depends = queryFacet.getDependencies();
-    int place = 0;
-    for (QueryFacetRequest qfr : currentList) {
-      if (qfr.getDependencies().remove(queryFacet.getName())) {
-        break;
-      }
-      place++;
-      depends.remove(qfr.getName());
-    }
-    currentList.add(place,queryFacet);
-    for (int count = place+1; count < currentList.size(); count++) {
-      currentList.get(count).getDependencies().remove(queryFacet.getName());
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsStats.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsStats.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsStats.java
deleted file mode 100644
index 771aff7..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsStats.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.request;
-
-import java.io.IOException;
-import java.lang.invoke.MethodHandles;
-import java.util.List;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.search.DocIdSet;
-import org.apache.lucene.search.DocIdSetIterator;
-import org.apache.solr.analytics.accumulator.BasicAccumulator;
-import org.apache.solr.analytics.accumulator.FacetingAccumulator;
-import org.apache.solr.analytics.accumulator.ValueAccumulator;
-import org.apache.solr.analytics.plugin.AnalyticsStatisticsCollector;
-import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.search.DocSet;
-import org.apache.solr.search.Filter;
-import org.apache.solr.search.SolrIndexSearcher;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Class which computes the set of {@link AnalyticsRequest}s.
- */
-public class AnalyticsStats {
-  protected DocSet docs;
-  protected SolrParams params;
-  protected SolrIndexSearcher searcher;
-  protected SolrQueryRequest req;
-  protected AnalyticsStatisticsCollector statsCollector;
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-  
-  public AnalyticsStats(SolrQueryRequest req, DocSet docs, SolrParams params, AnalyticsStatisticsCollector statsCollector) {
-    this.req = req;
-    this.searcher = req.getSearcher();
-    this.docs = docs;
-    this.params = params; 
-    this.statsCollector = statsCollector;
-  }
-
-  /**
-   * Calculates the analytics requested in the Parameters.
-   * 
-   * @return List of results formated to mirror the input XML.
-   * @throws IOException if execution fails
-   */
-  public NamedList<?> execute() throws IOException {
-    statsCollector.startRequest();
-    NamedList<Object> res = new NamedList<>();
-    List<AnalyticsRequest> requests;
-    
-    requests = AnalyticsRequestFactory.parse(searcher.getSchema(), params);
-
-    if(requests == null || requests.size()==0){
-      return res;
-    }
-    statsCollector.addRequests(requests.size());
-    
-    // Get filter to all docs
-    Filter filter = docs.getTopFilter();
-    
-    // Computing each Analytics Request Separately
-    for( AnalyticsRequest areq : requests ){
-      // The Accumulator which will control the statistics generation
-      // for the entire analytics request
-      ValueAccumulator accumulator; 
-      
-      // The number of total facet requests
-      int facets = areq.getFieldFacets().size()+areq.getRangeFacets().size()+areq.getQueryFacets().size();
-      try {
-        if( facets== 0 ){
-          accumulator = BasicAccumulator.create(searcher, docs, areq);
-        } else {
-          accumulator = FacetingAccumulator.create(searcher, docs, areq, req);
-        }
-      } catch (IOException e) {
-        log.warn("Analytics request '"+areq.getName()+"' failed", e);
-        continue;
-      }
-
-      statsCollector.addStatsCollected(((BasicAccumulator)accumulator).getNumStatsCollectors());
-      statsCollector.addStatsRequests(areq.getExpressions().size());
-      statsCollector.addFieldFacets(areq.getFieldFacets().size());
-      statsCollector.addRangeFacets(areq.getRangeFacets().size());
-      statsCollector.addQueryFacets(areq.getQueryFacets().size());
-      statsCollector.addQueries(((BasicAccumulator)accumulator).getNumQueries());
-      
-      // Loop through the documents returned by the query and add to accumulator
-      List<LeafReaderContext> contexts = searcher.getTopReaderContext().leaves();
-      for (int leafNum = 0; leafNum < contexts.size(); leafNum++) {
-        LeafReaderContext context = contexts.get(leafNum);
-        DocIdSet dis = filter.getDocIdSet(context, null); // solr docsets already exclude any deleted docs
-        DocIdSetIterator disi = null;
-        if (dis != null) {
-          disi = dis.iterator();
-        }
-
-        if (disi != null) {
-          accumulator.getLeafCollector(context);
-          int doc = disi.nextDoc();
-          while( doc != DocIdSetIterator.NO_MORE_DOCS){
-            // Add a document to the statistics being generated
-            accumulator.collect(doc);
-            doc = disi.nextDoc();
-          }
-        }
-      }
-      
-      // do some post-processing
-      accumulator.postProcess();
-     
-      // compute the stats
-      accumulator.compute();
-      
-      res.add(areq.getName(),accumulator.export());
-    }
-
-    statsCollector.endRequest();
-    return res;
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/ExpressionRequest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/ExpressionRequest.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/ExpressionRequest.java
deleted file mode 100644
index a833c80..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/ExpressionRequest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.request;
-
-import org.apache.solr.analytics.expression.Expression;
-
-/**
- * Contains name and string representation of an expression.
- */
-public class ExpressionRequest implements Comparable<ExpressionRequest> {
-  private String name;
-  private String expressionString;
-  private Expression expression;
-  
-  /**
-   * @param name The name of the Expression.
-   * @param expressionString The string representation of the desired Expression.
-   */
-  public ExpressionRequest(String name, String expressionString) {
-    this.name = name;
-    this.expressionString = expressionString;
-  }
-
-  public void setExpressionString(String expressionString) {
-    this.expressionString = expressionString;
-  }
-  
-  public String getExpressionString() {
-    return expressionString;
-  }
-  
-  public void setExpression(Expression expression) {
-    this.expression = expression;
-  }
-  
-  public Expression getExpression() {
-    return expression;
-  }
-  
-  public void setName(String name) {
-    this.name = name;
-  }
-  
-  public String getName() {
-    return name;
-  }
-
-  @Override
-  public int compareTo(ExpressionRequest o) {
-    return name.compareTo(o.getName());
-  }
-  
-  @Override
-  public String toString() {
-    return "<ExpressionRequest name=" + name + " expression=" + expressionString + "/>";
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/FacetRequest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/FacetRequest.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/FacetRequest.java
deleted file mode 100644
index 936af72..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/FacetRequest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.request;
-
-public interface FacetRequest {
-  
-  /**
-   * Get the name of this facet (commonly the field name)
-   * @return the name
-   */
-  String getName();  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/FieldFacetRequest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/FieldFacetRequest.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/FieldFacetRequest.java
deleted file mode 100644
index 67d93da..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/FieldFacetRequest.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.request;
-
-import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.schema.SchemaField;
-
-import java.util.Locale;
-
-
-/**
- * Contains all of the specifications for a field facet.
- */
-public class FieldFacetRequest extends AbstractFieldFacetRequest {
-
-  private FacetSortSpecification sort = null;
-  private FacetSortDirection dir = null;
-  private int limit;
-  private int offset;
-  private boolean missing;
-  private boolean hidden;
-  
-  
-  public static enum FacetSortDirection {
-    ASCENDING ,
-    DESCENDING;
-   
-    public static FacetSortDirection fromExternal(String value){
-      final String sort = value.toLowerCase(Locale.ROOT);
-      if( "asc".equals(sort) )            return ASCENDING;
-      if( "ascending".equals(sort) )      return ASCENDING;
-      if( "desc".equals(sort) )           return DESCENDING;
-      if( "descending".equals(sort) )     return DESCENDING;
-      return Enum.valueOf(FacetSortDirection.class, value);
-    }
-  }
-  
-  /**
-   * Specifies how to sort the buckets of a field facet.
-   * 
-   */
-  public static class FacetSortSpecification {
-    private String statistic;
-    private FacetSortDirection direction = FacetSortDirection.DESCENDING;
-    
-    public FacetSortSpecification(){}
-    
-    /**
-     * @param statistic The name of a statistic specified in the {@link AnalyticsRequest}
-     * which is wrapping the {@link FieldFacetRequest} being sorted.
-     */
-    public FacetSortSpecification(String statistic) {
-      this.statistic = statistic;
-    }
-    
-    public FacetSortSpecification(String statistic, FacetSortDirection direction) {
-      this(statistic);
-      this.direction = direction;
-    }
-    
-    public String getStatistic() {
-      return statistic;
-    }
-    public void setStatistic(String statistic) {
-      this.statistic = statistic;
-    }
-    public FacetSortDirection getDirection() {
-      return direction;
-    }
-    public void setDirection(FacetSortDirection direction) {
-      this.direction = direction;
-    }
-
-    public static FacetSortSpecification fromExternal(String spec){
-      String[] parts = spec.split(" ",2);
-      if( parts.length == 1 ){
-        return new FacetSortSpecification(parts[0]);
-      } else {
-        return new FacetSortSpecification(parts[0], FacetSortDirection.fromExternal(parts[1]));
-      }
-    }
-
-    @Override
-    public String toString() {
-      return "<SortSpec stat=" + statistic + " dir=" + direction + ">";
-    }
-  }
-
-  public FieldFacetRequest(SchemaField field) {
-    super(field);
-    this.limit = AnalyticsParams.DEFAULT_LIMIT;
-    this.hidden = AnalyticsParams.DEFAULT_HIDDEN;
-  }
-
-  public FacetSortDirection getDirection() {
-    return dir;
-  }
-
-  public void setDirection(String dir) {
-    this.dir = FacetSortDirection.fromExternal(dir);
-    if (sort!=null) {
-      sort.setDirection(this.dir);
-    }
-  }
-
-  public FacetSortSpecification getSort() {
-    return sort;
-  }
-
-  public void setSort(FacetSortSpecification sort) {
-    this.sort = sort;
-  }
-
-  public boolean showsMissing() {
-    return missing;
-  }
-
-  /**
-   * If there are missing values in the facet field, include the bucket 
-   * for the missing facet values in the facet response.
-   * @param missing true/false if we calculate missing
-   */
-  public void showMissing(boolean missing) {
-    this.missing = missing;
-  }
-
-  public int getLimit() {
-    return limit;
-  }
-
-  public void setLimit(int limit) {
-    this.limit = limit;
-  }
-  
-  public int getOffset() {
-    return offset;
-  }
-
-  public void setOffset(int offset) {
-    this.offset = offset;
-  }
-
-  public boolean isHidden() {
-    return hidden;
-  }
-
-  public void setHidden(boolean hidden) {
-    this.hidden = hidden;
-  }
-
-  @Override
-  public String toString() {
-    return "<FieldFacetRequest field="+field.getName()+(sort==null?"":" sort=" + sort) + " limit=" + limit+" offset="+offset+">";
-  }
-
-
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/QueryFacetRequest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/QueryFacetRequest.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/QueryFacetRequest.java
deleted file mode 100644
index fbe34db..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/QueryFacetRequest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.request;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Contains all of the specifications for a query facet.
- */
-public class QueryFacetRequest implements FacetRequest {
-  private String name;
-  private List<String> queries;
-  private Set<String> dependencies;
-  
-  public QueryFacetRequest() {
-    dependencies = new HashSet<>();
-  }
-
-  public QueryFacetRequest(String name) {
-    this.name = name;
-    this.queries = new ArrayList<>();
-    dependencies = new HashSet<>();
-  }
- 
-  public List<String> getQueries() {
-    return queries;
-  }
-
-  public void setQueries(List<String> queries) {
-    this.queries = queries;
-  }
-
-  public void addQuery(String query) {
-    queries.add(query);
-  }
-
-  public Set<String> getDependencies() {
-    return dependencies;
-  }
-
-  public void setDependencies(Set<String> dependencies) {
-    this.dependencies = dependencies;
-  }
-
-  public void addDependency(String dependency) {
-    dependencies.add(dependency);
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String name) {
-    this.name = name;
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/RangeFacetRequest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/RangeFacetRequest.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/RangeFacetRequest.java
deleted file mode 100644
index ec9cf6b..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/RangeFacetRequest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.request;
-
-import java.util.Arrays;
-import java.util.EnumSet;
-
-import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.common.params.FacetParams.FacetRangeInclude;
-import org.apache.solr.common.params.FacetParams.FacetRangeOther;
-import org.apache.solr.schema.SchemaField;
-
-/**
- * Contains all of the specifications for a range facet.
- */
-public class RangeFacetRequest extends AbstractFieldFacetRequest {
-  protected String start;
-  protected String end;
-  protected String[] gaps;
-  protected boolean hardEnd = false;
-  protected EnumSet<FacetRangeInclude> include;
-  protected boolean includeCalled = false;
-  protected EnumSet<FacetRangeOther> others;
-  protected boolean othersCalled = false;
-  
-  public RangeFacetRequest(SchemaField field) {
-    super(field);
-    include = EnumSet.of(AnalyticsParams.DEFAULT_INCLUDE);
-    others = EnumSet.of(AnalyticsParams.DEFAULT_OTHER);
-  }
-  
-  public RangeFacetRequest(SchemaField field, String start, String end, String[] gaps) {
-    super(field);
-    this.start = start;
-    this.end = end;
-    this.gaps = gaps;
-  }
-
-  public String getStart() {
-    return start;
-  }
-
-  public void setStart(String start) {
-    this.start = start;
-  }
-
-  public String getEnd() {
-    return end;
-  }
-
-  public void setEnd(String end) {
-    this.end = end;
-  }
-
-  public EnumSet<FacetRangeInclude> getInclude() {
-    return include;
-  }
-
-  public void setInclude(EnumSet<FacetRangeInclude> include) {
-    includeCalled = true;
-    this.include = include;
-  }
-
-  public void addInclude(FacetRangeInclude include) {
-    if (includeCalled) {
-      this.include.add(include);
-    } else {
-      includeCalled = true;
-      this.include = EnumSet.of(include);
-    }
-  }
-
-  public String[] getGaps() {
-    return gaps;
-  }
-
-  public void setGaps(String[] gaps) {
-    this.gaps = gaps;
-  }
-
-  public boolean isHardEnd() {
-    return hardEnd;
-  }
-
-  public void setHardEnd(boolean hardEnd) {
-    this.hardEnd = hardEnd;
-  }
-
-  public EnumSet<FacetRangeOther> getOthers() {
-    return others;
-  }
-
-  public void setOthers(EnumSet<FacetRangeOther> others) {
-    othersCalled = true;
-    this.others = others;
-  }
-
-  public void addOther(FacetRangeOther other) {
-    if (othersCalled) {
-      this.others.add(other);
-    } else {
-      othersCalled = true;
-      this.others = EnumSet.of(other);
-    }
-  }
-
-  @Override
-  public String toString() {
-    return "<RangeFacetRequest field="+field.getName() + " start=" + start + ", end=" + end + ", gap=" + Arrays.toString(gaps) + ", hardEnd=" + hardEnd + 
-                               ", include=" + include + ", others=" + others +">";
-  }
-
-  
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/package-info.java
deleted file mode 100644
index de2feb3..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-/** 
- * Request objects for creating Analytics requests
- */
-package org.apache.solr.analytics.request;
-
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/AbstractDelegatingStatsCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/AbstractDelegatingStatsCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/AbstractDelegatingStatsCollector.java
deleted file mode 100644
index 92969f1..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/AbstractDelegatingStatsCollector.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.statistics;
-
-import java.io.IOException;
-import java.util.Set;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.util.mutable.MutableValue;
-
-/**
- * <code>AbstractDelegationStatsCollector</code> objects wrap other StatsCollectors.
- * While they compute their own statistics they pass along all inputs and requests
- * to the delegates as well.
- */
-public abstract class AbstractDelegatingStatsCollector implements StatsCollector{
-  protected final StatsCollector delegate;
-  protected final Set<String> statsList;
-  MutableValue value;
-  FunctionValues function;
-  
-  /**
-   * @param delegate The delegate computing statistics on the same set of values.
-   */
-  public AbstractDelegatingStatsCollector(StatsCollector delegate) {
-    this.delegate = delegate;
-    this.statsList = delegate.getStatsList();
-  }
-  
-  public void setNextReader(LeafReaderContext context) throws IOException {
-    delegate.setNextReader(context);
-    value = getValue();
-    function = getFunction();
-  }
-  
-  public StatsCollector delegate(){
-    return delegate;
-  }
-  
-  public Set<String> getStatsList(){
-    return statsList;
-  }
-  
-  public MutableValue getValue() {
-    return delegate.getValue();
-  }
-  
-  public FunctionValues getFunction() {
-    return delegate.getFunction();
-  }
-  
-  public void collect(int doc) throws IOException {
-    delegate.collect(doc);
-  }
-  
-  public String valueSourceString() {
-    return delegate.valueSourceString();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/MedianStatsCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/MedianStatsCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/MedianStatsCollector.java
deleted file mode 100644
index bf71429..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/MedianStatsCollector.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.statistics;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import org.apache.solr.analytics.util.MedianCalculator;
-
-/**
- * <code>MedianStatsCollector</code> computes the median.
- */
-public class MedianStatsCollector extends AbstractDelegatingStatsCollector{
-
-  private final List<Double> values = new ArrayList<>();
-  protected double median;
-  
-  public MedianStatsCollector(StatsCollector delegate) {
-    super(delegate);
-  }
-
-  public Double getMedian() {
-    return new Double(MedianCalculator.getMedian(values));
-  }
-
-  @Override
-  public Comparable getStat(String stat) {
-    if (stat.equals("median")) {
-      return new Double(median);
-    }
-    return delegate.getStat(stat);
-  }
-  
-  public void compute(){
-    delegate.compute();
-    median = getMedian();
-  }
-  
-  @Override
-  public void collect(int doc) throws IOException {
-    super.collect(doc);
-    if (value.exists) {
-      values.add(function.doubleVal(doc));
-    }
-  }
-}
-class DateMedianStatsCollector extends MedianStatsCollector{
-  
-  public DateMedianStatsCollector(StatsCollector delegate) {
-    super(delegate);
-  }
-
-  @Override
-  public Comparable getStat(String stat) {
-    if (stat.equals("median")) {
-      return new Date((long)median);
-    }
-    return delegate.getStat(stat);
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/MinMaxStatsCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/MinMaxStatsCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/MinMaxStatsCollector.java
deleted file mode 100644
index c21b045..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/MinMaxStatsCollector.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.statistics;
-
-import java.io.IOException;
-import java.util.Locale;
-import java.util.Set;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.FunctionValues.ValueFiller;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.util.mutable.MutableValue;
-
-/**
- * <code>MinMaxStatsCollector</code> computes the min, max, number of values and number of missing values.
- */
-public class MinMaxStatsCollector implements StatsCollector{
-  protected long missingCount = 0;
-  protected long valueCount = 0;
-  protected MutableValue max;
-  protected MutableValue min;
-  protected MutableValue value;
-  protected final Set<String> statsList;
-  protected final ValueSource source;
-  protected FunctionValues function;
-  protected ValueFiller valueFiller;
-  
-  public MinMaxStatsCollector(ValueSource source, Set<String> statsList) {
-    this.source = source;
-    this.statsList = statsList;
-  }
-  
-  public void setNextReader(LeafReaderContext context) throws IOException {
-    function = source.getValues(null, context);
-    valueFiller = function.getValueFiller();
-    value = valueFiller.getValue();
-  }
-  
-  public void collect(int doc) throws IOException {
-    valueFiller.fillValue(doc);
-    if( value.exists ){
-      valueCount += 1;
-      if ( max==null ) max = value.duplicate();
-      else if( !max.exists || value.compareTo(max) > 0 ) max.copy(value);
-      if ( min==null ) min = value.duplicate();
-      else if( !min.exists || value.compareTo(min) < 0 ) min.copy(value);
-    } else {
-      missingCount += 1;
-    }
-  }
- 
-  @Override
-  public String toString() {
-    return String.format(Locale.ROOT, "<min=%s max=%s c=%d m=%d>", min, max, valueCount, missingCount );
-  }
-  
-  public Comparable getStat(String stat){
-    if (stat.equals("min")&&min!=null) {
-      return (Comparable)min.toObject();
-    }
-    if (stat.equals("max")&&max!=null) {
-      return (Comparable)max.toObject();
-    }
-    if (stat.equals("count")) {
-      return new Long(valueCount);
-    }
-    if (stat.equals("missing")) {
-      return new Long(missingCount);
-    }
-
-    return null;
-//    throw new IllegalArgumentException("No stat named '"+stat+"' in this collector " + this);
-  }
-  
-  public Set<String> getStatsList() {
-    return statsList;
-  }
-
-  @Override
-  public void compute() {  }
-  
-  @Override 
-  public MutableValue getValue() {
-    return value;
-  }
-  
-  @Override 
-  public FunctionValues getFunction() {
-    return function;
-  }
-  
-  public String valueSourceString() {
-    return source.toString();
-  }
-  
-  public String statString(String stat) {
-    return stat+"("+valueSourceString()+")";
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/NumericStatsCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/NumericStatsCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/NumericStatsCollector.java
deleted file mode 100644
index 1f22baa..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/NumericStatsCollector.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.statistics;
-
-import java.io.IOException;
-import java.util.Set;
-
-import org.apache.lucene.queries.function.ValueSource;
-
-/**
- * <code>NumericStatsCollector</code> computes the sum, sum of squares, mean and standard deviation.
- */
-public class NumericStatsCollector extends MinMaxStatsCollector {
-  protected double sum = 0;
-  protected double sumOfSquares = 0;
-  protected double mean = 0;
-  protected double stddev = 0;
-  
-  public NumericStatsCollector(ValueSource source, Set<String> statsList) {
-    super(source, statsList);
-  }
-  
-  public void collect(int doc) throws IOException {
-    super.collect(doc);
-    double value = function.doubleVal(doc);
-    sum += value;
-    sumOfSquares += (value * value);
-  }
-  
-  @Override
-  public Comparable getStat(String stat) {
-    if (stat.equals("sum")) {
-      return new Double(sum);
-    }
-    if (stat.equals("sumofsquares")) {
-      return new Double(sumOfSquares);
-    }
-    if (stat.equals("mean")) {
-      return new Double(mean);
-    }
-    if (stat.equals("stddev")) {
-      return new Double(stddev);
-    }
-    return super.getStat(stat);
-  }  
-  
-  @Override
-  public void compute(){
-    super.compute();
-    mean = (valueCount==0)? 0:sum / valueCount;
-    stddev = (valueCount <= 1) ? 0.0D : Math.sqrt((sumOfSquares/valueCount) - (mean*mean));
-  }
-  
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/PercentileStatsCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/PercentileStatsCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/PercentileStatsCollector.java
deleted file mode 100644
index e12cb83..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/PercentileStatsCollector.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.statistics;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Pattern;
-
-import org.apache.solr.analytics.util.PercentileCalculator;
-
-import com.google.common.collect.Iterables;
-
-/**
- * <code>PercentileStatsCollector</code> computes a given list of percentiles.
- */
-@SuppressWarnings("rawtypes")
-public class PercentileStatsCollector extends AbstractDelegatingStatsCollector{
-  public final List<Comparable> values = new ArrayList<>();
-  public static final Pattern PERCENTILE_PATTERN = Pattern.compile("perc(?:entile)?_(\\d+)",Pattern.CASE_INSENSITIVE);
-  protected final double[] percentiles;
-  protected final String[] percentileNames;
-  protected Comparable[] results;
-  
-  public PercentileStatsCollector(StatsCollector delegate, double[] percentiles, String[] percentileNames) {
-    super(delegate);
-    this.percentiles = percentiles;
-    this.percentileNames = percentileNames;
-  }
-
-  @Override
-  public Comparable getStat(String stat) {
-    for( int i=0; i < percentiles.length; i++ ){
-      if (stat.equals(percentileNames[i])) {
-        if (results!=null) {
-          return results[i];
-        } else {
-          return null;
-        }
-      }
-    }
-    return delegate.getStat(stat);
-  }
-
-  public void compute(){
-    delegate.compute();
-    if (values.size()>0) {
-      results = Iterables.toArray(getPercentiles(),Comparable.class);
-    } else {
-      results = null;
-    }
-  }
-
-  @SuppressWarnings({ "unchecked"})
-  protected List<Comparable> getPercentiles() {
-    return PercentileCalculator.getPercentiles(values, percentiles);
-  }
-  
-  public void collect(int doc) throws IOException {
-    super.collect(doc);
-    if (value.exists) {
-      values.add((Comparable)value.toObject());
-    }
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollector.java
deleted file mode 100644
index 039300f..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollector.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.statistics;
-
-import java.io.IOException;
-import java.util.Set;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.util.mutable.MutableValue;
-
-/**
- * <code>StatsCollector</code> implementations reduce a list of Objects to a single value.
- * Most implementations reduce a list to a statistic on that list.
- */
-public interface StatsCollector {
-  
-  /**
-   * Collect values from the value source and add to statistics.
-   * @param doc Document to collect from
-   */
-  void collect(int doc) throws IOException;
-  
-  /**
-   * @param context The context to read documents from.
-   * @throws IOException if setting next reader fails
-   */
-  void setNextReader(LeafReaderContext context) throws IOException;
-  
-  MutableValue getValue();
-  FunctionValues getFunction();
-  
-  /**
-   * @return The set of statistics being computed by the stats collector.
-   */
-  Set<String> getStatsList();
-  
-  /**
-   * Return the value of the given statistic.
-   * @param stat the stat
-   * @return a comparable
-   */
-  Comparable getStat(String stat);
-  
-  /**
-   * After all documents have been collected, this method should be
-   * called to finalize the calculations of each statistic.
-   */
-  void compute();
-  
-  /**
-   * @return The string representation of the value source.
-   */
-  String valueSourceString();
-}


[14/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LambdaFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LambdaFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LambdaFunction.java
new file mode 100644
index 0000000..ff8a1a6
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/LambdaFunction.java
@@ -0,0 +1,3220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.function.mapping.LambdaFunction.BoolInBoolOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.DoubleInDoubleOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.FloatInFloatOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.IntInIntOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.LongInLongOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.StringInStringOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.TwoBoolInBoolOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.TwoDoubleInDoubleOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.TwoFloatInFloatOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.TwoIntInIntOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.TwoLongInLongOutLambda;
+import org.apache.solr.analytics.function.mapping.LambdaFunction.TwoStringInStringOutLambda;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.BooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.BooleanValue.AbstractBooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream.AbstractBooleanValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DateValueStream.AbstractDateValueStream;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream.AbstractDoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.FloatValueStream.AbstractFloatValueStream;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.IntValueStream.AbstractIntValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.LongValueStream.AbstractLongValueStream;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.value.StringValueStream.AbstractStringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * Lambda Functions are used to easily create basic mapping functions.
+ * <p>
+ * There are lambda functions for all types: boolean, int, long, float, double, date and string.
+ * Lambda functions must have parameters of all the same type, which will be the same type as the returned Value or ValueStream.
+ * <p>
+ * The types of functions that are accepted are: (multi = multi-valued expression, single = single-valued expression)
+ * <ul>
+ * <li> {@code func(single) -> single}
+ * <li> {@code func(multi) -> multi}
+ * <li> {@code func(single,single) -> single}
+ * <li> {@code func(multi,single) -> multi}
+ * <li> {@code func(single,multi) -> multi}
+ * <li> {@code func(multi) -> single}
+ * <li> {@code func(single,single,...) -> single}
+ * (You can also specify whether all parameters must exist, or at least one must exist for the returned value to exist)
+ * </ul>
+ * <p>
+ * NOTE: The combination of name and parameters MUST be unique for an expression.
+ * <br>
+ * For example consider if {@code join(fieldA, ',')} and {@code join(fieldA, ';')} are both called. If the JoinFunction uses:
+ * <br>
+ * {@code LambdaFunction.createStringLambdaFunction("join", (a,b) -> a + sep + b, (StringValueStream)params[0])}
+ * <br>
+ * then both the name "join" and single parameter fieldA will be used for two DIFFERENT expressions.
+ * This does not meet the uniqueness requirmenet and will break the query.
+ * <br>
+ * A solution to this is to name the function using the missing information:
+ * <br>
+ * {@code LambdaFunction.createStringLambdaFunction("join(" + sep + ")", (a,b) -> a + sep + b, (StringValueStream)params[0])}
+ * <br>
+ * Therefore both expressions will have fieldA as the only parameter, but the names {@code "join(,)"} and {@code "join(;)"} will be different.
+ * This meets the uniqueness requirement for lambda functions.
+ */
+public class LambdaFunction {
+  private static final boolean defaultMultiExistsMethod = true;
+  
+  /* *********************
+   * 
+   *  Boolean Functions
+   * 
+   * *********************/
+  
+  /**
+   * Creates a function that takes in either a single or multi valued boolean expression and returns the same type of expression with
+   * the given lambda function applied to every value.
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (boolean) -> boolean}
+   * @param param the expression to apply the lambda to
+   * @return an expression the same type as was given with the lambda applied
+   */
+  public static BooleanValueStream createBooleanLambdaFunction(String name, BoolInBoolOutLambda lambda, BooleanValueStream param) {
+    if (param instanceof BooleanValue) {
+      return new BooleanValueInBooleanValueOutFunction(name,lambda,(BooleanValue)param);
+    } else {
+      return new BooleanStreamInBooleanStreamOutFunction(name,lambda,param);
+    }
+  }
+  /**
+   * Creates a function that takes in a multi-valued boolean expression and returns a single-valued boolean expression.
+   * The given lambda is used to associatively (order not guaranteed) reduce all values for a document down to a single value. 
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (boolean, boolean) -> boolean}
+   * @param param the expression to be reduced per-document
+   * @return a single-valued expression which has been reduced for every document
+   */
+  public static BooleanValue createBooleanLambdaFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValueStream param) {
+    return new BooleanStreamInBooleanValueOutFunction(name,lambda,param);
+  }
+  /**
+   * Creates a function that maps two booleans to a single boolean.
+   * This can take the following shapes:
+   * <ul>
+   * <li> Taking in two single-valued expressions and returning a single-valued expression which represents the lambda combination of the inputs.
+   * <li> Taking in a single-valued expression and a multi-valued expression and returning a multi-valued expression which
+   * represents the lambda combination of the single-value input with each of the values of the multi-value input.
+   * <br>
+   * The inputs can be either {@code func(single,multi)} or {@code func(multi,single)}.
+   * </ul>
+   * <p>
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (boolean,boolean) -> boolean}
+   * @param param1 the first parameter in the lambda
+   * @param param2 the second parameter in the lambda
+   * @return a single or multi valued expression combining the two parameters with the given lambda
+   * @throws SolrException if neither parameter is single-valued
+   */
+  public static BooleanValueStream createBooleanLambdaFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValueStream param1, BooleanValueStream param2) throws SolrException {
+    if (param1 instanceof BooleanValue && param2 instanceof BooleanValue) {
+      return new TwoBooleanValueInBooleanValueOutFunction(name,lambda,(BooleanValue)param1,(BooleanValue)param2);
+    } else if (param1 instanceof BooleanValue) {
+      return new BooleanValueBooleanStreamInBooleanStreamOutFunction(name,lambda,(BooleanValue)param1,param2);
+    } else if (param2 instanceof BooleanValue) {
+      return new BooleanStreamBooleanValueInBooleanStreamOutFunction(name,lambda,param1,(BooleanValue)param2);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 1 single-valued parameter.");
+    }
+  }
+  /**
+   * Forwards the creation of the function to {@link #createBooleanLambdaFunction(String, TwoBoolInBoolOutLambda, BooleanValue[], boolean)},
+   * using {@value #defaultMultiExistsMethod} for the last argument ({@code allMustExist}).
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (boolean, boolean) -> boolean}
+   * @param params the expressions to reduce
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static BooleanValue createBooleanLambdaFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValue[] params) {
+    return createBooleanLambdaFunction(name,lambda,params,defaultMultiExistsMethod);
+  }
+  /**
+   * Creates a function that associatively (order is guaranteed) reduces multiple
+   * single-value boolean expressions into a single-value boolean expression for each document.
+   * <br>
+   * For a document, every parameter's value must exist for the resulting value to exist if {@code allMustExist} is true.
+   * If {@code allMustExist} is false, only one of the parameters' values must exist.
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (boolean, boolean) -> boolean}
+   * @param params the expressions to reduce
+   * @param allMustExist whether all parameters are required to exist
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static BooleanValue createBooleanLambdaFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValue[] params, boolean allMustExist) {
+    if (allMustExist) {
+      return new MultiBooleanValueInBooleanValueOutRequireAllFunction(name,lambda,params);
+    } else {
+      return new MultiBooleanValueInBooleanValueOutRequireOneFunction(name,lambda,params);
+    }
+  }
+  
+  /* *********************
+   * 
+   *  Integer Functions
+   * 
+   * *********************/
+  
+  /**
+   * Creates a function that takes in either a single or multi valued integer expression and returns the same type of expression with
+   * the given lambda function applied to every value.
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (integer) -> integer}
+   * @param param the expression to apply the lambda to
+   * @return an expression the same type as was given with the lambda applied
+   */
+  public static IntValueStream createIntLambdaFunction(String name, IntInIntOutLambda lambda, IntValueStream param) {
+    if (param instanceof IntValue) {
+      return new IntValueInIntValueOutFunction(name,lambda,(IntValue)param);
+    } else {
+      return new IntStreamInIntStreamOutFunction(name,lambda,param);
+    }
+  }
+  /**
+   * Creates a function that takes in a multi-valued integer expression and returns a single-valued integer expression.
+   * The given lambda is used to associatively (order not guaranteed) reduce all values for a document down to a single value. 
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (integer, integer) -> integer}
+   * @param param the expression to be reduced per-document
+   * @return a single-valued expression which has been reduced for every document
+   */
+  public static IntValue createIntLambdaFunction(String name, TwoIntInIntOutLambda lambda, IntValueStream param) {
+    return new IntStreamInIntValueOutFunction(name,lambda,param);
+  }
+  /**
+   * Creates a function that maps two integers to a single integer.
+   * This can take the following shapes:
+   * <ul>
+   * <li> Taking in two single-valued expressions and returning a single-valued expression which represents the lambda combination of the inputs.
+   * <li> Taking in a single-valued expression and a multi-valued expression and returning a multi-valued expression which
+   * represents the lambda combination of the single-value input with each of the values of the multi-value input.
+   * <br>
+   * The inputs can be either {@code func(single,multi)} or {@code func(multi,single)}.
+   * </ul>
+   * <p>
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (integer,integer) -> integer}
+   * @param param1 the first parameter in the lambda
+   * @param param2 the second parameter in the lambda
+   * @return a single or multi valued expression combining the two parameters with the given lambda
+   * @throws SolrException if neither parameter is single-valued
+   */
+  public static IntValueStream createIntLambdaFunction(String name, TwoIntInIntOutLambda lambda, IntValueStream param1, IntValueStream param2) throws SolrException {
+    if (param1 instanceof IntValue && param2 instanceof IntValue) {
+      return new TwoIntValueInIntValueOutFunction(name,lambda,(IntValue)param1,(IntValue)param2);
+    } else if (param1 instanceof IntValue) {
+      return new IntValueIntStreamInIntStreamOutFunction(name,lambda,(IntValue)param1,param2);
+    } else if (param2 instanceof IntValue) {
+      return new IntStreamIntValueInIntStreamOutFunction(name,lambda,param1,(IntValue)param2);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 1 single-valued parameter.");
+    }
+  }
+  /**
+   * Forwards the creation of the function to {@link #createIntLambdaFunction(String, TwoIntInIntOutLambda, IntValue[], boolean)},
+   * using {@value #defaultMultiExistsMethod} for the last argument ({@code allMustExist}).
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (boolean, boolean) -> boolean}
+   * @param params the expressions to reduce
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static IntValue createIntLambdaFunction(String name, TwoIntInIntOutLambda lambda, IntValue[] params) {
+    return createIntLambdaFunction(name,lambda,params,defaultMultiExistsMethod);
+  }
+  /**
+   * Creates a function that associatively (order is guaranteed) reduces multiple
+   * single-value integer expressions into a single-value integer expression for each document.
+   * <br>
+   * For a document, every parameter's value must exist for the resulting value to exist if {@code allMustExist} is true.
+   * If {@code allMustExist} is false, only one of the parameters' values must exist.
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (integer, integer) -> integer}
+   * @param params the expressions to reduce
+   * @param allMustExist whether all parameters are required to exist
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static IntValue createIntLambdaFunction(String name, TwoIntInIntOutLambda lambda, IntValue[] params, boolean allMustExist) {
+    if (allMustExist) {
+      return new MultiIntValueInIntValueOutRequireAllFunction(name,lambda,params);
+    } else {
+      return new MultiIntValueInIntValueOutRequireOneFunction(name,lambda,params);
+    }
+  }
+  
+  /* *********************
+   * 
+   *  Long Functions
+   * 
+   * *********************/
+  
+  /**
+   * Creates a function that takes in either a single or multi valued long expression and returns the same type of expression with
+   * the given lambda function applied to every value.
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (long) -> long}
+   * @param param the expression to apply the lambda to
+   * @return an expression the same type as was given with the lambda applied
+   */
+  public static LongValueStream createLongLambdaFunction(String name, LongInLongOutLambda lambda, LongValueStream param) {
+    if (param instanceof LongValue) {
+      return new LongValueInLongValueOutFunction(name,lambda,(LongValue)param);
+    } else {
+      return new LongStreamInLongStreamOutFunction(name,lambda,param);
+    }
+  }
+  /**
+   * Creates a function that takes in a multi-valued long expression and returns a single-valued long expression.
+   * The given lambda is used to associatively (order not guaranteed) reduce all values for a document down to a single value. 
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (boolean, boolean) -> boolean}
+   * @param param the expression to be reduced per-document
+   * @return a single-valued expression which has been reduced for every document
+   */
+  public static LongValue createLongLambdaFunction(String name, TwoLongInLongOutLambda lambda, LongValueStream param) {
+    return new LongStreamInLongValueOutFunction(name,lambda,param);
+  }
+  /**
+   * Creates a function that maps two longs to a single long.
+   * This can take the following shapes:
+   * <ul>
+   * <li> Taking in two single-valued expressions and returning a single-valued expression which represents the lambda combination of the inputs.
+   * <li> Taking in a single-valued expression and a multi-valued expression and returning a multi-valued expression which
+   * represents the lambda combination of the single-value input with each of the values of the multi-value input.
+   * <br>
+   * The inputs can be either {@code func(single,multi)} or {@code func(multi,single)}.
+   * </ul>
+   * <p>
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (long,long) -> long}
+   * @param param1 the first parameter in the lambda
+   * @param param2 the second parameter in the lambda
+   * @return a single or multi valued expression combining the two parameters with the given lambda
+   * @throws SolrException if neither parameter is single-valued
+   */
+  public static LongValueStream createLongLambdaFunction(String name, TwoLongInLongOutLambda lambda, LongValueStream param1, LongValueStream param2) throws SolrException {
+    if (param1 instanceof LongValue && param2 instanceof LongValue) {
+      return new TwoLongValueInLongValueOutFunction(name,lambda,(LongValue)param1,(LongValue)param2);
+    } else if (param1 instanceof LongValue) {
+      return new LongValueLongStreamInLongStreamOutFunction(name,lambda,(LongValue)param1,param2);
+    } else if (param2 instanceof LongValue) {
+      return new LongStreamLongValueInLongStreamOutFunction(name,lambda,param1,(LongValue)param2);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 1 single-valued parameter.");
+    }
+  }
+  /**
+   * Forwards the creation of the function to {@link #createLongLambdaFunction(String, TwoLongInLongOutLambda, LongValue[], boolean)},
+   * using {@value #defaultMultiExistsMethod} for the last argument ({@code allMustExist}).
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (boolean, boolean) -> boolean}
+   * @param params the expressions to reduce
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static LongValue createLongLambdaFunction(String name, TwoLongInLongOutLambda lambda, LongValue[] params) {
+    return createLongLambdaFunction(name,lambda,params,defaultMultiExistsMethod);
+  }
+  /**
+   * Creates a function that associatively (order is guaranteed) reduces multiple
+   * single-value long expressions into a single-value long expression for each document.
+   * <br>
+   * For a document, every parameter's value must exist for the resulting value to exist if {@code allMustExist} is true.
+   * If {@code allMustExist} is false, only one of the parameters' values must exist.
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (long, long) -> long}
+   * @param params the expressions to reduce
+   * @param allMustExist whether all parameters are required to exist
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static LongValue createLongLambdaFunction(String name, TwoLongInLongOutLambda lambda, LongValue[] params, boolean allMustExist) {
+    if (allMustExist) {
+      return new MultiLongValueInLongValueOutRequireAllFunction(name,lambda,params);
+    } else {
+      return new MultiLongValueInLongValueOutRequireOneFunction(name,lambda,params);
+    }
+  }
+  
+  /* *********************
+   * 
+   *  Float Functions
+   * 
+   * *********************/
+  
+  /**
+   * Creates a function that takes in either a single or multi valued float expression and returns the same type of expression with
+   * the given lambda function applied to every value.
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (float) -> float}
+   * @param param the expression to apply the lambda to
+   * @return an expression the same type as was given with the lambda applied
+   */
+  public static FloatValueStream createFloatLambdaFunction(String name, FloatInFloatOutLambda lambda, FloatValueStream param) {
+    if (param instanceof FloatValue) {
+      return new FloatValueInFloatValueOutFunction(name,lambda,(FloatValue)param);
+    } else {
+      return new FloatStreamInFloatStreamOutFunction(name,lambda,param);
+    }
+  }
+  /**
+   * Creates a function that takes in a multi-valued float expression and returns a single-valued float expression.
+   * The given lambda is used to associatively (order not guaranteed) reduce all values for a document down to a single value. 
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (float, float) -> float}
+   * @param param the expression to be reduced per-document
+   * @return a single-valued expression which has been reduced for every document
+   */
+  public static FloatValue createFloatLambdaFunction(String name, TwoFloatInFloatOutLambda lambda, FloatValueStream param) {
+    return new FloatStreamInFloatValueOutFunction(name,lambda,param);
+  }
+  /**
+   * Creates a function that maps two floats to a single float.
+   * This can take the following shapes:
+   * <ul>
+   * <li> Taking in two single-valued expressions and returning a single-valued expression which represents the lambda combination of the inputs.
+   * <li> Taking in a single-valued expression and a multi-valued expression and returning a multi-valued expression which
+   * represents the lambda combination of the single-value input with each of the values of the multi-value input.
+   * <br>
+   * The inputs can be either {@code func(single,multi)} or {@code func(multi,single)}.
+   * </ul>
+   * <p>
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (float,float) -> float}
+   * @param param1 the first parameter in the lambda
+   * @param param2 the second parameter in the lambda
+   * @return a single or multi valued expression combining the two parameters with the given lambda
+   * @throws SolrException if neither parameter is single-valued
+   */
+  public static FloatValueStream createFloatLambdaFunction(String name, TwoFloatInFloatOutLambda lambda, FloatValueStream param1, FloatValueStream param2) throws SolrException {
+    if (param1 instanceof FloatValue && param2 instanceof FloatValue) {
+      return new TwoFloatValueInFloatValueOutFunction(name,lambda,(FloatValue)param1,(FloatValue)param2);
+    } else if (param1 instanceof FloatValue) {
+      return new FloatValueFloatStreamInFloatStreamOutFunction(name,lambda,(FloatValue)param1,param2);
+    } else if (param2 instanceof FloatValue) {
+      return new FloatStreamFloatValueInFloatStreamOutFunction(name,lambda,param1,(FloatValue)param2);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 1 single-valued parameter.");
+    }
+  }
+  /**
+   * Forwards the creation of the function to {@link #createFloatLambdaFunction(String, TwoFloatInFloatOutLambda, FloatValue[], boolean)},
+   * using {@value #defaultMultiExistsMethod} for the last argument ({@code allMustExist}).
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (boolean, boolean) -> boolean}
+   * @param params the expressions to reduce
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static FloatValue createFloatLambdaFunction(String name, TwoFloatInFloatOutLambda lambda, FloatValue[] params) {
+    return createFloatLambdaFunction(name,lambda,params,defaultMultiExistsMethod);
+  }
+  /**
+   * Creates a function that associatively (order is guaranteed) reduces multiple
+   * single-value float expressions into a single-value float expression for each document.
+   * <br>
+   * For a document, every parameter's value must exist for the resulting value to exist if {@code allMustExist} is true.
+   * If {@code allMustExist} is false, only one of the parameters' values must exist.
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (float, float) -> float}
+   * @param params the expressions to reduce
+   * @param allMustExist whether all parameters are required to exist
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static FloatValue createFloatLambdaFunction(String name, TwoFloatInFloatOutLambda lambda, FloatValue[] params, boolean allMustExist) {
+    if (allMustExist) {
+      return new MultiFloatValueInFloatValueOutRequireAllFunction(name,lambda,params);
+    } else {
+      return new MultiFloatValueInFloatValueOutRequireOneFunction(name,lambda,params);
+    }
+  }
+  
+  /* *********************
+   * 
+   *  Double Functions
+   * 
+   * *********************/
+  
+  /**
+   * Creates a function that takes in either a single or multi valued double expression and returns the same type of expression with
+   * the given lambda function applied to every value.
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (double) -> double}
+   * @param param the expression to apply the lambda to
+   * @return an expression the same type as was given with the lambda applied
+   */
+  public static DoubleValueStream createDoubleLambdaFunction(String name, DoubleInDoubleOutLambda lambda, DoubleValueStream param) {
+    if (param instanceof DoubleValue) {
+      return new DoubleValueInDoubleValueOutFunction(name,lambda,(DoubleValue)param);
+    } else {
+      return new DoubleStreamInDoubleStreamOutFunction(name,lambda,param);
+    }
+  }
+  /**
+   * Creates a function that takes in a multi-valued double expression and returns a single-valued double expression.
+   * The given lambda is used to associatively (order not guaranteed) reduce all values for a document down to a single value. 
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (double, double) -> double}
+   * @param param the expression to be reduced per-document
+   * @return a single-valued expression which has been reduced for every document
+   */
+  public static DoubleValue createDoubleLambdaFunction(String name, TwoDoubleInDoubleOutLambda lambda, DoubleValueStream param) {
+    return new DoubleStreamInDoubleValueOutFunction(name,lambda,param);
+  }
+  /**
+   * Creates a function that maps two doubles to a single double.
+   * This can take the following shapes:
+   * <ul>
+   * <li> Taking in two single-valued expressions and returning a single-valued expression which represents the lambda combination of the inputs.
+   * <li> Taking in a single-valued expression and a multi-valued expression and returning a multi-valued expression which
+   * represents the lambda combination of the single-value input with each of the values of the multi-value input.
+   * <br>
+   * The inputs can be either {@code func(single,multi)} or {@code func(multi,single)}.
+   * </ul>
+   * <p>
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (double,double) -> double}
+   * @param param1 the first parameter in the lambda
+   * @param param2 the second parameter in the lambda
+   * @return a single or multi valued expression combining the two parameters with the given lambda
+   * @throws SolrException if neither parameter is single-valued
+   */
+  public static DoubleValueStream createDoubleLambdaFunction(String name, TwoDoubleInDoubleOutLambda lambda, DoubleValueStream param1, DoubleValueStream param2) throws SolrException {
+    if (param1 instanceof DoubleValue && param2 instanceof DoubleValue) {
+      return new TwoDoubleValueInDoubleValueOutFunction(name,lambda,(DoubleValue)param1,(DoubleValue)param2);
+    } else if (param1 instanceof DoubleValue) {
+      return new DoubleValueDoubleStreamInDoubleStreamOutFunction(name,lambda,(DoubleValue)param1,param2);
+    } else if (param2 instanceof DoubleValue) {
+      return new DoubleStreamDoubleValueInDoubleStreamOutFunction(name,lambda,param1,(DoubleValue)param2);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 1 single-valued parameter.");
+    }
+  }
+  /**
+   * Forwards the creation of the function to {@link #createDoubleLambdaFunction(String, TwoDoubleInDoubleOutLambda, DoubleValue[], boolean)},
+   * using {@value #defaultMultiExistsMethod} for the last argument ({@code allMustExist}).
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (boolean, boolean) -> boolean}
+   * @param params the expressions to reduce
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static DoubleValue createDoubleLambdaFunction(String name, TwoDoubleInDoubleOutLambda lambda, DoubleValue[] params) {
+    return createDoubleLambdaFunction(name,lambda,params,defaultMultiExistsMethod);
+  }
+  /**
+   * Creates a function that associatively (order is guaranteed) reduces multiple
+   * single-value double expressions into a single-value double expression for each document.
+   * <br>
+   * For a document, every parameter's value must exist for the resulting value to exist if {@code allMustExist} is true.
+   * If {@code allMustExist} is false, only one of the parameters' values must exist.
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (double, double) -> double}
+   * @param params the expressions to reduce
+   * @param allMustExist whether all parameters are required to exist
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static DoubleValue createDoubleLambdaFunction(String name, TwoDoubleInDoubleOutLambda lambda, DoubleValue[] params, boolean allMustExist) {
+    if (allMustExist) {
+      return new MultiDoubleValueInDoubleValueOutRequireAllFunction(name,lambda,params);
+    } else {
+      return new MultiDoubleValueInDoubleValueOutRequireOneFunction(name,lambda,params);
+    }
+  }
+  
+  /* *********************
+   * 
+   *  Date Functions
+   * 
+   * *********************/
+  
+  /**
+   * Creates a function that takes in either a single or multi valued date expression and returns the same type of expression with
+   * the given lambda function applied to every value. 
+   * 
+   * <p>
+   * NOTE: The lambda must work on longs, not Date objects
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (long) -> long}
+   * @param param the expression to apply the lambda to
+   * @return an expression the same type as was given with the lambda applied
+   */
+  public static DateValueStream createDateLambdaFunction(String name, LongInLongOutLambda lambda, DateValueStream param) {
+    if (param instanceof DateValue) {
+      return new DateValueInDateValueOutFunction(name,lambda,(DateValue)param);
+    } else {
+      return new DateStreamInDateStreamOutFunction(name,lambda,param);
+    }
+  }
+  /**
+   * Creates a function that takes in a multi-valued date expression and returns a single-valued date expression.
+   * The given lambda is used to associatively (order not guaranteed) reduce all values for a document down to a single value. 
+   * 
+   * <p>
+   * NOTE: The lambda must work on longs, not Date objects
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (long, long) -> long}
+   * @param param the expression to be reduced per-document
+   * @return a single-valued expression which has been reduced for every document
+   */
+  public static DateValue createDateLambdaFunction(String name, TwoLongInLongOutLambda lambda, DateValueStream param) {
+    return new DateStreamInDateValueOutFunction(name,lambda,param);
+  }
+  /**
+   * Creates a function that maps two dates to a single date.
+   * This can take the following shapes:
+   * <ul>
+   * <li> Taking in two single-valued expressions and returning a single-valued expression which represents the lambda combination of the inputs.
+   * <li> Taking in a single-valued expression and a multi-valued expression and returning a multi-valued expression which
+   * represents the lambda combination of the single-value input with each of the values of the multi-value input.
+   * <br>
+   * The inputs can be either {@code func(single,multi)} or {@code func(multi,single)}.
+   * </ul>
+   * 
+   * <p>
+   * NOTE: The lambda must work on longs, not Date objects
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (long,long) -> long}
+   * @param param1 the first parameter in the lambda
+   * @param param2 the second parameter in the lambda
+   * @return a single or multi valued expression combining the two parameters with the given lambda
+   * @throws SolrException if neither parameter is single-valued
+   */
+  public static DateValueStream createDateLambdaFunction(String name, TwoLongInLongOutLambda lambda, DateValueStream param1, DateValueStream param2) throws SolrException {
+    if (param1 instanceof DateValue && param2 instanceof DateValue) {
+      return new TwoDateValueInDateValueOutFunction(name,lambda,(DateValue)param1,(DateValue)param2);
+    } else if (param1 instanceof DateValue) {
+      return new DateValueDateStreamInDateStreamOutFunction(name,lambda,(DateValue)param1,param2);
+    } else if (param2 instanceof DateValue) {
+      return new DateStreamDateValueInDateStreamOutFunction(name,lambda,param1,(DateValue)param2);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 1 single-valued parameter.");
+    }
+  }
+  /**
+   * Forwards the creation of the function to {@link #createDateLambdaFunction(String, TwoLongInLongOutLambda, DateValue[], boolean)},
+   * using {@value #defaultMultiExistsMethod} for the last argument ({@code allMustExist}).
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (boolean, boolean) -> boolean}
+   * @param params the expressions to reduce
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static DateValue createDateLambdaFunction(String name, TwoLongInLongOutLambda lambda, DateValue[] params) {
+    return createDateLambdaFunction(name,lambda,params,defaultMultiExistsMethod);
+  }
+  /**
+   * Creates a function that associatively (order is guaranteed) reduces multiple
+   * single-value date expressions into a single-value date expression for each document.
+   * <br>
+   * For a document, every parameter's value must exist for the resulting value to exist if {@code allMustExist} is true.
+   * If {@code allMustExist} is false, only one of the parameters' values must exist.
+   * 
+   * <p>
+   * NOTE: The lambda must work on longs, not Date objects
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (long, long) -> long}
+   * @param params the expressions to reduce
+   * @param allMustExist whether all parameters are required to exist
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static DateValue createDateLambdaFunction(String name, TwoLongInLongOutLambda lambda, DateValue[] params, boolean allMustExist) {
+    if (allMustExist) {
+      return new MultiDateValueInDateValueOutRequireAllFunction(name,lambda,params);
+    } else {
+      return new MultiDateValueInDateValueOutRequireOneFunction(name,lambda,params);
+    }
+  }
+  
+  /* *********************
+   * 
+   *  String Functions
+   * 
+   * *********************/
+  
+  /**
+   * Creates a function that takes in either a single or multi valued string expression and returns the same type of expression with
+   * the given lambda function applied to every value.
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (String) -> String}
+   * @param param the expression to apply the lambda to
+   * @return an expression the same type as was given with the lambda applied
+   */
+  public static StringValueStream createStringLambdaFunction(String name, StringInStringOutLambda lambda, StringValueStream param) {
+    if (param instanceof StringValue) {
+      return new StringValueInStringValueOutFunction(name,lambda,(StringValue)param);
+    } else {
+      return new StringStreamInStringStreamOutFunction(name,lambda,param);
+    }
+  }
+  /**
+   * Creates a function that takes in a multi-valued string expression and returns a single-valued string expression.
+   * The given lambda is used to associatively (order not guaranteed) reduce all values for a document down to a single value. 
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (String, String) -> String}
+   * @param param the expression to be reduced per-document
+   * @return a single-valued expression which has been reduced for every document
+   */
+  public static StringValue createStringLambdaFunction(String name, TwoStringInStringOutLambda lambda, StringValueStream param) {
+    return new StringStreamInStringValueOutFunction(name,lambda,param);
+  }
+  /**
+   * Creates a function that maps two strings to a single string.
+   * This can take the following shapes:
+   * <ul>
+   * <li> Taking in two single-valued expressions and returning a single-valued expression which represents the lambda combination of the inputs.
+   * <li> Taking in a single-valued expression and a multi-valued expression and returning a multi-valued expression which
+   * represents the lambda combination of the single-value input with each of the values of the multi-value input.
+   * <br>
+   * The inputs can be either {@code func(single,multi)} or {@code func(multi,single)}.
+   * </ul>
+   * <p>
+   * 
+   * @param name name for the function
+   * @param lambda the function to be applied to every value: {@code (String,String) -> String}
+   * @param param1 the first parameter in the lambda
+   * @param param2 the second parameter in the lambda
+   * @return a single or multi valued expression combining the two parameters with the given lambda
+   * @throws SolrException if neither parameter is single-valued
+   */
+  public static StringValueStream createStringLambdaFunction(String name, TwoStringInStringOutLambda lambda, StringValueStream param1, StringValueStream param2) throws SolrException {
+    if (param1 instanceof StringValue && param2 instanceof StringValue) {
+      return new TwoStringValueInStringValueOutFunction(name,lambda,(StringValue)param1,(StringValue)param2);
+    } else if (param1 instanceof StringValue) {
+      return new StringValueStringStreamInStringStreamOutFunction(name,lambda,(StringValue)param1,param2);
+    } else if (param2 instanceof StringValue) {
+      return new StringStreamStringValueInStringStreamOutFunction(name,lambda,param1,(StringValue)param2);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 1 single-valued parameter.");
+    }
+  }
+  /**
+   * Forwards the creation of the function to {@link #createStringLambdaFunction(String, TwoStringInStringOutLambda, StringValue[], boolean)},
+   * using {@value #defaultMultiExistsMethod} for the last argument ({@code allMustExist}).
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (boolean, boolean) -> boolean}
+   * @param params the expressions to reduce
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static StringValue createStringLambdaFunction(String name, TwoStringInStringOutLambda lambda, StringValue[] params) {
+    return createStringLambdaFunction(name,lambda,params,defaultMultiExistsMethod);
+  }
+  /**
+   * Creates a function that associatively (order is guaranteed) reduces multiple
+   * single-value string expressions into a single-value string expression for each document.
+   * <br>
+   * For a document, every parameter's value must exist for the resulting value to exist if {@code allMustExist} is true.
+   * If {@code allMustExist} is false, only one of the parameters' values must exist.
+   * 
+   * @param name name for the function
+   * @param lambda the associative function used to reduce the values: {@code (String, String) -> String}
+   * @param params the expressions to reduce
+   * @param allMustExist whether all parameters are required to exist
+   * @return a single-value expression that reduces the parameters with the given lambda
+   */
+  public static StringValue createStringLambdaFunction(String name, TwoStringInStringOutLambda lambda, StringValue[] params, boolean allMustExist) {
+    if (allMustExist) {
+      return new MultiStringValueInStringValueOutRequireAllFunction(name,lambda,params);
+    } else {
+      return new MultiStringValueInStringValueOutRequireOneFunction(name,lambda,params);
+    }
+  }
+  
+
+  /*
+   * Single Parameter
+   */
+  // Boolean Out
+  @FunctionalInterface
+  public static interface BoolInBoolOutLambda   { boolean apply(boolean a); }
+  @FunctionalInterface
+  public static interface IntInBoolOutLambda    { boolean apply(int     a); }
+  @FunctionalInterface
+  public static interface LongInBoolOutLambda   { boolean apply(long    a); }
+  @FunctionalInterface
+  public static interface FloatInBoolOutLambda  { boolean apply(float   a); }
+  @FunctionalInterface
+  public static interface DoubleInBoolOutLambda { boolean apply(double  a); }
+  @FunctionalInterface
+  public static interface StringInBoolOutLambda { boolean apply(double  a); }
+  // Int Out
+  @FunctionalInterface
+  public static interface BoolInIntOutLambda   { int apply(boolean a); }
+  @FunctionalInterface
+  public static interface IntInIntOutLambda    { int apply(int     a); }
+  @FunctionalInterface
+  public static interface LongInIntOutLambda   { int apply(long    a); }
+  @FunctionalInterface
+  public static interface FloatInIntOutLambda  { int apply(float   a); }
+  @FunctionalInterface
+  public static interface DoubleInIntOutLambda { int apply(double  a); }
+  @FunctionalInterface
+  public static interface StringInIntOutLambda { int apply(double  a); }
+  // Long Out
+  @FunctionalInterface
+  public static interface BoolInLongOutLambda   { long apply(boolean a); }
+  @FunctionalInterface
+  public static interface IntInLongOutLambda    { long apply(int     a); }
+  @FunctionalInterface
+  public static interface LongInLongOutLambda   { long apply(long    a); }
+  @FunctionalInterface
+  public static interface FloatInLongOutLambda  { long apply(float   a); }
+  @FunctionalInterface
+  public static interface DoubleInLongOutLambda { long apply(double  a); }
+  @FunctionalInterface
+  public static interface StringInLongOutLambda { long apply(double  a); }
+  // Float Out
+  @FunctionalInterface
+  public static interface BoolInFloatOutLambda   { float apply(boolean a); }
+  @FunctionalInterface
+  public static interface IntInFloatOutLambda    { float apply(int     a); }
+  @FunctionalInterface
+  public static interface LongInFloatOutLambda   { float apply(long    a); }
+  @FunctionalInterface
+  public static interface FloatInFloatOutLambda  { float apply(float   a); }
+  @FunctionalInterface
+  public static interface DoubleInFloatOutLambda { float apply(double  a); }
+  @FunctionalInterface
+  public static interface StringInFloatOutLambda { float apply(String  a); }
+  //Double Out
+  @FunctionalInterface
+  public static interface BoolInDoubleOutLambda   { double apply(boolean a); }
+  @FunctionalInterface
+  public static interface IntInDoubleOutLambda    { double apply(int     a); }
+  @FunctionalInterface
+  public static interface LongInDoubleOutLambda   { double apply(long    a); }
+  @FunctionalInterface
+  public static interface FloatInDoubleOutLambda  { double apply(float   a); }
+  @FunctionalInterface
+  public static interface DoubleInDoubleOutLambda { double apply(double  a); }
+  @FunctionalInterface
+  public static interface StringInDoubleOutLambda { double apply(String  a); }
+  //String Out
+  @FunctionalInterface
+  public static interface BoolInStringOutLambda   { String apply(boolean a); }
+  @FunctionalInterface
+  public static interface IntInStringOutLambda    { String apply(int     a); }
+  @FunctionalInterface
+  public static interface LongInStringOutLambda   { String apply(long    a); }
+  @FunctionalInterface
+  public static interface FloatInStringOutLambda  { String apply(float   a); }
+  @FunctionalInterface
+  public static interface DoubleInStringOutLambda { String apply(double  a); }
+  @FunctionalInterface
+  public static interface StringInStringOutLambda { String apply(String  a); }
+  
+  /*
+   * Two Parameters
+   */
+  //Boolean Out
+  @FunctionalInterface
+  public static interface TwoBoolInBoolOutLambda   { boolean apply(boolean a, boolean b); }
+  @FunctionalInterface
+  public static interface TwoIntInBoolOutLambda    { boolean apply(int     a, int     b); }
+  @FunctionalInterface
+  public static interface TwoLongInBoolOutLambda   { boolean apply(long    a, long    b); }
+  @FunctionalInterface
+  public static interface TwoFloatInBoolOutLambda  { boolean apply(float   a, float   b); }
+  @FunctionalInterface
+  public static interface TwoDoubleInBoolOutLambda { boolean apply(double  a, double  b); }
+  @FunctionalInterface
+  public static interface TwoStringInBoolOutLambda { boolean apply(double  a, double  b); }
+  //Int Out
+  @FunctionalInterface
+  public static interface TwoBoolInIntOutLambda   { int apply(boolean a, boolean b); }
+  @FunctionalInterface
+  public static interface TwoIntInIntOutLambda    { int apply(int     a, int     b); }
+  @FunctionalInterface
+  public static interface TwoLongInIntOutLambda   { int apply(long    a, long    b); }
+  @FunctionalInterface
+  public static interface TwoFloatInIntOutLambda  { int apply(float   a, float   b); }
+  @FunctionalInterface
+  public static interface TwoDoubleInIntOutLambda { int apply(double  a, double  b); }
+  @FunctionalInterface
+  public static interface TwoStringInIntOutLambda { int apply(double  a, double  b); }
+  //Long Out
+  @FunctionalInterface
+  public static interface TwoBoolInLongOutLambda   { long apply(boolean a, boolean b); }
+  @FunctionalInterface
+  public static interface TwoIntInLongOutLambda    { long apply(int     a, int     b); }
+  @FunctionalInterface
+  public static interface TwoLongInLongOutLambda   { long apply(long    a, long    b); }
+  @FunctionalInterface
+  public static interface TwoFloatInLongOutLambda  { long apply(float   a, float   b); }
+  @FunctionalInterface
+  public static interface TwoDoubleInLongOutLambda { long apply(double  a, double  b); }
+  @FunctionalInterface
+  public static interface TwoStringInLongOutLambda { long apply(double  a, double  b); }
+  //Float Out
+  @FunctionalInterface
+  public static interface TwoBoolInFloatOutLambda   { float apply(boolean a, boolean b); }
+  @FunctionalInterface
+  public static interface TwoIntInFloatOutLambda    { float apply(int     a, int     b); }
+  @FunctionalInterface
+  public static interface TwoLongInFloatOutLambda   { float apply(long    a, long    b); }
+  @FunctionalInterface
+  public static interface TwoFloatInFloatOutLambda  { float apply(float   a, float   b); }
+  @FunctionalInterface
+  public static interface TwoDoubleInFloatOutLambda { float apply(double  a, double  b); }
+  @FunctionalInterface
+  public static interface TwoStringInFloatOutLambda { float apply(String  a, String  b); }
+  //Double Out
+  @FunctionalInterface
+  public static interface TwoBoolInDoubleOutLambda   { double apply(boolean a, boolean b); }
+  @FunctionalInterface
+  public static interface TwoIntInDoubleOutLambda    { double apply(int     a, int     b); }
+  @FunctionalInterface
+  public static interface TwoLongInDoubleOutLambda   { double apply(long    a, long    b); }
+  @FunctionalInterface
+  public static interface TwoFloatInDoubleOutLambda  { double apply(float   a, float   b); }
+  @FunctionalInterface
+  public static interface TwoDoubleInDoubleOutLambda { double apply(double  a, double  b); }
+  @FunctionalInterface
+  public static interface TwoStringInDoubleOutLambda { double apply(String  a, String  b); }
+  //String Out
+  @FunctionalInterface
+  public static interface TwoBoolInStringOutLambda   { String apply(boolean a, boolean b); }
+  @FunctionalInterface
+  public static interface TwoIntInStringOutLambda    { String apply(int     a, int     b); }
+  @FunctionalInterface
+  public static interface TwoLongInStringOutLambda   { String apply(long    a, long    b); }
+  @FunctionalInterface
+  public static interface TwoFloatInStringOutLambda  { String apply(float   a, float   b); }
+  @FunctionalInterface
+  public static interface TwoDoubleInStringOutLambda { String apply(double  a, double  b); }
+  @FunctionalInterface
+  public static interface TwoStringInStringOutLambda { String apply(String  a, String  b); }
+} 
+class BooleanValueInBooleanValueOutFunction extends AbstractBooleanValue {
+  private final BooleanValue param;
+  private final BoolInBoolOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanValueInBooleanValueOutFunction(String name, BoolInBoolOutLambda lambda, BooleanValue param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public boolean getBoolean() {
+    boolean value = lambda.apply(param.getBoolean());
+    exists = param.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanStreamInBooleanStreamOutFunction extends AbstractBooleanValueStream {
+  private final BooleanValueStream param;
+  private final BoolInBoolOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanStreamInBooleanStreamOutFunction(String name, BoolInBoolOutLambda lambda, BooleanValueStream param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    param.streamBooleans(value -> cons.accept(lambda.apply(value)));
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanStreamInBooleanValueOutFunction extends AbstractBooleanValue implements BooleanConsumer {
+  private final BooleanValueStream param;
+  private final TwoBoolInBoolOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanStreamInBooleanValueOutFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValueStream param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  private boolean exists = false;
+  private boolean value;
+
+  @Override
+  public boolean getBoolean() {
+    exists = false;
+    param.streamBooleans(this);
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  public void accept(boolean paramValue) {
+    if (!exists) {
+      exists = true;
+      value = paramValue;
+    } else {
+      value = lambda.apply(value, paramValue);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class TwoBooleanValueInBooleanValueOutFunction extends AbstractBooleanValue {
+  private final BooleanValue param1;
+  private final BooleanValue param2;
+  private final TwoBoolInBoolOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public TwoBooleanValueInBooleanValueOutFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValue param1, BooleanValue param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+  
+  private boolean exists = false;
+
+  @Override
+  public boolean getBoolean() {
+    boolean value = lambda.apply(param1.getBoolean(), param2.getBoolean());
+    exists = param1.exists() && param2.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanValueBooleanStreamInBooleanStreamOutFunction extends AbstractBooleanValueStream {
+  private final BooleanValue param1;
+  private final BooleanValueStream param2;
+  private final TwoBoolInBoolOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanValueBooleanStreamInBooleanStreamOutFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValue param1, BooleanValueStream param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    boolean value1 = param1.getBoolean();
+    if (param1.exists()) {
+      param2.streamBooleans(value2 -> cons.accept(lambda.apply(value1,value2)));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanStreamBooleanValueInBooleanStreamOutFunction extends AbstractBooleanValueStream {
+  private final BooleanValueStream param1;
+  private final BooleanValue param2;
+  private final TwoBoolInBoolOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanStreamBooleanValueInBooleanStreamOutFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValueStream param1, BooleanValue param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    boolean value2 = param2.getBoolean();
+    if (param2.exists()) {
+      param1.streamBooleans(value1 -> cons.accept(lambda.apply(value1,value2)));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+abstract class MultiBooleanValueInBooleanValueOutFunction extends AbstractBooleanValue {
+  protected final BooleanValue[] params;
+  protected final TwoBoolInBoolOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public MultiBooleanValueInBooleanValueOutFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValue[] params) {
+    this.name = name;
+    this.lambda = lambda;
+    this.params = params;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,params);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,params);
+  }
+  
+  protected boolean exists = false;
+  protected boolean temp;
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class MultiBooleanValueInBooleanValueOutRequireAllFunction extends MultiBooleanValueInBooleanValueOutFunction {
+  
+  public MultiBooleanValueInBooleanValueOutRequireAllFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValue[] params) {
+    super(name, lambda, params);
+  }
+  
+  @Override
+  public boolean getBoolean() {
+    boolean value = params[0].getBoolean();
+    exists = params[0].exists();
+    for (int i = 1; i < params.length && exists; ++i) {
+      value = lambda.apply(value, params[i].getBoolean());
+      exists = params[i].exists();
+    }
+    return value;
+  }
+}
+class MultiBooleanValueInBooleanValueOutRequireOneFunction extends MultiBooleanValueInBooleanValueOutFunction {
+  
+  public MultiBooleanValueInBooleanValueOutRequireOneFunction(String name, TwoBoolInBoolOutLambda lambda, BooleanValue[] params) {
+    super(name, lambda, params);
+  }
+  
+  @Override
+  public boolean getBoolean() {
+    int i = -1;
+    boolean value = false;
+    exists = false;
+    while (++i < params.length) {
+      value = params[i].getBoolean();
+      exists = params[i].exists();
+      if (exists) {
+        break;
+      }
+    }
+    while (++i < params.length) {
+      temp = params[i].getBoolean();
+      if (params[i].exists()) {
+        value = lambda.apply(value, temp);
+      }
+    }
+    return value;
+  }
+}
+class IntValueInIntValueOutFunction extends AbstractIntValue {
+  private final IntValue param;
+  private final IntInIntOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntValueInIntValueOutFunction(String name, IntInIntOutLambda lambda, IntValue param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public int getInt() {
+    int value = lambda.apply(param.getInt());
+    exists = param.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntStreamInIntStreamOutFunction extends AbstractIntValueStream {
+  private final IntValueStream param;
+  private final IntInIntOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntStreamInIntStreamOutFunction(String name, IntInIntOutLambda lambda, IntValueStream param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  @Override
+  public void streamInts(IntConsumer cons) {
+    param.streamInts(value -> cons.accept(lambda.apply(value)));
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntStreamInIntValueOutFunction extends AbstractIntValue implements IntConsumer {
+  private final IntValueStream param;
+  private final TwoIntInIntOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntStreamInIntValueOutFunction(String name, TwoIntInIntOutLambda lambda, IntValueStream param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  private boolean exists = false;
+  private int value;
+
+  @Override
+  public int getInt() {
+    exists = false;
+    param.streamInts(this);
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  public void accept(int paramValue) {
+    if (!exists) {
+      exists = true;
+      value = paramValue;
+    } else {
+      value = lambda.apply(value, paramValue);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class TwoIntValueInIntValueOutFunction extends AbstractIntValue {
+  private final IntValue param1;
+  private final IntValue param2;
+  private final TwoIntInIntOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public TwoIntValueInIntValueOutFunction(String name, TwoIntInIntOutLambda lambda, IntValue param1, IntValue param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+  
+  private boolean exists = false;
+
+  @Override
+  public int getInt() {
+    int value = lambda.apply(param1.getInt(), param2.getInt());
+    exists = param1.exists() && param2.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntValueIntStreamInIntStreamOutFunction extends AbstractIntValueStream {
+  private final IntValue param1;
+  private final IntValueStream param2;
+  private final TwoIntInIntOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntValueIntStreamInIntStreamOutFunction(String name, TwoIntInIntOutLambda lambda, IntValue param1, IntValueStream param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+
+  @Override
+  public void streamInts(IntConsumer cons) {
+    int value1 = param1.getInt();
+    if (param1.exists()) {
+      param2.streamInts(value2 -> cons.accept(lambda.apply(value1,value2)));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntStreamIntValueInIntStreamOutFunction extends AbstractIntValueStream {
+  private final IntValueStream param1;
+  private final IntValue param2;
+  private final TwoIntInIntOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntStreamIntValueInIntStreamOutFunction(String name, TwoIntInIntOutLambda lambda, IntValueStream param1, IntValue param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+
+  @Override
+  public void streamInts(IntConsumer cons) {
+    int value2 = param2.getInt();
+    if (param2.exists()) {
+      param1.streamInts(value1 -> cons.accept(lambda.apply(value1,value2)));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+abstract class MultiIntValueInIntValueOutFunction extends AbstractIntValue {
+  protected final IntValue[] params;
+  protected final TwoIntInIntOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public MultiIntValueInIntValueOutFunction(String name, TwoIntInIntOutLambda lambda, IntValue[] params) {
+    this.name = name;
+    this.lambda = lambda;
+    this.params = params;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,params);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,params);
+  }
+  
+  protected boolean exists = false;
+  protected int temp;
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class MultiIntValueInIntValueOutRequireAllFunction extends MultiIntValueInIntValueOutFunction {
+  
+  public MultiIntValueInIntValueOutRequireAllFunction(String name, TwoIntInIntOutLambda lambda, IntValue[] params) {
+    super(name, lambda, params);
+  }
+  
+  @Override
+  public int getInt() {
+    int value = params[0].getInt();
+    exists = params[0].exists();
+    for (int i = 1; i < params.length && exists; ++i) {
+      value = lambda.apply(value, params[i].getInt());
+      exists = params[i].exists();
+    }
+    return value;
+  }
+}
+class MultiIntValueInIntValueOutRequireOneFunction extends MultiIntValueInIntValueOutFunction {
+  
+  public MultiIntValueInIntValueOutRequireOneFunction(String name, TwoIntInIntOutLambda lambda, IntValue[] params) {
+    super(name, lambda, params);
+  }
+  
+  @Override
+  public int getInt() {
+    int i = -1;
+    int value = 0;
+    exists = false;
+    while (++i < params.length) {
+      value = params[i].getInt();
+      exists = params[i].exists();
+      if (exists) {
+        break;
+      }
+    }
+    while (++i < params.length) {
+      temp = params[i].getInt();
+      if (params[i].exists()) {
+        value = lambda.apply(value, temp);
+      }
+    }
+    return value;
+  }
+}
+class LongValueInLongValueOutFunction extends AbstractLongValue {
+  private final LongValue param;
+  private final LongInLongOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongValueInLongValueOutFunction(String name, LongInLongOutLambda lambda, LongValue param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public long getLong() {
+    long value = lambda.apply(param.getLong());
+    exists = param.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongStreamInLongStreamOutFunction extends AbstractLongValueStream {
+  private final LongValueStream param;
+  private final LongInLongOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongStreamInLongStreamOutFunction(String name, LongInLongOutLambda lambda, LongValueStream param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    param.streamLongs(value -> cons.accept(lambda.apply(value)));
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongStreamInLongValueOutFunction extends AbstractLongValue implements LongConsumer {
+  private final LongValueStream param;
+  private final TwoLongInLongOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongStreamInLongValueOutFunction(String name, TwoLongInLongOutLambda lambda, LongValueStream param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  private boolean exists = false;
+  private long value;
+
+  @Override
+  public long getLong() {
+    exists = false;
+    param.streamLongs(this);
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  public void accept(long paramValue) {
+    if (!exists) {
+      exists = true;
+      value = paramValue;
+    } else {
+      value = lambda.apply(value, paramValue);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class TwoLongValueInLongValueOutFunction extends AbstractLongValue {
+  private final LongValue param1;
+  private final LongValue param2;
+  private final TwoLongInLongOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public TwoLongValueInLongValueOutFunction(String name, TwoLongInLongOutLambda lambda, LongValue param1, LongValue param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+  
+  private boolean exists = false;
+
+  @Override
+  public long getLong() {
+    long value = lambda.apply(param1.getLong(), param2.getLong());
+    exists = param1.exists() && param2.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongValueLongStreamInLongStreamOutFunction extends AbstractLongValueStream {
+  private final LongValue param1;
+  private final LongValueStream param2;
+  private final TwoLongInLongOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongValueLongStreamInLongStreamOutFunction(String name, TwoLongInLongOutLambda lambda, LongValue param1, LongValueStream param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    long value1 = param1.getLong();
+    if (param1.exists()) {
+      param2.streamLongs(value2 -> cons.accept(lambda.apply(value1,value2)));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongStreamLongValueInLongStreamOutFunction extends AbstractLongValueStream {
+  private final LongValueStream param1;
+  private final LongValue param2;
+  private final TwoLongInLongOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongStreamLongValueInLongStreamOutFunction(String name, TwoLongInLongOutLambda lambda, LongValueStream param1, LongValue param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    long value2 = param2.getLong();
+    if (param2.exists()) {
+      param1.streamLongs(value1 -> cons.accept(lambda.apply(value1,value2)));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+abstract class MultiLongValueInLongValueOutFunction extends AbstractLongValue {
+  protected final LongValue[] params;
+  protected final TwoLongInLongOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public MultiLongValueInLongValueOutFunction(String name, TwoLongInLongOutLambda lambda, LongValue[] params) {
+    this.name = name;
+    this.lambda = lambda;
+    this.params = params;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,params);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,params);
+  }
+  
+  protected boolean exists = false;
+  protected long temp;
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class MultiLongValueInLongValueOutRequireAllFunction extends MultiLongValueInLongValueOutFunction {
+  
+  public MultiLongValueInLongValueOutRequireAllFunction(String name, TwoLongInLongOutLambda lambda, LongValue[] params) {
+    super(name, lambda, params);
+  }
+  
+  @Override
+  public long getLong() {
+    long value = params[0].getLong();
+    exists = params[0].exists();
+    for (int i = 1; i < params.length && exists; ++i) {
+      value = lambda.apply(value, params[i].getLong());
+      exists = params[i].exists();
+    }
+    return value;
+  }
+}
+class MultiLongValueInLongValueOutRequireOneFunction extends MultiLongValueInLongValueOutFunction {
+  
+  public MultiLongValueInLongValueOutRequireOneFunction(String name, TwoLongInLongOutLambda lambda, LongValue[] params) {
+    super(name, lambda, params);
+  }
+  
+  @Override
+  public long getLong() {
+    int i = -1;
+    long value = 0;
+    exists = false;
+    while (++i < params.length) {
+      value = params[i].getLong();
+      exists = params[i].exists();
+      if (exists) {
+        break;
+      }
+    }
+    while (++i < params.length) {
+      temp = params[i].getLong();
+      if (params[i].exists()) {
+        value = lambda.apply(value, temp);
+      }
+    }
+    return value;
+  }
+}
+class FloatValueInFloatValueOutFunction extends AbstractFloatValue {
+  private final FloatValue param;
+  private final FloatInFloatOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatValueInFloatValueOutFunction(String name, FloatInFloatOutLambda lambda, FloatValue param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public float getFloat() {
+    float value = lambda.apply(param.getFloat());
+    exists = param.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatStreamInFloatStreamOutFunction extends AbstractFloatValueStream {
+  private final FloatValueStream param;
+  private final FloatInFloatOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatStreamInFloatStreamOutFunction(String name, FloatInFloatOutLambda lambda, FloatValueStream param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    param.streamFloats(value -> cons.accept(lambda.apply(value)));
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatStreamInFloatValueOutFunction extends AbstractFloatValue implements FloatConsumer {
+  private final FloatValueStream param;
+  private final TwoFloatInFloatOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatStreamInFloatValueOutFunction(String name, TwoFloatInFloatOutLambda lambda, FloatValueStream param) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+  }
+
+  private boolean exists = false;
+  private float value;
+
+  @Override
+  public float getFloat() {
+    exists = false;
+    param.streamFloats(this);
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  public void accept(float paramValue) {
+    if (!exists) {
+      exists = true;
+      value = paramValue;
+    } else {
+      value = lambda.apply(value, paramValue);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class TwoFloatValueInFloatValueOutFunction extends AbstractFloatValue {
+  private final FloatValue param1;
+  private final FloatValue param2;
+  private final TwoFloatInFloatOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public TwoFloatValueInFloatValueOutFunction(String name, TwoFloatInFloatOutLambda lambda, FloatValue param1, FloatValue param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+  
+  private boolean exists = false;
+
+  @Override
+  public float getFloat() {
+    float value = lambda.apply(param1.getFloat(), param2.getFloat());
+    exists = param1.exists() && param2.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatValueFloatStreamInFloatStreamOutFunction extends AbstractFloatValueStream {
+  private final FloatValue param1;
+  private final FloatValueStream param2;
+  private final TwoFloatInFloatOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatValueFloatStreamInFloatStreamOutFunction(String name, TwoFloatInFloatOutLambda lambda, FloatValue param1, FloatValueStream param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    float value1 = param1.getFloat();
+    if (param1.exists()) {
+      param2.streamFloats(value2 -> cons.accept(lambda.apply(value1,value2)));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatStreamFloatValueInFloatStreamOutFunction extends AbstractFloatValueStream {
+  private final FloatValueStream param1;
+  private final FloatValue param2;
+  private final TwoFloatInFloatOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatStreamFloatValueInFloatStreamOutFunction(String name, TwoFloatInFloatOutLambda lambda, FloatValueStream param1, FloatValue param2) {
+    this.name = name;
+    this.lambda = lambda;
+    this.param1 = param1;
+    this.param2 = param2;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param1,param2);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param1,param2);
+  }
+
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    float value2 = param2.getFloat();
+    if (param2.exists()) {
+      param1.streamFloats(value1 -> cons.accept(lambda.apply(value1,value2)));
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+abstract class MultiFloatValueInFloatValueOutFunction extends AbstractFloatValue {
+  protected final FloatValue[] params;
+  protected final TwoFloatInFloatOutLambda lambda;
+  private final String name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public MultiFloatValueInFloatValueOutFunction(String name, TwoFloatInFloatOutLambda lambda, FloatValue[] params) {
+    this.name = name;
+    this.lambda = lambda;
+    this.params = params;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,params);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,params);
+  }
+  
+  protected boolean exists = false;
+  protected float temp;
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  p

<TRUNCATED>

[08/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionCheckedDataReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionCheckedDataReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionCheckedDataReservation.java
new file mode 100644
index 0000000..73287fe
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionCheckedDataReservation.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.util.function.BooleanSupplier;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+
+/**
+ * A reservation allows a {@link ReductionDataCollector} to specify a piece of data it needs to export from the shard.
+ * This data may, or may not, exist. The {@link ReductionDataCollector} need not check while importing/exporting since
+ * the Reader/Writers handle all checking.
+ */
+public abstract class ReductionCheckedDataReservation<A, E> extends ReductionDataReservation<A, E> {
+  protected final BooleanSupplier exists;
+  
+  protected ReductionCheckedDataReservation(A applier, E extractor, BooleanSupplier exists) {
+    super(applier, extractor);
+    this.exists = exists;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionDataArrayReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionDataArrayReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionDataArrayReservation.java
new file mode 100644
index 0000000..cbeece6
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionDataArrayReservation.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+
+/**
+ * A reservation allows a {@link ReductionDataCollector} to specify an array of data it needs to export from the shard.
+ */
+public abstract class ReductionDataArrayReservation<A, E> extends ReductionDataReservation<A, E> {
+  protected final IntConsumer sizeApplier;
+  protected final IntSupplier sizeExtractor;
+  
+  protected ReductionDataArrayReservation(A applier, IntConsumer sizeApplier, E extractor, IntSupplier sizeExtractor) {
+    super(applier, extractor);
+    this.sizeApplier = sizeApplier;
+    this.sizeExtractor = sizeExtractor;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionDataReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionDataReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionDataReservation.java
new file mode 100644
index 0000000..903016e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/ReductionDataReservation.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.stream.reservation.read.ReductionDataReader;
+import org.apache.solr.analytics.stream.reservation.write.ReductionDataWriter;
+
+/**
+ * A reservation allows a {@link ReductionDataCollector} to specify a piece of data it needs to export from the shard.
+ */
+public abstract class ReductionDataReservation<A, E> {
+  protected final A applier;
+  protected final E extractor;
+  
+  protected ReductionDataReservation(A applier, E extractor) {
+    this.applier = applier;
+    this.extractor = extractor;
+  }
+  
+  /**
+   * Generate a {@link ReductionDataReader} that merges the set of data this reservation represents.
+   * 
+   * @param input the shard input stream
+   * @return a reader from the given input
+   */
+  public abstract ReductionDataReader<A> createReadStream(DataInput input);
+  
+  /**
+   * Generate a {@link ReductionDataWriter} that exports the set of data this reservation represents.
+   * 
+   * @param output the shard output stream
+   * @return a writer to the given output
+   */
+  public abstract ReductionDataWriter<E> createWriteStream(DataOutput output);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringArrayReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringArrayReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringArrayReservation.java
new file mode 100644
index 0000000..c3c6989
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringArrayReservation.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import org.apache.solr.analytics.stream.reservation.read.StringDataArrayReader;
+import org.apache.solr.analytics.stream.reservation.write.StringDataArrayWriter;
+
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+public class StringArrayReservation extends ReductionDataArrayReservation<Consumer<String>, Supplier<String>> {
+  
+  public StringArrayReservation(Consumer<String> applier, IntConsumer sizeApplier, Supplier<String> extractor, IntSupplier sizeExtractor) {
+    super(applier, sizeApplier, extractor, sizeExtractor);
+  }
+
+  @Override
+  public StringDataArrayReader createReadStream(DataInput input) {
+    return new StringDataArrayReader(input, applier, sizeApplier);
+  }
+
+  @Override
+  public StringDataArrayWriter createWriteStream(DataOutput output) {
+    return new StringDataArrayWriter(output, extractor, sizeExtractor);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringCheckedReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringCheckedReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringCheckedReservation.java
new file mode 100644
index 0000000..29c3614
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringCheckedReservation.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.Supplier;
+
+import org.apache.solr.analytics.stream.reservation.read.StringCheckedDataReader;
+import org.apache.solr.analytics.stream.reservation.write.StringCheckedDataWriter;
+
+import java.util.function.BooleanSupplier;
+import java.util.function.Consumer;
+
+public class StringCheckedReservation extends ReductionCheckedDataReservation<Consumer<String>, Supplier<String>> {
+  
+  public StringCheckedReservation(Consumer<String> applier, Supplier<String> extractor, BooleanSupplier exists) {
+    super(applier, extractor, exists);
+  }
+
+  @Override
+  public StringCheckedDataReader createReadStream(DataInput input) {
+    return new StringCheckedDataReader(input, applier);
+  }
+
+  @Override
+  public StringCheckedDataWriter createWriteStream(DataOutput output) {
+    return new StringCheckedDataWriter(output, extractor, exists);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringReservation.java
new file mode 100644
index 0000000..2601874
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/StringReservation.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.Supplier;
+
+import org.apache.solr.analytics.stream.reservation.read.StringDataReader;
+import org.apache.solr.analytics.stream.reservation.write.StringDataWriter;
+
+import java.util.function.Consumer;
+
+public class StringReservation extends ReductionDataReservation<Consumer<String>, Supplier<String>> {
+  
+  public StringReservation(Consumer<String> applier, Supplier<String> extractor) {
+    super(applier, extractor);
+  }
+
+  @Override
+  public StringDataReader createReadStream(DataInput input) {
+    return new StringDataReader(input, applier);
+  }
+
+  @Override
+  public StringDataWriter createWriteStream(DataOutput output) {
+    return new StringDataWriter(output, extractor);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/package-info.java
new file mode 100644
index 0000000..bfd832d
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Reservation classes for a single type of data being stored by one Reduction Data Collector.
+ * These reservations are imported/exported between shards during the streaming process.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanCheckedDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanCheckedDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanCheckedDataReader.java
new file mode 100644
index 0000000..49f6f00
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanCheckedDataReader.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+
+public class BooleanCheckedDataReader extends ReductionCheckedDataReader<BooleanConsumer> {
+  
+  public BooleanCheckedDataReader(DataInput inputStream, BooleanConsumer applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void checkedRead() throws IOException {
+    applier.accept(inputStream.readBoolean());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanDataArrayReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanDataArrayReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanDataArrayReader.java
new file mode 100644
index 0000000..ee929f4
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanDataArrayReader.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.IntConsumer;
+
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+
+public class BooleanDataArrayReader extends ReductionDataArrayReader<BooleanConsumer> {
+  
+  public BooleanDataArrayReader(DataInput inputStream, BooleanConsumer applier, IntConsumer signal) {
+    super(inputStream, applier, signal);
+  }
+  @Override
+  public void read(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      applier.accept(inputStream.readBoolean());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanDataReader.java
new file mode 100644
index 0000000..98e116d
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/BooleanDataReader.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+
+public class BooleanDataReader extends ReductionDataReader<BooleanConsumer> {
+  
+  public BooleanDataReader(DataInput inputStream, BooleanConsumer applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void read() throws IOException {
+    applier.accept(inputStream.readBoolean());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleCheckedDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleCheckedDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleCheckedDataReader.java
new file mode 100644
index 0000000..ec6a6e4
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleCheckedDataReader.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.DoubleConsumer;
+
+public class DoubleCheckedDataReader extends ReductionCheckedDataReader<DoubleConsumer> {
+  
+  public DoubleCheckedDataReader(DataInput inputStream, DoubleConsumer applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void checkedRead() throws IOException {
+    applier.accept(inputStream.readDouble());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleDataArrayReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleDataArrayReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleDataArrayReader.java
new file mode 100644
index 0000000..5690a45
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleDataArrayReader.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+
+public class DoubleDataArrayReader extends ReductionDataArrayReader<DoubleConsumer> {
+  
+  public DoubleDataArrayReader(DataInput inputStream, DoubleConsumer applier, IntConsumer signal) {
+    super(inputStream, applier, signal);
+  }
+  @Override
+  public void read(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      applier.accept(inputStream.readDouble());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleDataReader.java
new file mode 100644
index 0000000..42de9bf
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/DoubleDataReader.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.DoubleConsumer;
+
+public class DoubleDataReader extends ReductionDataReader<DoubleConsumer> {
+  
+  public DoubleDataReader(DataInput inputStream, DoubleConsumer applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void read() throws IOException {
+    applier.accept(inputStream.readDouble());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatCheckedDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatCheckedDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatCheckedDataReader.java
new file mode 100644
index 0000000..8139cfb
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatCheckedDataReader.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+import org.apache.solr.analytics.util.function.FloatConsumer;
+
+public class FloatCheckedDataReader extends ReductionCheckedDataReader<FloatConsumer> {
+  
+  public FloatCheckedDataReader(DataInput inputStream, FloatConsumer applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void checkedRead() throws IOException {
+    applier.accept(inputStream.readFloat());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatDataArrayReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatDataArrayReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatDataArrayReader.java
new file mode 100644
index 0000000..1157a11
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatDataArrayReader.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.IntConsumer;
+
+import org.apache.solr.analytics.util.function.FloatConsumer;
+
+public class FloatDataArrayReader extends ReductionDataArrayReader<FloatConsumer> {
+  
+  public FloatDataArrayReader(DataInput inputStream, FloatConsumer applier, IntConsumer signal) {
+    super(inputStream, applier, signal);
+  }
+  @Override
+  public void read(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      applier.accept(inputStream.readFloat());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatDataReader.java
new file mode 100644
index 0000000..63067cd
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/FloatDataReader.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+import org.apache.solr.analytics.util.function.FloatConsumer;
+
+public class FloatDataReader extends ReductionDataReader<FloatConsumer> {
+  
+  public FloatDataReader(DataInput inputStream, FloatConsumer applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void read() throws IOException {
+    applier.accept(inputStream.readFloat());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntCheckedDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntCheckedDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntCheckedDataReader.java
new file mode 100644
index 0000000..e926e3e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntCheckedDataReader.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.IntConsumer;
+
+public class IntCheckedDataReader extends ReductionCheckedDataReader<IntConsumer> {
+  
+  public IntCheckedDataReader(DataInput inputStream, IntConsumer applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void checkedRead() throws IOException {
+    applier.accept(inputStream.readInt());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntDataArrayReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntDataArrayReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntDataArrayReader.java
new file mode 100644
index 0000000..a0c1d86
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntDataArrayReader.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.IntConsumer;
+
+public class IntDataArrayReader extends ReductionDataArrayReader<IntConsumer> {
+  
+  public IntDataArrayReader(DataInput inputStream, IntConsumer applier, IntConsumer signal) {
+    super(inputStream, applier, signal);
+  }
+  @Override
+  public void read(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      applier.accept(inputStream.readInt());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntDataReader.java
new file mode 100644
index 0000000..5b65055
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/IntDataReader.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.IntConsumer;
+
+public class IntDataReader extends ReductionDataReader<IntConsumer> {
+  
+  public IntDataReader(DataInput inputStream, IntConsumer applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void read() throws IOException {
+    applier.accept(inputStream.readInt());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongCheckedDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongCheckedDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongCheckedDataReader.java
new file mode 100644
index 0000000..7d9a7ff
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongCheckedDataReader.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.LongConsumer;
+
+public class LongCheckedDataReader extends ReductionCheckedDataReader<LongConsumer> {
+  
+  public LongCheckedDataReader(DataInput inputStream, LongConsumer applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void checkedRead() throws IOException {
+    applier.accept(inputStream.readLong());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongDataArrayReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongDataArrayReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongDataArrayReader.java
new file mode 100644
index 0000000..6c09f46
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongDataArrayReader.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+public class LongDataArrayReader extends ReductionDataArrayReader<LongConsumer> {
+  
+  public LongDataArrayReader(DataInput inputStream, LongConsumer applier, IntConsumer signal) {
+    super(inputStream, applier, signal);
+  }
+  @Override
+  public void read(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      applier.accept(inputStream.readLong());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongDataReader.java
new file mode 100644
index 0000000..bf4057d
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/LongDataReader.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.LongConsumer;
+
+public class LongDataReader extends ReductionDataReader<LongConsumer> {
+  
+  public LongDataReader(DataInput inputStream, LongConsumer applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void read() throws IOException {
+    applier.accept(inputStream.readLong());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionCheckedDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionCheckedDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionCheckedDataReader.java
new file mode 100644
index 0000000..ac98987
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionCheckedDataReader.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+/**
+ * Abstract class to manage the reading and application of data from a {@link DataInput} stream.
+ * The data being read may not exist, so the reader first checks before reading.
+ */
+public abstract class ReductionCheckedDataReader<A> extends ReductionDataReader<A> {
+  
+  public ReductionCheckedDataReader(DataInput inputStream, A applier) {
+    super(inputStream, applier);
+  }
+  
+  @Override
+  /**
+   * Read a piece of data from the input stream and feed it to the applier.
+   * <br>
+   * First checks that the piece of data exists before reading.
+   * 
+   * @throws IOException if an exception occurs while reading from the input stream
+   */
+  public void read() throws IOException {
+    if (inputStream.readBoolean()) {
+      checkedRead();
+    }
+  }
+  
+  /**
+   * Read a piece of data from the input stream and feed it to the applier.
+   * <br>
+   * This piece of data is guaranteed to be there.
+   * 
+   * @throws IOException if an exception occurs while reading from the input stream
+   */
+  protected abstract void checkedRead() throws IOException;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionDataArrayReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionDataArrayReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionDataArrayReader.java
new file mode 100644
index 0000000..2a696d7
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionDataArrayReader.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.IntConsumer;
+
+/**
+ * Abstract class to manage the reading and application of array data from a {@link DataInput} stream.
+ */
+public abstract class ReductionDataArrayReader<A> extends ReductionDataReader<A> {
+  protected final IntConsumer signal;
+  
+  public ReductionDataArrayReader(DataInput inputStream, A applier, IntConsumer signal) {
+    super(inputStream, applier);
+    
+    this.signal = signal;
+  }
+  
+  @Override
+  /**
+   * Read an array of data from the input stream and feed it to the applier, first signaling the size of the array.
+   * 
+   * @throws IOException if an exception occurs while reading from the input stream
+   */
+  public void read() throws IOException {
+    int size = inputStream.readInt();
+    signal.accept(size);
+    read(size);
+  }
+  
+  /**
+   * Read an array from the input stream, feeding each member to the applier.
+   * 
+   * @param size length of the array to read
+   * @throws IOException if an exception occurs while reading from the input stream
+   */
+  protected abstract void read(int size) throws IOException;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionDataReader.java
new file mode 100644
index 0000000..ec99621
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/ReductionDataReader.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+/**
+ * Abstract class to manage the reading and application of data from a {@link DataInput} stream.
+ */
+public abstract class ReductionDataReader<A> {
+  protected final DataInput inputStream;
+  protected final A applier;
+  
+  public ReductionDataReader(DataInput inputStream, A applier) {
+    this.inputStream = inputStream;
+    this.applier = applier;
+  }
+  
+  /**
+   * Read a piece of data from the input stream and feed it to the applier.
+   * 
+   * @throws IOException if an exception occurs while reading from the input stream
+   */
+  public abstract void read() throws IOException;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringCheckedDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringCheckedDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringCheckedDataReader.java
new file mode 100644
index 0000000..400e990
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringCheckedDataReader.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.Consumer;
+
+public class StringCheckedDataReader extends ReductionCheckedDataReader<Consumer<String>> {
+  
+  public StringCheckedDataReader(DataInput inputStream, Consumer<String> applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void checkedRead() throws IOException {
+    applier.accept(inputStream.readUTF());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringDataArrayReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringDataArrayReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringDataArrayReader.java
new file mode 100644
index 0000000..048b84f
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringDataArrayReader.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.IntConsumer;
+
+public class StringDataArrayReader extends ReductionDataArrayReader<Consumer<String>> {
+  
+  public StringDataArrayReader(DataInput inputStream, Consumer<String> applier, IntConsumer signal) {
+    super(inputStream, applier, signal);
+  }
+  @Override
+  public void read(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      applier.accept(inputStream.readUTF());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringDataReader.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringDataReader.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringDataReader.java
new file mode 100644
index 0000000..d4d6bc4
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/StringDataReader.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.function.Consumer;
+
+public class StringDataReader extends ReductionDataReader<Consumer<String>> {
+  
+  public StringDataReader(DataInput inputStream, Consumer<String> applier) {
+    super(inputStream, applier);
+  }
+  @Override
+  public void read() throws IOException {
+    if (inputStream.readBoolean()) {
+      applier.accept(inputStream.readUTF());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/package-info.java
new file mode 100644
index 0000000..26bb7c5
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/read/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Reading classes for a single type of data being stored by one Reduction Data Collector.
+ * These writers are used to import data from shards during the streaming process.
+ */
+package org.apache.solr.analytics.stream.reservation.read;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanCheckedDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanCheckedDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanCheckedDataWriter.java
new file mode 100644
index 0000000..6b4c1b7
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanCheckedDataWriter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.BooleanSupplier;
+
+public class BooleanCheckedDataWriter extends ReductionCheckedDataWriter<BooleanSupplier> {
+  
+  public BooleanCheckedDataWriter(DataOutput output, BooleanSupplier extractor, BooleanSupplier existsSupplier) {
+    super(output, extractor, existsSupplier);
+  }
+
+  @Override
+  public void checkedWrite() throws IOException {
+    output.writeBoolean(extractor.getAsBoolean());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanDataArrayWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanDataArrayWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanDataArrayWriter.java
new file mode 100644
index 0000000..c188770
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanDataArrayWriter.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.BooleanSupplier;
+import java.util.function.IntSupplier;
+
+public class BooleanDataArrayWriter extends ReductionDataArrayWriter<BooleanSupplier> {
+
+  public BooleanDataArrayWriter(DataOutput output, BooleanSupplier extractor, IntSupplier sizeSupplier) {
+    super(output, extractor, sizeSupplier);
+  }
+  
+  @Override
+  public void write(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      output.writeBoolean(extractor.getAsBoolean());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanDataWriter.java
new file mode 100644
index 0000000..f921a5d
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/BooleanDataWriter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.BooleanSupplier;
+
+public class BooleanDataWriter extends ReductionDataWriter<BooleanSupplier> {
+  
+  public BooleanDataWriter(DataOutput output, BooleanSupplier extractor) {
+    super(output, extractor);
+  }
+
+  @Override
+  public void write() throws IOException {
+    output.writeBoolean(extractor.getAsBoolean());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleCheckedDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleCheckedDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleCheckedDataWriter.java
new file mode 100644
index 0000000..376afee
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleCheckedDataWriter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.BooleanSupplier;
+import java.util.function.DoubleSupplier;
+
+public class DoubleCheckedDataWriter extends ReductionCheckedDataWriter<DoubleSupplier> {
+  
+  public DoubleCheckedDataWriter(DataOutput output, DoubleSupplier extractor, BooleanSupplier existsSupplier) {
+    super(output, extractor, existsSupplier);
+  }
+
+  @Override
+  public void checkedWrite() throws IOException {
+    output.writeDouble(extractor.getAsDouble());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleDataArrayWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleDataArrayWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleDataArrayWriter.java
new file mode 100644
index 0000000..830ceee
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleDataArrayWriter.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.DoubleSupplier;
+import java.util.function.IntSupplier;
+
+public class DoubleDataArrayWriter extends ReductionDataArrayWriter<DoubleSupplier> {
+
+  public DoubleDataArrayWriter(DataOutput output, DoubleSupplier extractor, IntSupplier sizeSupplier) {
+    super(output, extractor, sizeSupplier);
+  }
+  
+  @Override
+  public void write(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      output.writeDouble(extractor.getAsDouble());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleDataWriter.java
new file mode 100644
index 0000000..074b859
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/DoubleDataWriter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.DoubleSupplier;
+
+public class DoubleDataWriter extends ReductionDataWriter<DoubleSupplier> {
+  
+  public DoubleDataWriter(DataOutput output, DoubleSupplier extractor) {
+    super(output, extractor);
+  }
+
+  @Override
+  public void write() throws IOException {
+    output.writeDouble(extractor.getAsDouble());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatCheckedDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatCheckedDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatCheckedDataWriter.java
new file mode 100644
index 0000000..69c74b9
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatCheckedDataWriter.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.BooleanSupplier;
+
+import org.apache.solr.analytics.util.function.FloatSupplier;
+
+public class FloatCheckedDataWriter extends ReductionCheckedDataWriter<FloatSupplier> {
+  
+  public FloatCheckedDataWriter(DataOutput output, FloatSupplier extractor, BooleanSupplier existsSupplier) {
+    super(output, extractor, existsSupplier);
+  }
+
+  @Override
+  public void checkedWrite() throws IOException {
+    output.writeFloat(extractor.getAsFloat());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatDataArrayWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatDataArrayWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatDataArrayWriter.java
new file mode 100644
index 0000000..0fd0d25
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatDataArrayWriter.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.IntSupplier;
+
+import org.apache.solr.analytics.util.function.FloatSupplier;
+
+public class FloatDataArrayWriter extends ReductionDataArrayWriter<FloatSupplier> {
+
+  public FloatDataArrayWriter(DataOutput output, FloatSupplier extractor, IntSupplier sizeSupplier) {
+    super(output, extractor, sizeSupplier);
+  }
+  
+  @Override
+  public void write(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      output.writeFloat(extractor.getAsFloat());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatDataWriter.java
new file mode 100644
index 0000000..bc23f21
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/FloatDataWriter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.solr.analytics.util.function.FloatSupplier;
+
+public class FloatDataWriter extends ReductionDataWriter<FloatSupplier> {
+  
+  public FloatDataWriter(DataOutput output, FloatSupplier extractor) {
+    super(output, extractor);
+  }
+
+  @Override
+  public void write() throws IOException {
+    output.writeFloat(extractor.getAsFloat());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntCheckedDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntCheckedDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntCheckedDataWriter.java
new file mode 100644
index 0000000..fd55cf7
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntCheckedDataWriter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.BooleanSupplier;
+import java.util.function.IntSupplier;
+
+public class IntCheckedDataWriter extends ReductionCheckedDataWriter<IntSupplier> {
+  
+  public IntCheckedDataWriter(DataOutput output, IntSupplier extractor, BooleanSupplier existsSupplier) {
+    super(output, extractor, existsSupplier);
+  }
+
+  @Override
+  public void checkedWrite() throws IOException {
+    output.writeInt(extractor.getAsInt());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntDataArrayWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntDataArrayWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntDataArrayWriter.java
new file mode 100644
index 0000000..144b27f
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntDataArrayWriter.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.IntSupplier;
+
+public class IntDataArrayWriter extends ReductionDataArrayWriter<IntSupplier> {
+
+  public IntDataArrayWriter(DataOutput output, IntSupplier extractor, IntSupplier sizeSupplier) {
+    super(output, extractor, sizeSupplier);
+  }
+  
+  @Override
+  public void write(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      output.writeInt(extractor.getAsInt());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntDataWriter.java
new file mode 100644
index 0000000..fd2420a
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/IntDataWriter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.IntSupplier;
+
+public class IntDataWriter extends ReductionDataWriter<IntSupplier> {
+  
+  public IntDataWriter(DataOutput output, IntSupplier extractor) {
+    super(output, extractor);
+  }
+
+  @Override
+  public void write() throws IOException {
+    output.writeInt(extractor.getAsInt());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongCheckedDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongCheckedDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongCheckedDataWriter.java
new file mode 100644
index 0000000..e148e40
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongCheckedDataWriter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.BooleanSupplier;
+import java.util.function.LongSupplier;
+
+public class LongCheckedDataWriter extends ReductionCheckedDataWriter<LongSupplier> {
+  
+  public LongCheckedDataWriter(DataOutput output, LongSupplier extractor, BooleanSupplier existsSupplier) {
+    super(output, extractor, existsSupplier);
+  }
+
+  @Override
+  public void checkedWrite() throws IOException {
+    output.writeLong(extractor.getAsLong());
+  }
+}
\ No newline at end of file


[57/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10818: Fix bug in construct payload with special characters in testCollectionsApi()

Posted by ab...@apache.org.
SOLR-10818: Fix bug in construct payload with special characters in testCollectionsApi()


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

Branch: refs/heads/jira/solr-10879
Commit: d070ca6051bd13e2cee436225139127c7a37f69f
Parents: 20dcb56
Author: Cao Manh Dat <da...@apache.org>
Authored: Mon Jul 3 15:38:05 2017 +0700
Committer: Cao Manh Dat <da...@apache.org>
Committed: Mon Jul 3 15:38:05 2017 +0700

----------------------------------------------------------------------
 .../test/org/apache/solr/handler/V2ApiIntegrationTest.java  | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d070ca60/solr/core/src/test/org/apache/solr/handler/V2ApiIntegrationTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/V2ApiIntegrationTest.java b/solr/core/src/test/org/apache/solr/handler/V2ApiIntegrationTest.java
index 844c960..c2b7459 100644
--- a/solr/core/src/test/org/apache/solr/handler/V2ApiIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/V2ApiIntegrationTest.java
@@ -19,6 +19,7 @@ package org.apache.solr.handler;
 
 
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -138,9 +139,15 @@ public class V2ApiIntegrationTest extends SolrCloudTestCase {
     result = resAsMap(client, new V2Request.Builder("/collections/"+COLL_NAME+"/get/_introspect").build());
     assertEquals("/collections/collection1/get", Utils.getObjectByPath(result, true, "/spec[0]/url/paths[0]"));
     String tempDir = createTempDir().toFile().getPath();
+    Map<String, Object> backupPayload = new HashMap<>();
+    Map<String, Object> backupParams = new HashMap<>();
+    backupPayload.put("backup-collection", backupParams);
+    backupParams.put("name", "backup_test");
+    backupParams.put("collection", COLL_NAME);
+    backupParams.put("location", tempDir);
     client.request(new V2Request.Builder("/c")
         .withMethod(SolrRequest.METHOD.POST)
-        .withPayload("{backup-collection:{name: backup_test, collection: "+COLL_NAME+" , location: '"+tempDir+"' }}")
+        .withPayload(Utils.toJSONString(backupPayload))
         .build());
   }
 


[07/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongDataArrayWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongDataArrayWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongDataArrayWriter.java
new file mode 100644
index 0000000..12fc86e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongDataArrayWriter.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.IntSupplier;
+import java.util.function.LongSupplier;
+
+public class LongDataArrayWriter extends ReductionDataArrayWriter<LongSupplier> {
+
+  public LongDataArrayWriter(DataOutput output, LongSupplier extractor, IntSupplier sizeSupplier) {
+    super(output, extractor, sizeSupplier);
+  }
+  
+  @Override
+  public void write(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      output.writeLong(extractor.getAsLong());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongDataWriter.java
new file mode 100644
index 0000000..3b8af52
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/LongDataWriter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.LongSupplier;
+
+public class LongDataWriter extends ReductionDataWriter<LongSupplier> {
+  
+  public LongDataWriter(DataOutput output, LongSupplier extractor) {
+    super(output, extractor);
+  }
+
+  @Override
+  public void write() throws IOException {
+    output.writeLong(extractor.getAsLong());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionCheckedDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionCheckedDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionCheckedDataWriter.java
new file mode 100644
index 0000000..a5a2273
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionCheckedDataWriter.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.BooleanSupplier;
+
+/**
+ * Abstract class to manage the extraction and writing of data to a {@link DataOutput} stream.
+ * The data being written may not exist, so the writer first writes whether the data exists before writing the data.
+ */
+public abstract class ReductionCheckedDataWriter<C> extends ReductionDataWriter<C> {
+  private final BooleanSupplier existsSupplier;
+  
+  public ReductionCheckedDataWriter(DataOutput output, C extractor, BooleanSupplier existsSupplier) {
+    super(output, extractor);
+    
+    this.existsSupplier = existsSupplier;
+  }
+  
+  /**
+   * Write a piece of data, retrieved from the extractor, to the output stream.
+   * <br>
+   * First writes whether the data exists, then if it does exists writes the data.
+   * 
+   * @throws IOException if an exception occurs while writing to the output stream
+   */
+  @Override
+  public void write() throws IOException {
+    boolean exists = existsSupplier.getAsBoolean();
+    output.writeBoolean(exists);
+    if (exists) {
+      checkedWrite();
+    }
+  }
+  
+  /**
+   * Write a piece of data, retrieved from the extractor, to the output stream.
+   * <br>
+   * The data being written is guaranteed to exist.
+   * 
+   * @throws IOException if an exception occurs while writing to the output stream
+   */
+  protected abstract void checkedWrite() throws IOException;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionDataArrayWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionDataArrayWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionDataArrayWriter.java
new file mode 100644
index 0000000..29ba77e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionDataArrayWriter.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.IntSupplier;
+
+/**
+ * Abstract class to manage the extraction and writing of array data to a {@link DataOutput} stream.
+ */
+public abstract class ReductionDataArrayWriter<C> extends ReductionDataWriter<C> {
+  private final IntSupplier sizeSupplier;
+  
+  public ReductionDataArrayWriter(DataOutput output, C extractor, IntSupplier sizeSupplier) {
+    super(output, extractor);
+    
+    this.sizeSupplier = sizeSupplier;
+  }
+  
+  /**
+   * Write an array of data, retrieved from the extractor, and its size, received from the sizeSupplier, to the output stream.
+   * 
+   * @throws IOException if an exception occurs while writing to the output stream
+   */
+  @Override
+  public void write() throws IOException {
+    int size = sizeSupplier.getAsInt();
+    output.writeInt(size);
+    write(size);
+  }
+  
+  /**
+   * Write an array of data, retrieved from the extractor, with the given size to the output stream.
+   * 
+   * @throws IOException if an exception occurs while writing to the output stream
+   */
+  protected abstract void write(int size) throws IOException;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionDataWriter.java
new file mode 100644
index 0000000..504a2be
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/ReductionDataWriter.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * Abstract public class to manage the extraction and writing of data to a {@link DataOutput} stream.
+ */
+public abstract class ReductionDataWriter<E> {
+  protected final DataOutput output;
+  protected final E extractor;
+  
+  public ReductionDataWriter(DataOutput output, E extractor) {
+    this.output = output;
+    this.extractor = extractor;
+  }
+
+  /**
+   * Write a piece of data, retrieved from the extractor, to the output stream.
+   * 
+   * @throws IOException if an exception occurs while writing to the output stream
+   */
+  public abstract void write() throws IOException;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringCheckedDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringCheckedDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringCheckedDataWriter.java
new file mode 100644
index 0000000..6560a8f
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringCheckedDataWriter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.BooleanSupplier;
+import java.util.function.Supplier;
+
+public class StringCheckedDataWriter extends ReductionCheckedDataWriter<Supplier<String>> {
+  
+  public StringCheckedDataWriter(DataOutput output, Supplier<String> extractor, BooleanSupplier existsSupplier) {
+    super(output, extractor, existsSupplier);
+  }
+
+  @Override
+  public void checkedWrite() throws IOException {
+    output.writeUTF(extractor.get());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringDataArrayWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringDataArrayWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringDataArrayWriter.java
new file mode 100644
index 0000000..18c71d1
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringDataArrayWriter.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+
+public class StringDataArrayWriter extends ReductionDataArrayWriter<Supplier<String>> {
+
+  public StringDataArrayWriter(DataOutput output, Supplier<String> extractor, IntSupplier sizeSupplier) {
+    super(output, extractor, sizeSupplier);
+  }
+  
+  @Override
+  public void write(int size) throws IOException {
+    for (int i = 0; i < size; ++i) {
+      output.writeUTF(extractor.get());
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringDataWriter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringDataWriter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringDataWriter.java
new file mode 100644
index 0000000..4aac07c
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/StringDataWriter.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.function.Supplier;
+
+public class StringDataWriter extends ReductionDataWriter<Supplier<String>> {
+  
+  public StringDataWriter(DataOutput output, Supplier<String> extractor) {
+    super(output, extractor);
+  }
+
+  @Override
+  public void write() throws IOException {
+    String temp = extractor.get();
+    output.writeBoolean(temp != null);
+    if (temp != null) {
+      output.writeUTF(temp);
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/package-info.java
new file mode 100644
index 0000000..53a5168
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/write/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Writing classes for a single type of data being stored by one Reduction Data Collector.
+ * These writers are used to export data between shards during the streaming process.
+ */
+package org.apache.solr.analytics.stream.reservation.write;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParams.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParams.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParams.java
deleted file mode 100644
index f6716ff..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParams.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.solr.common.params.FacetParams.FacetRangeInclude;
-import org.apache.solr.common.params.FacetParams.FacetRangeOther;
-import org.apache.solr.search.function.ConcatStringFunction;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-public interface AnalyticsParams {
-  // Full length Analytics Params
-  public static final String ANALYTICS = "olap";
-  
-  public static final String REQUEST = "o|olap";
-
-  public static final String EXPRESSION = "s|stat|statistic";
-  public static final String HIDDEN_EXPRESSION = "hs|hiddenstat|hiddenstatistic";
-
-  public static final String FIELD_FACET = "ff|fieldfacet";
-  public static final String LIMIT = "l|limit";
-  public static final String OFFSET = "off|offset";
-  public static final String HIDDEN = "h|hidden";
-  public static final String SHOW_MISSING = "sm|showmissing";
-  public static final String SORT_STATISTIC ="ss|sortstat|sortstatistic";
-  public static final String SORT_DIRECTION ="sd|sortdirection";
-  
-  public static final String RANGE_FACET = "rf|rangefacet";
-  public static final String START = "st|start";
-  public static final String END = "e|end";
-  public static final String GAP = "g|gap";
-  public static final String HARDEND = "he|hardend";
-  public static final String INCLUDE_BOUNDARY = "ib|includebound";
-  public static final String OTHER_RANGE = "or|otherrange";
-  
-  public static final String QUERY_FACET = "qf|queryfacet";
-  public static final String DEPENDENCY = "d|dependecy";
-  public static final String QUERY = "q|query";
-  
-  //Defaults
-  public static final boolean DEFAULT_ABBREVIATE_PREFIX = true;
-  public static final String DEFAULT_SORT_DIRECTION = "ascending";
-  public static final int DEFAULT_LIMIT = -1;
-  public static final boolean DEFAULT_HIDDEN = false;
-  public static final boolean DEFAULT_HARDEND = false;
-  public static final boolean DEFAULT_SHOW_MISSING = false;
-  public static final FacetRangeInclude DEFAULT_INCLUDE = FacetRangeInclude.LOWER;
-  public static final FacetRangeOther DEFAULT_OTHER = FacetRangeOther.NONE;
-  
-  // Statistic Function Names (Cannot share names with ValueSource & Expression Functions)
-  public static final String STAT_COUNT = "count";
-  public static final String STAT_MISSING = "missing";
-  public static final String STAT_SUM = "sum";
-  public static final String STAT_SUM_OF_SQUARES = "sumofsquares";
-  public static final String STAT_STANDARD_DEVIATION = "stddev";
-  public static final String STAT_MEAN = "mean";
-  public static final String STAT_UNIQUE = "unique";
-  public static final String STAT_MEDIAN = "median";
-  public static final String STAT_PERCENTILE = "percentile";
-  public static final String STAT_MIN = "min";
-  public static final String STAT_MAX = "max";
-  
-  public static final List<String> ALL_STAT_LIST = Collections.unmodifiableList(Lists.newArrayList(STAT_COUNT, STAT_MISSING, STAT_SUM, STAT_SUM_OF_SQUARES, STAT_STANDARD_DEVIATION, STAT_MEAN, STAT_UNIQUE, STAT_MEDIAN, STAT_PERCENTILE,STAT_MIN,STAT_MAX));
-  public static final Set<String> ALL_STAT_SET = Collections.unmodifiableSet(Sets.newLinkedHashSet(ALL_STAT_LIST));
-
-  // ValueSource & Expression Function Names (Cannot share names with Statistic Functions)
-  // No specific type
-  final static String FILTER = "filter";
-  final static String RESULT = "result";
-  final static String QUERY_RESULT = "qresult";
-  
-  // Numbers
-  final static String CONSTANT_NUMBER = "const_num";
-  final static String NEGATE = "neg";
-  final static String ABSOLUTE_VALUE = "abs";
-  final static String LOG = "log";
-  final static String ADD = "add";
-  final static String MULTIPLY = "mult";
-  final static String DIVIDE = "div";
-  final static String POWER = "pow";
-  public static final Set<String> NUMERIC_OPERATION_SET = Collections.unmodifiableSet(Sets.newLinkedHashSet(Lists.newArrayList(CONSTANT_NUMBER,NEGATE,ABSOLUTE_VALUE,LOG,ADD,MULTIPLY,DIVIDE,POWER)));
-  
-  // Dates
-  final static String CONSTANT_DATE = "const_date";
-  final static String DATE_MATH = "date_math";
-  public static final Set<String> DATE_OPERATION_SET = Collections.unmodifiableSet(Sets.newLinkedHashSet(Lists.newArrayList(CONSTANT_DATE,DATE_MATH)));
-  
-  //Strings
-  final static String CONSTANT_STRING = "const_str";
-  final static String REVERSE = "rev";
-  final static String CONCATENATE = ConcatStringFunction.NAME;
-  public static final Set<String> STRING_OPERATION_SET = Collections.unmodifiableSet(Sets.newLinkedHashSet(Lists.newArrayList(CONSTANT_STRING,REVERSE,CONCATENATE)));
-  
-  // Field Source Wrappers
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParsers.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParsers.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParsers.java
deleted file mode 100644
index dd64c3f..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsParsers.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util;
-
-import java.io.IOException;
-import java.time.Instant;
-import java.util.Arrays;
-
-import org.apache.solr.legacy.LegacyNumericUtils;
-import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.NumericUtils;
-import org.apache.solr.schema.FieldType;
-import org.apache.solr.schema.TrieDateField;
-import org.apache.solr.schema.TrieDoubleField;
-import org.apache.solr.schema.TrieFloatField;
-import org.apache.solr.schema.TrieIntField;
-import org.apache.solr.schema.TrieLongField;
-
-/** 
- * Class to hold the parsers used for Solr Analytics.
- */
-public class AnalyticsParsers {
-
-  /**
-   * Returns a parser that will translate a BytesRef or long from DocValues into 
-   * a String that correctly represents the value.
-   * @param class1 class of the FieldType of the field being faceted on.
-   * @return A Parser
-   */
-  public static Parser getParser(Class<? extends FieldType> class1) {
-    if (class1.equals(TrieIntField.class)) {
-      return AnalyticsParsers.INT_DOC_VALUES_PARSER;
-    } else if (class1.equals(TrieLongField.class)) {
-      return AnalyticsParsers.LONG_DOC_VALUES_PARSER;
-    } else if (class1.equals(TrieFloatField.class)) {
-      return AnalyticsParsers.FLOAT_DOC_VALUES_PARSER;
-    } else if (class1.equals(TrieDoubleField.class)) {
-      return AnalyticsParsers.DOUBLE_DOC_VALUES_PARSER;
-    } else if (class1.equals(TrieDateField.class)) {
-      return AnalyticsParsers.DATE_DOC_VALUES_PARSER;
-    } else {
-      return AnalyticsParsers.STRING_PARSER;
-    }
-  }
-
-  /**
-   * For use in classes that grab values by docValue.
-   * Converts a BytesRef object into the correct readable text.
-   */
-  public static interface Parser {
-    String parse(BytesRef bytes) throws IOException;
-  }
-  
-  /**
-   * Converts the long returned by NumericDocValues into the
-   * correct number and return it as a string.
-   */
-  public static interface NumericParser extends Parser {
-    String parseNum(long l);
-  }
-  
-  /**
-   * Converts the BytesRef or long to the correct int string.
-   */
-  public static final NumericParser INT_DOC_VALUES_PARSER = new NumericParser() {
-    public String parse(BytesRef bytes) throws IOException {
-      try {
-        return ""+ LegacyNumericUtils.prefixCodedToInt(bytes);
-      } catch (NumberFormatException e) {
-        throw new IOException("The byte array "+Arrays.toString(bytes.bytes)+" cannot be converted to an int.");
-      }
-    }
-    @Override
-    public String parseNum(long l) {
-      return ""+(int)l;
-    }
-  };
-  
-  /**
-   * Converts the BytesRef or long to the correct long string.
-   */
-  public static final NumericParser LONG_DOC_VALUES_PARSER = new NumericParser() {
-    public String parse(BytesRef bytes) throws IOException {
-      try {
-        return ""+ LegacyNumericUtils.prefixCodedToLong(bytes);
-      } catch (NumberFormatException e) {
-        throw new IOException("The byte array "+Arrays.toString(bytes.bytes)+" cannot be converted to a long.");
-      }
-    }
-    @Override
-    public String parseNum(long l) {
-      return ""+l;
-    }
-  };
-  
-  /**
-   * Converts the BytesRef or long to the correct float string.
-   */
-  public static final NumericParser FLOAT_DOC_VALUES_PARSER = new NumericParser() {
-    public String parse(BytesRef bytes) throws IOException {
-      try {
-        return ""+ NumericUtils.sortableIntToFloat(LegacyNumericUtils.prefixCodedToInt(bytes));
-      } catch (NumberFormatException e) {
-        throw new IOException("The byte array "+Arrays.toString(bytes.bytes)+" cannot be converted to a float.");
-      }
-    }
-    @Override
-    public String parseNum(long l) {
-      return ""+ NumericUtils.sortableIntToFloat((int) l);
-    }
-  };
-  
-  /**
-   * Converts the BytesRef or long to the correct double string.
-   */
-  public static final NumericParser DOUBLE_DOC_VALUES_PARSER = new NumericParser() {
-    public String parse(BytesRef bytes) throws IOException {
-      try {
-        return ""+ NumericUtils.sortableLongToDouble(LegacyNumericUtils.prefixCodedToLong(bytes));
-      } catch (NumberFormatException e) {
-        throw new IOException("The byte array "+Arrays.toString(bytes.bytes)+" cannot be converted to a double.");
-      }
-    }
-    @Override
-    public String parseNum(long l) {
-      return ""+ NumericUtils.sortableLongToDouble(l);
-    }
-  };
-  
-  /**
-   * Converts the BytesRef or long to the correct date string.
-   */
-  public static final NumericParser DATE_DOC_VALUES_PARSER = new NumericParser() {
-    @SuppressWarnings("deprecation")
-    public String parse(BytesRef bytes) throws IOException {
-      try {
-        return Instant.ofEpochMilli(LegacyNumericUtils.prefixCodedToLong(bytes)).toString();
-      } catch (NumberFormatException e) {
-        throw new IOException("The byte array "+Arrays.toString(bytes.bytes)+" cannot be converted to a date.");
-      }
-    }
-    @SuppressWarnings("deprecation")
-    @Override
-    public String parseNum(long l) {
-      return Instant.ofEpochMilli(l).toString();
-    }
-  };
-  
-  /**
-   * Converts the BytesRef to the correct string.
-   */
-  public static final Parser STRING_PARSER = new Parser() {
-    public String parse(BytesRef bytes) {
-      return bytes.utf8ToString();
-    }
-  };
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsResponseHeadings.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsResponseHeadings.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsResponseHeadings.java
new file mode 100644
index 0000000..00e0afb
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/AnalyticsResponseHeadings.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.util;
+
+/**
+ * Holds the headers for analytics responses.
+ */
+public class AnalyticsResponseHeadings {
+
+  public static final String COMPLETED_HEADER = "analytics_response";
+  public static final String RESULTS = "results";
+  public static final String GROUPINGS = "groupings";
+  public static final String FACET_VALUE = "value";
+  public static final String PIVOT_NAME = "pivot";
+  public static final String PIVOT_CHILDREN = "children";
+  
+  // Old Olap-style
+  public static final String COMPLETED_OLD_HEADER = "stats";
+  public static final String FIELD_FACETS = "fieldFacets";
+  public static final String RANGE_FACETS = "rangeFacets";
+  public static final String QUERY_FACETS = "queryFacets";
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/FacetRangeGenerator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/FacetRangeGenerator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/FacetRangeGenerator.java
new file mode 100644
index 0000000..0576096
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/FacetRangeGenerator.java
@@ -0,0 +1,356 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.util;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.solr.analytics.facet.RangeFacet;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.FacetParams.FacetRangeInclude;
+import org.apache.solr.common.params.FacetParams.FacetRangeOther;
+import org.apache.solr.schema.FieldType;
+import org.apache.solr.schema.SchemaField;
+import org.apache.solr.schema.TrieDateField;
+import org.apache.solr.schema.TrieField;
+import org.apache.solr.util.DateMathParser;
+
+
+/**
+ * Calculates a set of {@link FacetRange}s for a given {@link RangeFacet}.
+ */
+public abstract class FacetRangeGenerator<T extends Comparable<T>> {
+  protected final SchemaField field;
+  protected final RangeFacet rangeFacet;
+  
+  public FacetRangeGenerator(final RangeFacet rangeFacet) {
+    this.field = rangeFacet.getField();
+    this.rangeFacet = rangeFacet;
+  }
+
+  /**
+   * Formats a Range endpoint for use as a range label name in the response.
+   * Default Impl just uses toString()
+   */
+  public String formatValue(final T val) {
+    return val.toString();
+  }
+  
+  /**
+   * Parses a String param into an Range endpoint value throwing 
+   * a useful exception if not possible
+   */
+  public final T getValue(final String rawval) {
+    try {
+      return parseVal(rawval);
+    } catch (Exception e) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can't parse value "+rawval+" for field: " + field.getName(), e);
+    }
+  }
+  
+  /**
+   * Parses a String param into an Range endpoint. 
+   * Can throw a low level format exception as needed.
+   */
+  protected abstract T parseVal(final String rawval) throws java.text.ParseException;
+
+  /** 
+   * Parses a String param into a value that represents the gap and 
+   * can be included in the response, throwing 
+   * a useful exception if not possible.
+   *
+   * Note: uses Object as the return type instead of T for things like 
+   * Date where gap is just a DateMathParser string 
+   */
+  public final Object getGap(final String gap) {
+    try {
+      return parseGap(gap);
+    } catch (Exception e) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can't parse gap "+gap+" for field: " + field.getName(), e);
+    }
+  }
+
+  /**
+   * Parses a String param into a value that represents the gap and 
+   * can be included in the response. 
+   * Can throw a low level format exception as needed.
+   *
+   * Default Impl calls parseVal
+   */
+  protected Object parseGap(final String rawval) throws java.text.ParseException {
+    return parseVal(rawval);
+  }
+
+  /**
+   * Adds the String gap param to a low Range endpoint value to determine 
+   * the corrisponding high Range endpoint value, throwing 
+   * a useful exception if not possible.
+   */
+  public final T addGap(T value, String gap) {
+    try {
+      return parseAndAddGap(value, gap);
+    } catch (Exception e) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can't add gap "+gap+" to value " + value + " for field: " + field.getName(), e);
+    }
+  }
+  
+  /**
+   * Adds the String gap param to a low Range endpoint value to determine 
+   * the corrisponding high Range endpoint value.
+   * Can throw a low level format exception as needed.
+   */
+  protected abstract T parseAndAddGap(T value, String gap) throws java.text.ParseException;
+
+  public static class FacetRange {
+    public final String name;
+    public final String lower;
+    public final String upper;
+    public final boolean includeLower;
+    public final boolean includeUpper;
+    private final String facetValue;
+    
+    public FacetRange(String name, String lower, String upper, boolean includeLower, boolean includeUpper) {
+      this.name = name;
+      this.lower = lower;
+      this.upper = upper;
+      this.includeLower = includeLower;
+      this.includeUpper = includeUpper;
+      
+      String value = "(*";
+      if (lower != null) {
+        value = (includeLower ? "[" : "(") + lower;
+      }
+      value += " TO ";
+      if (upper == null) {
+        value += "*)";
+      } else {
+        value += upper + (includeUpper? "]" : ")");
+      }
+      facetValue = value;
+    }
+    
+    @Override
+    public String toString() {
+        return facetValue;
+    }
+  }
+  
+  public List<FacetRange> getRanges(){
+
+    final T start = getValue(rangeFacet.getStart());
+    T end = getValue(rangeFacet.getEnd()); // not final, hardend may change this
+    
+    if( end.compareTo(start) < 0 ){
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "range facet 'end' comes before 'start': "+end+" < "+start);
+    }
+    
+    // explicitly return the gap.  compute this early so we are more 
+    // likely to catch parse errors before attempting math
+    final List<String> gaps = rangeFacet.getGaps();
+    String gap = gaps.get(0);
+    
+    final EnumSet<FacetRangeInclude> include = rangeFacet.getInclude();
+        
+    T low = start;
+    
+    List<FacetRange> ranges = new ArrayList<>();
+    
+    int gapCounter = 0;
+    
+    while (low.compareTo(end) < 0) {
+      if (gapCounter<gaps.size()) {
+        gap = gaps.get(gapCounter++);
+      }
+      T high = addGap(low,gap);
+      if (end.compareTo(high) < 0) {
+        if (rangeFacet.isHardEnd()){
+          high = end;
+        } else {
+          end = high;
+        }
+      }
+      
+      if (high.compareTo(low) < 0) {
+        throw new SolrException (SolrException.ErrorCode.BAD_REQUEST, "range facet infinite loop (is gap negative? did the math overflow?)");
+      }
+      
+      if (high.compareTo(low) == 0) {
+        throw new SolrException (SolrException.ErrorCode.BAD_REQUEST, "range facet infinite loop: gap is either zero, or too small relative start/end and caused underflow: " + low + " + " + gap + " = " + high );
+      }
+      
+      final boolean includeLower = (include.contains(FacetRangeInclude.ALL) ||
+                                    include.contains(FacetRangeInclude.LOWER) ||
+                                   (include.contains(FacetRangeInclude.EDGE) && 
+                                   0 == low.compareTo(start)));
+      final boolean includeUpper = (include.contains(FacetRangeInclude.ALL) ||
+                                    include.contains(FacetRangeInclude.UPPER) ||
+                                   (include.contains(FacetRangeInclude.EDGE) && 
+                                   0 == high.compareTo(end)));
+      
+      final String lowS = formatValue(low);
+      final String highS = formatValue(high);
+
+      ranges.add( new FacetRange(lowS,lowS,highS,includeLower,includeUpper) );
+      low = high;
+    }
+    
+    final Set<FacetRangeOther> others = rangeFacet.getOthers();
+    if (null != others && 0 < others.size() ) {
+      
+      // no matter what other values are listed, we don't do
+      // anything if "none" is specified.
+      if( !others.contains(FacetRangeOther.NONE) ) {
+        
+        boolean all = others.contains(FacetRangeOther.ALL);
+
+        if (all || others.contains(FacetRangeOther.BEFORE)) {
+          // include upper bound if "outer" or if first gap doesn't already include it
+          ranges.add( new FacetRange(FacetRangeOther.BEFORE.toString(), 
+                                        null, formatValue(start), false, include.contains(FacetRangeInclude.OUTER) || include.contains(FacetRangeInclude.ALL) ||
+                                                            !(include.contains(FacetRangeInclude.LOWER) || include.contains(FacetRangeInclude.EDGE)) ) );
+          
+        }
+        if (all || others.contains(FacetRangeOther.AFTER)) {
+          // include lower bound if "outer" or if last gap doesn't already include it
+          ranges.add( new FacetRange(FacetRangeOther.AFTER.toString(), 
+                                        formatValue(end), null, include.contains(FacetRangeInclude.OUTER) || include.contains(FacetRangeInclude.ALL) ||
+                                                   !(include.contains(FacetRangeInclude.UPPER) || include.contains(FacetRangeInclude.EDGE)), false) );
+        }
+        if (all || others.contains(FacetRangeOther.BETWEEN)) {
+          ranges.add( new FacetRange(FacetRangeOther.BETWEEN.toString(), formatValue(start), formatValue(end),
+                                        include.contains(FacetRangeInclude.LOWER) || include.contains(FacetRangeInclude.EDGE) || include.contains(FacetRangeInclude.ALL),
+                                        include.contains(FacetRangeInclude.UPPER) || include.contains(FacetRangeInclude.EDGE) || include.contains(FacetRangeInclude.ALL)) );
+        }
+      }
+      
+    }
+  
+    return ranges;
+  }
+  
+  public static FacetRangeGenerator<? extends Comparable<?>> create(RangeFacet rangeFacet){
+    final SchemaField sf = rangeFacet.getField();
+    final FieldType ft = sf.getType();
+    final FacetRangeGenerator<?> calc;
+    if (ft instanceof TrieField) {
+      switch (ft.getNumberType()) {
+        case FLOAT:
+          calc = new FloatFacetRangeGenerator(rangeFacet);
+          break;
+        case DOUBLE:
+          calc = new DoubleFacetRangeGenerator(rangeFacet);
+          break;
+        case INTEGER:
+          calc = new IntegerFacetRangeGenerator(rangeFacet);
+          break;
+        case LONG:
+          calc = new LongFacetRangeGenerator(rangeFacet);
+          break;
+        case DATE:
+          calc = new DateFacetRangeGenerator(rangeFacet, null);
+          break;
+        default:
+          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Unable to range facet on tried field of unexpected type:" + sf.getName());
+      }
+    } else {
+      throw new SolrException (SolrException.ErrorCode.BAD_REQUEST, "Unable to range facet on field:" + sf);
+    } 
+    return calc;
+  }
+}
+class IntegerFacetRangeGenerator extends FacetRangeGenerator<Integer> {
+  public IntegerFacetRangeGenerator(final RangeFacet rangeFacet) { super(rangeFacet); }
+
+  @Override
+  protected Integer parseVal(String rawval) {
+    return Integer.valueOf(rawval);
+  }
+  @Override
+  public Integer parseAndAddGap(Integer value, String gap) {
+    return new Integer(value.intValue() + Integer.valueOf(gap).intValue());
+  }
+}
+class LongFacetRangeGenerator extends FacetRangeGenerator<Long> {
+  public LongFacetRangeGenerator(final RangeFacet rangeFacet) { super(rangeFacet); }
+
+  @Override
+  protected Long parseVal(String rawval) {
+    return Long.valueOf(rawval);
+  }
+  @Override
+  public Long parseAndAddGap(Long value, String gap) {
+    return new Long(value.longValue() + Long.valueOf(gap).longValue());
+  }
+}
+
+class FloatFacetRangeGenerator extends FacetRangeGenerator<Float> {
+  public FloatFacetRangeGenerator(final RangeFacet rangeFacet) { super(rangeFacet); }
+
+  @Override
+  protected Float parseVal(String rawval) {
+    return Float.valueOf(rawval);
+  }
+  @Override
+  public Float parseAndAddGap(Float value, String gap) {
+    return new Float(value.floatValue() + Float.valueOf(gap).floatValue());
+  }
+}
+
+class DoubleFacetRangeGenerator extends FacetRangeGenerator<Double> {
+  public DoubleFacetRangeGenerator(final RangeFacet rangeFacet) { super(rangeFacet); }
+
+  @Override
+  protected Double parseVal(String rawval) {
+    return Double.valueOf(rawval);
+  }
+  @Override
+  public Double parseAndAddGap(Double value, String gap) {
+    return new Double(value.doubleValue() + Double.valueOf(gap).doubleValue());
+  }
+}
+class DateFacetRangeGenerator extends FacetRangeGenerator<Date> {
+  private final Date now;
+  public DateFacetRangeGenerator(final RangeFacet rangeFacet, final Date now) { 
+    super(rangeFacet); 
+    this.now = now;
+    if (! (field.getType() instanceof TrieDateField) ) {
+      throw new IllegalArgumentException("SchemaField must use field type extending TrieDateField");
+    }
+  }
+  
+  @Override
+  public String formatValue(Date val) {
+    return val.toInstant().toString();
+  }
+  @Override
+  protected Date parseVal(String rawval) {
+    return DateMathParser.parseMath(now, rawval);
+  }
+  @Override
+  protected Object parseGap(final String rawval) {
+    return rawval;
+  }
+  @Override
+  public Date parseAndAddGap(Date value, String gap) throws java.text.ParseException {
+    final DateMathParser dmp = new DateMathParser();
+    dmp.setNow(value);
+    return dmp.parseMath(gap);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/MedianCalculator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/MedianCalculator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/MedianCalculator.java
index 52935e9..541cff0 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/MedianCalculator.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/MedianCalculator.java
@@ -18,6 +18,10 @@ package org.apache.solr.analytics.util;
 
 import java.util.List;
 
+/**
+ * Only used for testing.
+ * Medians are calculated with the {@link OrdinalCalculator} for actual analytics requests.
+ */
 public class MedianCalculator {
 
   /**

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OldAnalyticsParams.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OldAnalyticsParams.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OldAnalyticsParams.java
new file mode 100644
index 0000000..084d997
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OldAnalyticsParams.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+import org.apache.solr.analytics.AnalyticsRequestParser.AnalyticsExpressionSortRequest;
+import org.apache.solr.analytics.AnalyticsRequestParser.AnalyticsRangeFacetRequest;
+import org.apache.solr.analytics.AnalyticsRequestParser.AnalyticsSortRequest;
+import org.apache.solr.analytics.AnalyticsRequestParser.AnalyticsValueFacetRequest;
+
+/**
+ * Specifies the format of the old olap-style analytics requests.
+ */
+public interface OldAnalyticsParams {
+  // Old request language
+  public static final String OLD_ANALYTICS = "olap";
+
+  public static final String OLD_PREFIX = "o|olap";
+
+  public static final String OLD_EXPRESSION = "s|stat|statistic";
+  
+  public static class OldRequest {
+    public String name;
+    public Map<String,String> expressions = new HashMap<>();
+    public Map<String,OldFieldFacet> fieldFacets = new HashMap<>();
+    public Map<String,OldRangeFacet> rangeFacets = new HashMap<>();
+    public Map<String,OldQueryFacet> queryFacets = new HashMap<>();
+  }
+
+  public static final String FIELD_FACET = "ff|fieldfacet";
+  public static final String VALUE_FACET = "vf|valuefacet";
+  public static final String LIMIT = "l|limit";
+  public static final String OFFSET = "off|offset";
+  public static final String SHOW_MISSING = "sm|showmissing";
+  public static final String SORT_EXPRESSION ="se|sortexpr|sortexpression";
+  public static final String OLAP_SORT_EXPRESSION ="ss|sortstat|sortstatistic";
+  public static final String SORT_DIRECTION ="sd|sortdirection";
+  
+  public static class OldFieldFacet {
+    public String field;
+    public String showMissing;
+    public String limit;
+    public String offset;
+    public String sortExpr;
+    public String sortDir;
+  }
+  
+  public static class FieldFacetParamParser {
+    public static String regexParamList = LIMIT + "|" + OFFSET + "|" + SHOW_MISSING + "|" + OLAP_SORT_EXPRESSION + "|" + SORT_DIRECTION;
+
+    private static Predicate<String> isLimit = Pattern.compile("^" + LIMIT + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isOffset = Pattern.compile("^" + OFFSET + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isShowMissing = Pattern.compile("^" + SHOW_MISSING + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isSortExpr = Pattern.compile("^" + OLAP_SORT_EXPRESSION + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isSortDir = Pattern.compile("^" + SORT_DIRECTION + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    
+    public static void applyParam(AnalyticsValueFacetRequest facet, String param, String value) {
+      if (isLimit.test(param)) {
+        getSort(facet).limit = Integer.parseInt(value);
+      } else if (isOffset.test(param)) {
+        getSort(facet).offset = Integer.parseInt(value);
+      } else if (isShowMissing.test(param)) {
+        facet.expression = "fillmissing(" + facet.expression + ",\"(MISSING)\")";
+      } else if (isSortExpr.test(param)) {
+        AnalyticsSortRequest sort = getSort(facet);
+        AnalyticsExpressionSortRequest criterion;
+        if (sort.criteria.size() == 0) {
+          criterion = new AnalyticsExpressionSortRequest();
+          sort.criteria.add(criterion);
+        } else {
+          criterion = (AnalyticsExpressionSortRequest) sort.criteria.get(0);
+        }
+        criterion.expression = value;
+      } else if (isSortDir.test(param)) {
+        AnalyticsSortRequest sort = getSort(facet);
+        AnalyticsExpressionSortRequest criterion;
+        if (sort.criteria.size() == 0) {
+          criterion = new AnalyticsExpressionSortRequest();
+          sort.criteria.add(criterion);
+        } else {
+          criterion = (AnalyticsExpressionSortRequest) sort.criteria.get(0);
+        }
+        criterion.direction = value;
+      }
+    }
+    
+    public static AnalyticsSortRequest getSort(AnalyticsValueFacetRequest facet) {
+      if (facet.sort == null) {
+        facet.sort = new AnalyticsSortRequest();
+        facet.sort.criteria = new ArrayList<>();
+      }
+      return facet.sort;
+    }
+  }
+  
+  public static final String RANGE_FACET = "rf|rangefacet";
+  public static final String START = "st|start";
+  public static final String END = "e|end";
+  public static final String GAP = "g|gap";
+  public static final String HARDEND = "he|hardend";
+  public static final String INCLUDE_BOUNDARY = "ib|includebound";
+  public static final String OTHER_RANGE = "or|otherrange";
+  
+  public static class OldRangeFacet {
+    public String field;
+    public String start;
+    public String end;
+    public String gaps;
+    public String hardend;
+    public String[] include;
+    public String[] others;
+  }
+  
+  public static class RangeFacetParamParser {
+    public static String regexParamList = START + "|" + END + "|" + GAP + "|" + HARDEND + "|" + INCLUDE_BOUNDARY + "|" + OTHER_RANGE;
+
+    private static Predicate<String> isStart = Pattern.compile("^" + START + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isEnd = Pattern.compile("^" + END + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isGap = Pattern.compile("^" + GAP + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isHardEnd = Pattern.compile("^" + HARDEND + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isTrue = Pattern.compile("^t|true$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isFalse = Pattern.compile("^f|false$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isInclude = Pattern.compile("^" + INCLUDE_BOUNDARY + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    private static Predicate<String> isOther = Pattern.compile("^" + OTHER_RANGE + "$", Pattern.CASE_INSENSITIVE).asPredicate();
+    
+    public static void applyParam(AnalyticsRangeFacetRequest facet, String param, String[] values) {
+      if (isStart.test(param)) {
+        facet.start = values[0];
+      } else if (isEnd.test(param)) {
+        facet.end = values[0];
+      } else if (isGap.test(param)) {
+        facet.gaps = Arrays.asList(values[0].split(","));
+      } else if (isHardEnd.test(param)) {
+        if (isTrue.test(values[0])) {
+          facet.hardend = true;
+        } else if (isFalse.test(values[0])) {
+          facet.hardend = false;
+        }
+      } else if (isInclude.test(param)) {
+        facet.include = Arrays.asList(values);
+      } else if (isOther.test(param)) {
+        facet.others = Arrays.asList(values);
+      }
+    }
+  }
+  
+  public static class OldQueryFacet {
+    public String name;
+    public String[] queries;
+  }
+  
+  public static final String QUERY_FACET = "qf|queryfacet";
+  public static final String QUERY = "q|query";
+  
+  //Defaults
+  public static final boolean DEFAULT_ABBREVIATE_PREFIX = true;
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OldAnalyticsRequestConverter.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OldAnalyticsRequestConverter.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OldAnalyticsRequestConverter.java
new file mode 100644
index 0000000..0124dc8
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OldAnalyticsRequestConverter.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.solr.analytics.AnalyticsRequestParser.AnalyticsGroupingRequest;
+import org.apache.solr.analytics.AnalyticsRequestParser.AnalyticsQueryFacetRequest;
+import org.apache.solr.analytics.AnalyticsRequestParser.AnalyticsRangeFacetRequest;
+import org.apache.solr.analytics.AnalyticsRequestParser.AnalyticsRequest;
+import org.apache.solr.analytics.AnalyticsRequestParser.AnalyticsValueFacetRequest;
+import org.apache.solr.common.params.SolrParams;
+
+/**
+ * Converts Analytics Requests in the old olap-style format to the new format.
+ */
+public class OldAnalyticsRequestConverter implements OldAnalyticsParams {
+  // Old language Parsing
+  private static final Pattern oldExprPattern = 
+      Pattern.compile("^(?:"+OLD_PREFIX+")\\.([^\\.]+)\\.(?:"+OLD_EXPRESSION+")\\.([^\\.]+)$", Pattern.CASE_INSENSITIVE);
+  private static final Pattern oldFieldFacetPattern = 
+      Pattern.compile("^(?:"+OLD_PREFIX+")\\.([^\\.]+)\\.(?:"+FIELD_FACET+")$", Pattern.CASE_INSENSITIVE);
+  private static final Pattern oldFieldFacetParamPattern = 
+      Pattern.compile("^(?:"+OLD_PREFIX+")\\.([^\\.]+)\\.(?:"+FIELD_FACET+")\\.([^\\.]+)\\.("+FieldFacetParamParser.regexParamList+")$", Pattern.CASE_INSENSITIVE);
+  private static final Pattern oldRangeFacetParamPattern =
+      Pattern.compile("^(?:"+OLD_PREFIX+")\\.([^\\.]+)\\.(?:"+RANGE_FACET+")\\.([^\\.]+)\\.("+RangeFacetParamParser.regexParamList+")$", Pattern.CASE_INSENSITIVE);
+  private static final Pattern oldQueryFacetParamPattern = 
+      Pattern.compile("^(?:"+OLD_PREFIX+")\\.([^\\.]+)\\.(?:"+QUERY_FACET+")\\.([^\\.]+)\\.("+QUERY+")$", Pattern.CASE_INSENSITIVE);
+  
+  /**
+   * Convert the old olap-style Analytics Request in the given params to
+   * an analytics request string using the current format.
+   * 
+   * @param params to find the analytics request in
+   * @return an analytics request string
+   */
+  public static AnalyticsRequest convert(SolrParams params) {
+    AnalyticsRequest request = new AnalyticsRequest();
+    request.expressions = new HashMap<>();
+    request.groupings = new HashMap<>();
+    Iterator<String> paramsIterator = params.getParameterNamesIterator();
+    while (paramsIterator.hasNext()) {
+      String param = paramsIterator.next();
+      CharSequence paramSequence = param.subSequence(0, param.length());
+      parseParam(request, param, paramSequence, params);
+    }
+    return request;
+  }
+  
+  private static void parseParam(AnalyticsRequest request, String param, CharSequence paramSequence, SolrParams params) {
+    // Check if grouped expression
+    Matcher m = oldExprPattern.matcher(paramSequence);
+    if (m.matches()) {
+      addExpression(request,m.group(1),m.group(2),params.get(param));
+      return;
+    }
+    
+    // Check if field facet parameter
+    m = oldFieldFacetPattern.matcher(paramSequence);
+    if (m.matches()) {
+      addFieldFacets(request,m.group(1),params.getParams(param));
+      return;
+    }
+    
+    // Check if field facet parameter
+    m = oldFieldFacetParamPattern.matcher(paramSequence);
+    if (m.matches()) {
+      setFieldFacetParam(request,m.group(1),m.group(2),m.group(3),params.getParams(param));
+      return;
+    }
+    
+    // Check if field facet parameter
+    m = oldFieldFacetParamPattern.matcher(paramSequence);
+    if (m.matches()) {
+      setFieldFacetParam(request,m.group(1),m.group(2),m.group(3),params.getParams(param));
+      return;
+    }
+
+    // Check if range facet parameter
+    m = oldRangeFacetParamPattern.matcher(paramSequence);
+    if (m.matches()) {
+      setRangeFacetParam(request,m.group(1),m.group(2),m.group(3),params.getParams(param));
+      return;
+    }
+
+    // Check if query
+    m = oldQueryFacetParamPattern.matcher(paramSequence);
+    if (m.matches()) {
+      setQueryFacetParam(request,m.group(1),m.group(2),m.group(3),params.getParams(param));
+      return;
+    } 
+  }
+  
+  private static AnalyticsGroupingRequest getGrouping(AnalyticsRequest request, String name) {
+    AnalyticsGroupingRequest grouping = request.groupings.get(name);
+    if (grouping == null) {
+      grouping = new AnalyticsGroupingRequest();
+      grouping.expressions = new HashMap<>();
+      grouping.facets = new HashMap<>();
+      request.groupings.put(name, grouping);
+    }
+    return grouping;
+  }
+
+  private static void addFieldFacets(AnalyticsRequest request, String groupingName, String[] params) {
+    AnalyticsGroupingRequest grouping = getGrouping(request, groupingName);
+    
+    for (String param : params) {
+      if (!grouping.facets.containsKey(param)) {
+        AnalyticsValueFacetRequest fieldFacet = new AnalyticsValueFacetRequest();
+        fieldFacet.expression = param;
+        grouping.facets.put(param, fieldFacet);
+      }
+    }
+  }
+
+  private static void setFieldFacetParam(AnalyticsRequest request, String groupingName, String field, String paramType, String[] params) {
+    AnalyticsGroupingRequest grouping = getGrouping(request, groupingName);
+    
+    AnalyticsValueFacetRequest fieldFacet = (AnalyticsValueFacetRequest) grouping.facets.get(field);
+    
+    if (fieldFacet == null) {
+      fieldFacet = new AnalyticsValueFacetRequest();
+      fieldFacet.expression = field;
+      grouping.facets.put(field, fieldFacet);
+    }
+    FieldFacetParamParser.applyParam(fieldFacet, paramType, params[0]);
+  }
+
+  private static void setRangeFacetParam(AnalyticsRequest request, String groupingName, String field, String paramType, String[] params) {
+    AnalyticsGroupingRequest grouping = getGrouping(request, groupingName);
+    
+    AnalyticsRangeFacetRequest rangeFacet = (AnalyticsRangeFacetRequest) grouping.facets.get(field);
+    if (rangeFacet == null) {
+      rangeFacet = new AnalyticsRangeFacetRequest();
+      rangeFacet.field = field;
+      grouping.facets.put(field, rangeFacet);
+    }
+    RangeFacetParamParser.applyParam(rangeFacet, paramType, params);
+  }
+
+  private static void setQueryFacetParam(AnalyticsRequest request, String groupingName, String facetName, String paramType, String[] params) {
+    AnalyticsGroupingRequest grouping = getGrouping(request, groupingName);
+    
+    AnalyticsQueryFacetRequest queryFacet = new AnalyticsQueryFacetRequest();
+    queryFacet.queries = new HashMap<>();
+    if (paramType.equals("query")||paramType.equals("q")) {
+      for (String param : params) {
+        queryFacet.queries.put(param, param);
+      }
+    }
+    grouping.facets.put(facetName, queryFacet);
+  }
+
+  private static void addExpression(AnalyticsRequest request, String groupingName, String expressionName, String expression) {
+    request.expressions.put(groupingName + expressionName, expression);
+    
+    getGrouping(request, groupingName).expressions.put(expressionName, expression);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OrdinalCalculator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OrdinalCalculator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OrdinalCalculator.java
new file mode 100644
index 0000000..e484e7c
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/OrdinalCalculator.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.util;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Calculates ordinals of a comparable list by placing them in the correct positions in the list.
+ * <p>
+ * Implements the QuickSelect algorithm, but modifies it to select multiple ordinals all at once.
+ */
+public class OrdinalCalculator {
+  /**
+   * Calculates a set of ordinal values for a given list of comparable objects.
+   * Once the method returns, the each ordinal is guaranteed to have the correct value in the list.
+   *
+   * @param list the list of {@link Comparable} objects
+   * @param ordinals the collection ordinals to calculate (0 to (size of list) - 1) 
+   */
+  public static <T extends Comparable<T>> void putOrdinalsInPosition(List<T> list, Collection<Integer> ordinals) {
+    int size = list.size();
+    if (size == 0) {
+      return;
+    }
+
+    int[] ords = new int[ordinals.size()];
+    int i = 0;
+    for (int ord : ordinals) {
+      ords[i++] = ord;
+    }
+    Arrays.sort(ords);
+
+    if (ords[0] < 0 || ords[ords.length - 1] > size - 1) {
+      throw new IllegalArgumentException();
+    }
+    distributeAndFind(list, ords, 0, ords.length - 1);
+  }
+
+  private static <T extends Comparable<T>> void distributeAndFind(List<T> list, int[] ordinals, int beginIdx, int endIdx) {
+    if (endIdx < beginIdx) {
+      return;
+    }
+    int middleIdxb = beginIdx;
+    int middleIdxe = beginIdx;
+    int begin = (beginIdx == 0) ? -1 : ordinals[beginIdx - 1];
+    int end = (endIdx == ordinals.length - 1) ? list.size() : ordinals[endIdx + 1];
+    double middle = (begin + end) / 2.0;
+    for (int i = beginIdx; i <= endIdx; i++) {
+      double value = Math.abs(ordinals[i] - middle) - Math.abs(ordinals[middleIdxb] - middle);
+      if (ordinals[i] == ordinals[middleIdxb]) {
+        middleIdxe = i;
+      } else if (value < 0) {
+        middleIdxb = i;
+        do {
+          middleIdxe = i;
+          i++;
+        } while (i <= endIdx && ordinals[middleIdxb] == ordinals[i]);
+        break;
+      }
+    }
+
+    int middlePlace = ordinals[middleIdxb];
+    int beginPlace = begin + 1;
+    int endPlace = end - 1;
+
+    select(list, middlePlace, beginPlace, endPlace);
+    distributeAndFind(list, ordinals, beginIdx, middleIdxb - 1);
+    distributeAndFind(list, ordinals, middleIdxe + 1, endIdx);
+  }
+
+  private static <T extends Comparable<T>> void select(List<T> list, int place, int begin, int end) {
+    T split;
+    if (end - begin < 10) {
+      split = list.get((int) (Math.random() * (end - begin + 1)) + begin);
+    } else {
+      split = split(list, begin, end);
+    }
+
+    Point result = partition(list, begin, end, split);
+
+    if (place <= result.low) {
+      select(list, place, begin, result.low);
+    } else if (place >= result.high) {
+      select(list, place, result.high, end);
+    }
+  }
+
+  private static <T extends Comparable<T>> T split(List<T> list, int begin, int end) {
+    T temp;
+    int num = (end - begin + 1);
+    int recursiveSize = (int) Math.sqrt((double) num);
+    int step = num / recursiveSize;
+    for (int i = 1; i < recursiveSize; i++) {
+      int swapFrom = i * step + begin;
+      int swapTo = i + begin;
+      temp = list.get(swapFrom);
+      list.set(swapFrom, list.get(swapTo));
+      list.set(swapTo, temp);
+    }
+    recursiveSize--;
+    select(list, recursiveSize / 2 + begin, begin, recursiveSize + begin);
+    return list.get(recursiveSize / 2 + begin);
+  }
+
+  private static <T extends Comparable<T>> Point partition(List<T> list, int begin, int end, T indexElement) {
+    T temp;
+    int left, right;
+    for (left = begin, right = end; left <= right; left++, right--) {
+      while (list.get(left).compareTo(indexElement) < 0) {
+        left++;
+      }
+      while (right != begin - 1 && list.get(right).compareTo(indexElement) >= 0) {
+        right--;
+      }
+      if (right <= left) {
+        left--;
+        right++;
+        break;
+      }
+      temp = list.get(left);
+      list.set(left, list.get(right));
+      list.set(right, temp);
+    }
+    while (left > begin - 1 && list.get(left).compareTo(indexElement) >= 0) {
+      left--;
+    }
+    while (right < end + 1 && list.get(right).compareTo(indexElement) <= 0) {
+      right++;
+    }
+    int rightMove = right + 1;
+    while (rightMove < end + 1) {
+      if (list.get(rightMove).equals(indexElement)) {
+        temp = list.get(rightMove);
+        list.set(rightMove, list.get(right));
+        list.set(right, temp);
+        do {
+          right++;
+        } while (list.get(right).equals(indexElement));
+        if (rightMove <= right) {
+          rightMove = right;
+        }
+      }
+      rightMove++;
+    }
+    return new Point(left, right);
+  }
+}
+
+class Point {
+  public int low;
+  public int high;
+
+  public Point(int low, int high) {
+    this.low = low;
+    this.high = high;
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/PercentileCalculator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/PercentileCalculator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/PercentileCalculator.java
deleted file mode 100644
index 4ae5cc0..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/PercentileCalculator.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class PercentileCalculator {
-  /**
-   * Calculates a list of percentile values for a given list of objects and percentiles.
-   *
-   * @param list     The list of {@link Comparable} objects to calculate the percentiles of.
-   * @param percents The array of percentiles (.01 to .99) to calculate.
-   * @return a list of comparables
-   */
-  public static <T extends Comparable<T>> List<T> getPercentiles(List<T> list, double[] percents) {
-    int size = list.size();
-    if (size == 0) {
-      return null;
-    }
-
-    int[] percs = new int[percents.length];
-    for (int i = 0; i < percs.length; i++) {
-      percs[i] = (int) Math.round(percents[i] * size - .5);
-    }
-    int[] percentiles = Arrays.copyOf(percs, percs.length);
-    Arrays.sort(percentiles);
-
-    if (percentiles[0] < 0 || percentiles[percentiles.length - 1] > size - 1) {
-      throw new IllegalArgumentException();
-    }
-
-    List<T> results = new ArrayList<>(percs.length);
-
-    distributeAndFind(list, percentiles, 0, percentiles.length - 1);
-
-    for (int i = 0; i < percs.length; i++) {
-      results.add(list.get(percs[i]));
-    }
-    return results;
-  }
-
-  private static <T extends Comparable<T>> void distributeAndFind(List<T> list, int[] percentiles, int beginIdx, int endIdx) {
-    if (endIdx < beginIdx) {
-      return;
-    }
-    int middleIdxb = beginIdx;
-    int middleIdxe = beginIdx;
-    int begin = (beginIdx == 0) ? -1 : percentiles[beginIdx - 1];
-    int end = (endIdx == percentiles.length - 1) ? list.size() : percentiles[endIdx + 1];
-    double middle = (begin + end) / 2.0;
-    for (int i = beginIdx; i <= endIdx; i++) {
-      double value = Math.abs(percentiles[i] - middle) - Math.abs(percentiles[middleIdxb] - middle);
-      if (percentiles[i] == percentiles[middleIdxb]) {
-        middleIdxe = i;
-      } else if (value < 0) {
-        middleIdxb = i;
-        do {
-          middleIdxe = i;
-          i++;
-        } while (i <= endIdx && percentiles[middleIdxb] == percentiles[i]);
-        break;
-      }
-    }
-
-    int middlePlace = percentiles[middleIdxb];
-    int beginPlace = begin + 1;
-    int endPlace = end - 1;
-
-    select(list, middlePlace, beginPlace, endPlace);
-    distributeAndFind(list, percentiles, beginIdx, middleIdxb - 1);
-    distributeAndFind(list, percentiles, middleIdxe + 1, endIdx);
-  }
-
-  private static <T extends Comparable<T>> void select(List<T> list, int place, int begin, int end) {
-    T split;
-    if (end - begin < 10) {
-      split = list.get((int) (Math.random() * (end - begin + 1)) + begin);
-    } else {
-      split = split(list, begin, end);
-    }
-
-    Point result = partition(list, begin, end, split);
-
-    if (place <= result.low) {
-      select(list, place, begin, result.low);
-    } else if (place >= result.high) {
-      select(list, place, result.high, end);
-    }
-  }
-
-  private static <T extends Comparable<T>> T split(List<T> list, int begin, int end) {
-    T temp;
-    int num = (end - begin + 1);
-    int recursiveSize = (int) Math.sqrt((double) num);
-    int step = num / recursiveSize;
-    for (int i = 1; i < recursiveSize; i++) {
-      int swapFrom = i * step + begin;
-      int swapTo = i + begin;
-      temp = list.get(swapFrom);
-      list.set(swapFrom, list.get(swapTo));
-      list.set(swapTo, temp);
-    }
-    recursiveSize--;
-    select(list, recursiveSize / 2 + begin, begin, recursiveSize + begin);
-    return list.get(recursiveSize / 2 + begin);
-  }
-
-  private static <T extends Comparable<T>> Point partition(List<T> list, int begin, int end, T indexElement) {
-    T temp;
-    int left, right;
-    for (left = begin, right = end; left <= right; left++, right--) {
-      while (list.get(left).compareTo(indexElement) < 0) {
-        left++;
-      }
-      while (right != begin - 1 && list.get(right).compareTo(indexElement) >= 0) {
-        right--;
-      }
-      if (right <= left) {
-        left--;
-        right++;
-        break;
-      }
-      temp = list.get(left);
-      list.set(left, list.get(right));
-      list.set(right, temp);
-    }
-    while (left > begin - 1 && list.get(left).compareTo(indexElement) >= 0) {
-      left--;
-    }
-    while (right < end + 1 && list.get(right).compareTo(indexElement) <= 0) {
-      right++;
-    }
-    int rightMove = right + 1;
-    while (rightMove < end + 1) {
-      if (list.get(rightMove).equals(indexElement)) {
-        temp = list.get(rightMove);
-        list.set(rightMove, list.get(right));
-        list.set(right, temp);
-        do {
-          right++;
-        } while (list.get(right).equals(indexElement));
-        if (rightMove <= right) {
-          rightMove = right;
-        }
-      }
-      rightMove++;
-    }
-    return new Point(left, right);
-  }
-}
-
-class Point {
-  public int low;
-  public int high;
-
-  public Point(int low, int high) {
-    this.low = low;
-    this.high = high;
-  }
-}


[17/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ConstantComparator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ConstantComparator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ConstantComparator.java
new file mode 100644
index 0000000..ece09f8
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ConstantComparator.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet.compare;
+
+import org.apache.solr.analytics.facet.SortableFacet.FacetBucket;
+
+/**
+ * A results comparator that compares constants.
+ */
+public class ConstantComparator extends FacetResultsComparator {
+
+  @Override
+  public int compare(FacetBucket b1, FacetBucket b2) {
+      return 0;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/DelegatingComparator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/DelegatingComparator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/DelegatingComparator.java
new file mode 100644
index 0000000..200e68b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/DelegatingComparator.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet.compare;
+
+import java.util.Collection;
+
+import org.apache.solr.analytics.facet.SortableFacet.FacetBucket;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A comparator used to sort the facet-value buckets of facet, using the delegate comparator if two values are equal.
+ */
+public class DelegatingComparator extends FacetResultsComparator {
+  private final Iterable<FacetResultsComparator> comparators;
+  
+  /**
+   * Create a delegating results comparator. This comparator will in succession use the given comparators, continuing if the values are equal.
+   * Two buckets are considered equal if and only if all comparators find them equal
+   * 
+   * @param comparators the comparators to use in succession
+   */
+  private DelegatingComparator(Iterable<FacetResultsComparator> comparators) {
+    this.comparators = comparators;
+  }
+  
+  public static FacetResultsComparator joinComparators(Collection<FacetResultsComparator> comparators) throws SolrException {
+    if (comparators.size() == 0) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"A sort must have at least 1 comparator criteria.");
+    } else if (comparators.size() == 1) {
+      return comparators.iterator().next();
+    } else {
+      return new DelegatingComparator(comparators);
+    }
+  }
+
+  @Override
+  public int compare(FacetBucket b1, FacetBucket b2) {
+    int val = 0;
+    for (FacetResultsComparator comparator : comparators) {
+      val = comparator.compare(b1, b2);
+      if (val != 0) {
+        break;
+      }
+    }
+    return val;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ExpressionComparator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ExpressionComparator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ExpressionComparator.java
new file mode 100644
index 0000000..e4c1940
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/ExpressionComparator.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet.compare;
+
+import org.apache.solr.analytics.facet.SortableFacet.FacetBucket;
+
+/**
+ * A comparator used to sort the facet-value buckets of facet.
+ */
+public class ExpressionComparator<T extends Comparable<T>> extends FacetResultsComparator {
+  private final String expression;
+  
+  /**
+   * Create an entry comparator comparing the given expression.
+   * 
+   * @param expression the name of the expression results to compare
+   */
+  public ExpressionComparator(String expression) {
+    this.expression = expression;
+  }
+  
+  @SuppressWarnings("unchecked")
+  public int compare(FacetBucket b1, FacetBucket b2) {
+    T t1 = (T)b1.getResult(expression);
+    T t2 = (T)b2.getResult(expression);
+    if (t1 == null || t2 == null) {
+      return Boolean.compare(t2 == null, t1 == null) * resultMult;
+    } else {
+      return t1.compareTo(t2) * resultMult;
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetResultsComparator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetResultsComparator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetResultsComparator.java
new file mode 100644
index 0000000..9303f21
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetResultsComparator.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet.compare;
+
+import java.util.Comparator;
+
+import org.apache.solr.analytics.facet.SortableFacet.FacetBucket;
+
+/**
+ * A comparator used to sort the buckets of facet.
+ */
+public abstract class FacetResultsComparator implements Comparator<FacetBucket> {
+  protected int resultMult;
+  
+  /**
+   * Create a results comparator assuming an ascending ordering.
+   */
+  public FacetResultsComparator() {
+    setDirection(true);
+  }
+  
+  /**
+   * Set the order direction for comparison.
+   * 
+   * @param ascending whether to compare using an ascending ordering
+   */
+  public void setDirection(boolean ascending) {
+    this.resultMult = ascending ? 1 : -1;
+  }
+  
+  /**
+   * Compare one facet bucket to another.
+   * 
+   * @param b1 the first bucket to compare
+   * @param b2 the second bucket to compare
+   */
+  public abstract int compare(FacetBucket b1, FacetBucket b2);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetValueComparator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetValueComparator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetValueComparator.java
new file mode 100644
index 0000000..a07ac7b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/FacetValueComparator.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.facet.compare;
+
+import org.apache.solr.analytics.facet.SortableFacet.FacetBucket;
+
+/**
+ * A results comparator that compares the name of facet value buckets, which is the string value of the facet value.
+ */
+public class FacetValueComparator extends FacetResultsComparator {
+  
+  /**
+   * Create a facet value comparator.
+   */
+  public FacetValueComparator() {
+    super();
+  }
+  
+  @Override
+  public int compare(FacetBucket b1, FacetBucket b2) {
+      return b1.getFacetValue().compareTo(b2.getFacetValue()) * resultMult;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/package-info.java
new file mode 100644
index 0000000..c86ad17
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/compare/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Comparators used to sort the buckets of an analytics facet.
+ */
+package org.apache.solr.analytics.facet.compare;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/package-info.java
new file mode 100644
index 0000000..5812e54
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/facet/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Facets supported by the analytics component.
+ */
+package org.apache.solr.analytics.facet;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ExpressionCalculator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ExpressionCalculator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ExpressionCalculator.java
new file mode 100644
index 0000000..3c44555
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ExpressionCalculator.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.solr.analytics.AnalyticsExpression;
+import org.apache.solr.analytics.function.ReductionCollectionManager.ReductionDataCollection;
+import org.apache.solr.analytics.util.AnalyticsResponseHeadings;
+import org.apache.solr.common.util.NamedList;
+
+/**
+ * A class used to generate results for a list of {@link AnalyticsExpression}s.
+ */
+public class ExpressionCalculator {
+  private final Iterable<AnalyticsExpression> expressions;
+
+  public ExpressionCalculator(Iterable<AnalyticsExpression> expressions) {
+    this.expressions = expressions;
+  }
+
+  /**
+   * Calculate results for the list of {@link AnalyticsExpression}s.
+   * <p>
+   * NOTE: This method can, and is, called multiple times to generate different responses. 
+   * <br>
+   * The results are determined by which {@link ReductionDataCollection} is passed to the {@link ReductionCollectionManager#setData}
+   * method of the {@link ReductionCollectionManager} managing the reduction for the list of {@link AnalyticsExpression}s.
+   * 
+   * @return a {@link NamedList} containing the results
+   */
+  public Map<String,Object> getResults() {
+    Map<String,Object> exprVals = new HashMap<>();
+    expressions.forEach(expr -> {
+      Object obj = expr.toObject();
+      if (expr.exists()) {
+        exprVals.put(expr.getName(), obj);
+      }
+    });
+    return exprVals;
+  }
+
+  /**
+   * Calculate results for the list of {@link AnalyticsExpression}s and add them to the given response.
+   * <p>
+   * NOTE: This method can, and is, called multiple times to generate different responses. 
+   * <br>
+   * The results are determined by which {@link ReductionDataCollection} is passed to the {@link ReductionCollectionManager#setData}
+   * method of the {@link ReductionCollectionManager} managing the reduction for the list of {@link AnalyticsExpression}s.
+   * 
+   * @param response the response to add the results map to.
+   */
+  public void addResults(Map<String,Object> response) {
+    response.put(AnalyticsResponseHeadings.RESULTS, getResults());
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/MergingReductionCollectionManager.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/MergingReductionCollectionManager.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/MergingReductionCollectionManager.java
new file mode 100644
index 0000000..1402a76
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/MergingReductionCollectionManager.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function;
+
+import org.apache.solr.analytics.function.field.AnalyticsField;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+
+/**
+ * The {@link ReductionCollectionManager} used for distributed requests.
+ */
+public class MergingReductionCollectionManager extends ReductionCollectionManager {
+  
+  public MergingReductionCollectionManager() {
+    super();
+  }
+  
+  public MergingReductionCollectionManager(final ReductionDataCollector<?>[] reductionDataCollectors, final Iterable<AnalyticsField> fields) {
+    super(reductionDataCollectors, fields);
+  }
+  
+  @Override
+  protected ReductionCollectionManager createNewManager(final ReductionDataCollector<?>[] reductionDataCollectors, final Iterable<AnalyticsField> fields) {
+    return new MergingReductionCollectionManager(reductionDataCollectors,fields);
+  }
+  
+  @Override
+  public void setData(ReductionDataCollection dataCollection) {
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      reductionDataCollectors[i].setMergedData(dataCollection.dataArr[i]);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionCollectionManager.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionCollectionManager.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionCollectionManager.java
new file mode 100644
index 0000000..b3a178c
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionCollectionManager.java
@@ -0,0 +1,320 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.solr.analytics.function.field.AnalyticsField;
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.stream.reservation.ReductionDataReservation;
+import org.apache.solr.analytics.stream.reservation.read.ReductionDataReader;
+import org.apache.solr.analytics.stream.reservation.write.ReductionDataWriter;
+import org.apache.solr.analytics.value.AnalyticsValue;
+
+/**
+ * The manager of reduction collection.
+ * Contains a group of {@link ReductionDataCollector}s which will be updated together.
+ * <p>
+ * The manager assumes a non-distributed request. {@link MergingReductionCollectionManager} is used for distributed requests.
+ */
+public class ReductionCollectionManager {
+  protected final ReductionDataCollector<?>[] reductionDataCollectors;
+  private final List<ReductionDataReservation<?,?>> reservations;
+
+  private final List<ReductionDataReader<?>> readers;
+  private final List<ReductionDataWriter<?>> writers;
+  
+  private final Iterable<AnalyticsField> fields;
+  
+  public ReductionCollectionManager() {
+    this(new ReductionDataCollector<?>[0], new ArrayList<>(0));
+  }
+  
+  /**
+   * Create a Manager to oversee the given {@link ReductionDataCollector}s.
+   * 
+   * @param reductionDataCollectors array of collectors that are collecting over the same set of data
+   * @param fields all fields used by the given collectors
+   */
+  public ReductionCollectionManager(final ReductionDataCollector<?>[] reductionDataCollectors, final Iterable<AnalyticsField> fields) {
+    this.reductionDataCollectors = reductionDataCollectors;
+    Arrays.sort(reductionDataCollectors, (a,b) -> a.getExpressionStr().compareTo(b.getExpressionStr()));
+    
+    reservations = new LinkedList<>();
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      reductionDataCollectors[i].submitReservations(reservation -> reservations.add(reservation));
+    }
+    
+    this.fields = fields;
+    
+    this.readers = new ArrayList<>();
+    this.writers = new ArrayList<>();
+  }
+  
+  /**
+   * Return whether or not the manager needs collection done, which is false if no collectors are 
+   * being managed and true if at least one is.
+   * 
+   * @return true if at least one collector is being managed
+   */
+  public boolean needsCollection() {
+    return reductionDataCollectors.length > 0;
+  }
+  
+  /**
+   * Merge this collection manager with others.
+   *
+   * @param reductionManagers the collection managers to merge with
+   * @return a collection manager that manages the union of data collectors from this class and the given managers
+   */
+  public ReductionCollectionManager merge(Iterable<ReductionCollectionManager> reductionManagers) {
+    HashMap<String,ReductionDataCollector<?>> mergedCollectors = new HashMap<>();
+    HashMap<String,AnalyticsField> mergedFields = new HashMap<>();
+    
+    for (ReductionDataCollector<?> collector : reductionDataCollectors) {
+      mergedCollectors.put(collector.getExpressionStr(), collector);
+    }
+    fields.forEach( field -> mergedFields.put(field.getExpressionStr(), field) );
+    
+    reductionManagers.forEach( manager -> {
+      for (ReductionDataCollector<?> collector : manager.reductionDataCollectors) {
+        mergedCollectors.put(collector.getExpressionStr(), collector);
+      }
+      manager.fields.forEach( field -> mergedFields.put(field.getExpressionStr(), field) );
+    });
+    ReductionDataCollector<?>[] collectors = new ReductionDataCollector<?>[mergedCollectors.size()];
+    mergedCollectors.values().toArray(collectors);
+    return createNewManager(collectors, mergedFields.values());
+  }
+  
+  /**
+   * Create an {@link ReductionCollectionManager} to manage the given collectors and fields.
+   * 
+   * @param reductionDataCollectors Reduction collectors
+   * @param fields fields used by the reductions
+   * @return a collection manager
+   */
+  protected ReductionCollectionManager createNewManager(final ReductionDataCollector<?>[] reductionDataCollectors, final Iterable<AnalyticsField> fields) {
+    return new ReductionCollectionManager(reductionDataCollectors,fields);
+  }
+  
+  /**
+   * Get the {@link AnalyticsField}s used in the managed expressions.
+   * 
+   * @return the fields used
+   */
+  public Iterable<AnalyticsField> getUsedFields() {
+    return fields;
+  }
+  
+  /**
+   * Set the context of the readers of the used {@link AnalyticsField}s.
+   * 
+   * @param context the reader context
+   * @throws IOException if an error occurs while setting the fields' context
+   */
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    for (AnalyticsField field : fields) {
+      field.doSetNextReader(context);
+    }
+  }
+  
+  /**
+   * Collect the values from the used {@link AnalyticsField}s.
+   * 
+   * @param doc the document to collect values for
+   * @throws IOException if an error occurs during field collection
+   */
+  public void collect(int doc) throws IOException {
+    for (AnalyticsField field : fields) {
+      field.collect(doc);
+    }
+  }
+  
+  /**
+   * Add a {@link ReductionDataCollection} to target while collecting documents.
+   * This target is valid until the lasting targets are cleared.
+   * 
+   * @param target data collection to add document data too
+   */
+  public void addLastingCollectTarget(ReductionDataCollection target) {
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      reductionDataCollectors[i].addLastingCollectTarget(target.dataArr[i]);
+    }
+  }
+  /**
+   * Clear lasting collection targets.
+   */
+  public void clearLastingCollectTargets() {
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      reductionDataCollectors[i].clearLastingCollectTargets();
+    }
+  }
+  
+  /**
+   * Add a new {@link ReductionDataCollection} to target while collecting the next document.
+   * This target is only valid for the next {@link #apply()} call.
+   * 
+   * @return the new data collection being targeted
+   */
+  public ReductionDataCollection newDataCollectionTarget() {
+    ReductionDataCollection newCol = new ReductionDataCollection();
+    newCol.dataArr = new ReductionData[reductionDataCollectors.length];
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      newCol.dataArr[i] = reductionDataCollectors[i].newDataTarget();
+    }
+    return newCol;
+  }
+  /**
+   * Add a {@link ReductionDataCollection} to target while collecting the next document.
+   * This target is only valid for the next {@link #apply()} call.
+   * 
+   * @param target data collection to add document data too
+   */
+  public void addCollectTarget(ReductionDataCollection target) {
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      reductionDataCollectors[i].addCollectTarget(target.dataArr[i]);
+    }
+  }
+  
+  /**
+   * Apply the values of the collected fields through the expressions' logic to the managed data collectors.
+   * This is called after {@link #collect(int)} has been called and the collection targets have been added.
+   */
+  public void apply() {
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      reductionDataCollectors[i].collectAndApply();;
+    }
+  }
+  
+  /**
+   * Finalize the reductions with the collected data stored in the parameter.
+   * Once the data is finalized, the {@link ReductionFunction}s that use these 
+   * {@link ReductionDataCollector}s act like regular {@link AnalyticsValue} classes that 
+   * can be accessed through their {@code get<value-type>} methods.
+   * 
+   * @param dataCollection the collection of reduction data to compute results for
+   */
+  public void setData(ReductionDataCollection dataCollection) {
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      reductionDataCollectors[i].setData(dataCollection.dataArr[i]);
+    }
+  }
+  
+  /**
+   * Construct a new data collection holding data for all managed data collectors.
+   * 
+   * @return a new data collection
+   */
+  public ReductionDataCollection newDataCollection() {
+    ReductionDataCollection newCol = new ReductionDataCollection();
+    newCol.dataArr = new ReductionData[reductionDataCollectors.length];
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      newCol.dataArr[i] = reductionDataCollectors[i].newData();
+    }
+    return newCol;
+  }
+  
+  /**
+   * Sets the stream of shard data to merge with.
+   * 
+   * @param input the stream of shard data
+   */
+  public void setShardInput(DataInput input) {
+    readers.clear();
+    reservations.forEach( resv -> readers.add(resv.createReadStream(input)));
+  }
+  /**
+   * Merge the data from the given shard input stream into the set IO data collectors.
+   * Should always be called after {@link #setShardInput(DataInput)} and either {@link #prepareReductionDataIO(ReductionDataCollection)}
+   * or {@link #newDataCollectionIO()} have been called.
+   * 
+   * @throws IOException if an error occurs while reading the shard data
+   */
+  public void mergeData() throws IOException {
+    for (ReductionDataReader<?> reader : readers) {
+      reader.read();
+    }
+  }
+  
+  /**
+   * Sets the stream to export shard data to.
+   * 
+   * @param output the stream of shard data
+   */
+  public void setShardOutput(DataOutput output) {
+    writers.clear();
+    reservations.forEach( resv -> writers.add(resv.createWriteStream(output)));
+  }
+  /**
+   * Export the data from the set IO data collectors to the given shard output stream.
+   * Should always be called after {@link #setShardOutput(DataOutput)} and {@link #prepareReductionDataIO(ReductionDataCollection)}.
+   * 
+   * @throws IOException if an error occurs while writing the shard data
+   */
+  public void exportData() throws IOException {
+    for (ReductionDataWriter<?> writer : writers) {
+      writer.write();
+    }
+  }
+  
+  /**
+   * Set the given data collection to be used for either merging or exporting
+   *  
+   * @param col collection to export from or merge to
+   */
+  public void prepareReductionDataIO(ReductionDataCollection col) {
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      reductionDataCollectors[i].dataIO(col.dataArr[i]);
+    }
+  }
+  
+  /**
+   * Create a new {@link ReductionDataCollection} to merge to or export from.
+   * Mainly used for creating facet value collectors when merging shard data.
+   *  
+   * @return the new data collection created
+   */
+  public ReductionDataCollection newDataCollectionIO() {
+    ReductionDataCollection newCol = new ReductionDataCollection();
+    newCol.dataArr = new ReductionData[reductionDataCollectors.length];
+    for (int i = 0; i < reductionDataCollectors.length; i++) {
+      newCol.dataArr[i] = reductionDataCollectors[i].newDataIO();
+    }
+    return newCol;
+  }
+  
+  /**
+   * Holds the collection of {@link ReductionData} that will be updated together.
+   * 
+   * For example each grouping will have a separate {@link ReductionDataCollection}, and
+   * ungrouped expressions will have their own as well.
+   */
+  public static class ReductionDataCollection{
+    public ReductionData[] dataArr;
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionFunction.java
new file mode 100644
index 0000000..fea01c2
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/ReductionFunction.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.value.AnalyticsValue;
+
+/**
+ * A function that reduces the values of a mapping expression, field or constant.
+ */
+public interface ReductionFunction extends AnalyticsValue {
+
+  /**
+   * Syncs the data collectors with shared versions across the entire Analytics Request
+   * so that as little data as possible is sent across shards.
+   * 
+   * @param sync a function that takes in a {@link ReductionDataCollector} and returns a shared version
+   */
+  void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync);
+}
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/AnalyticsField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/AnalyticsField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/AnalyticsField.java
new file mode 100644
index 0000000..dab0358
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/AnalyticsField.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+
+/**
+ * An analytics wrapper for Solr Fields. 
+ * 
+ * Currently only fields with Doc Values enabled can be used in Analytics queries.
+ */
+public abstract class AnalyticsField implements AnalyticsValueStream {
+  protected static final int initialArrayLength = 20;
+  
+  protected final String fieldName;
+  
+  protected AnalyticsField(String fieldName) {
+    this.fieldName = fieldName;
+  }
+  
+  @Override
+  public String getExpressionStr() {
+    return fieldName;
+  }
+
+  @Override
+  public String getName() {
+    return fieldName;
+  }
+  
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.FIELD;
+  }
+  
+  /**
+   * Set the segment reader context
+   * 
+   * @param context segment context
+   * @throws IOException if an error occurs while loading the leaf reader
+   */
+  public abstract void doSetNextReader(LeafReaderContext context) throws IOException;
+  
+  /**
+   * Collect the value(s) of the wrapped field for the given document, and store the value.
+   * 
+   * @param doc ID of the document to collect
+   * @throws IOException if an error occurs while reading the document.
+   */
+  public abstract void collect(int doc) throws IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanField.java
new file mode 100644
index 0000000..650bc36
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanField.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedDocValues;
+import org.apache.lucene.util.BytesRef;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.value.BooleanValue.CastingBooleanValue;
+import org.apache.solr.schema.BoolField;
+
+/**
+ * An analytics wrapper for a single-valued {@link BoolField} with DocValues enabled.
+ */
+public class BooleanField extends AnalyticsField implements CastingBooleanValue {
+  private SortedDocValues docValues;
+  boolean value;
+  boolean exists;
+  int trueOrd;
+
+  public BooleanField(String fieldName) {
+    super(fieldName);
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSorted(context.reader(), fieldName);
+
+    // figure out what ord maps to true
+    int numOrds = docValues.getValueCount();
+    // if no values in the segment, default trueOrd to something other then -1 (missing)
+    int trueOrd = -2;
+    for (int i=0; i<numOrds; i++) {
+      final BytesRef br = docValues.lookupOrd(i);
+      if (br.length==1 && br.bytes[br.offset]=='T') {
+        trueOrd = i;
+        break;
+      }
+    }
+
+    this.trueOrd = trueOrd;
+  }
+
+  @Override
+  public void collect(int doc) throws IOException {
+    exists = docValues.advanceExact(doc);
+    if (exists) {
+      value = trueOrd ==  docValues.ordValue();
+    }
+  }
+
+  @Override
+  public boolean getBoolean() {
+    return value;
+  }
+  @Override
+  public String getString() {
+    return exists ? Boolean.toString(value) : null;
+  }
+  @Override
+  public Object getObject() {
+    return exists ? value : null;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    if (exists) {
+      cons.accept(Boolean.toString(value));
+    }
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+
+  @Override
+  public ExpressionComparator<Boolean> getObjectComparator(String expression) {
+    return new ExpressionComparator<>(expression);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanMultiField.java
new file mode 100644
index 0000000..e4eecd3
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/BooleanMultiField.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.lucene.util.BytesRef;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.value.BooleanValueStream.CastingBooleanValueStream;
+import org.apache.solr.schema.BoolField;
+
+
+/**
+ * An analytics wrapper for a multi-valued {@link BoolField} with DocValues enabled.
+ */
+public class BooleanMultiField extends AnalyticsField implements CastingBooleanValueStream {
+  private SortedSetDocValues docValues;
+  private int count;
+  private boolean[] values;
+  
+  private int trueOrd;
+
+  public BooleanMultiField(String fieldName) {
+    super(fieldName);
+    count = 0;
+    values = new boolean[initialArrayLength];
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSortedSet(context.reader(), fieldName);
+
+    // figure out what ord maps to true
+    long numOrds = docValues.getValueCount();
+    // if no values in the segment, default trueOrd to something other then -1 (missing)
+    int trueOrd = -2;
+    for (int i=0; i<numOrds; i++) {
+      final BytesRef br = docValues.lookupOrd(i);
+      if (br.length==1 && br.bytes[br.offset]=='T') {
+        trueOrd = i;
+        break;
+      }
+    }
+
+    this.trueOrd = trueOrd;
+  }
+  @Override
+  public void collect(int doc) throws IOException {
+    count = 0;
+    if (docValues.advanceExact(doc)) {
+      int term;
+      while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+        if (count == values.length) {
+          resizeValues();
+        }
+        values[count++] = term == trueOrd;
+      }
+    }
+  }
+  
+  private void resizeValues() {
+    boolean[] newValues = new boolean[values.length*2];
+    for (int i = 0; i < count; ++i) {
+      newValues[i] = values[i];
+    }
+    values = newValues;
+  }
+  
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    for (int i = 0; i < count; ++i) {
+      cons.accept(values[i]);
+    }
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamBooleans(value -> cons.accept(Boolean.toString(value)));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamBooleans(value -> cons.accept(value));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateField.java
new file mode 100644
index 0000000..88e71bc
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateField.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.util.Date;
+import java.util.function.Consumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.value.DateValue.CastingDateValue;
+import org.apache.solr.schema.DatePointField;
+import org.apache.solr.schema.TrieDateField;
+
+/**
+ * An analytics wrapper for a single-valued {@link TrieDateField} or {@link DatePointField} with DocValues enabled.
+ */
+public class DateField extends AnalyticsField implements CastingDateValue {
+  private NumericDocValues docValues; 
+  private long value;
+  private boolean exists;
+
+  public DateField(String fieldName) {
+    super(fieldName);
+  }
+
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getNumeric(context.reader(), fieldName);
+  }
+
+  @Override
+  public void collect(int doc) throws IOException {
+    exists = docValues.advanceExact(doc);
+    if (exists) {
+      value = docValues.longValue();
+    }
+  }
+
+  @Override
+  public long getLong() {
+    return value;
+  }
+  @Override
+  public Date getDate() {
+    return exists ? new Date(value) : null;
+  }
+  @Override
+  public String getString() {
+    return exists ? Instant.ofEpochMilli(value).toString() : null;
+  }
+  @Override
+  public Object getObject() {
+    return exists ? value : null;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+  @Override
+  public void streamDates(Consumer<Date> cons) {
+    if (exists) {
+      cons.accept(new Date(value));
+    }
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    if (exists) {
+      cons.accept(Instant.ofEpochMilli(value).toString());
+    }
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    if (exists) {
+      cons.accept(new Date(value));
+    }
+  }
+
+  @Override
+  public ExpressionComparator<Date> getObjectComparator(String expression) {
+    return new ExpressionComparator<>(expression);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiField.java
new file mode 100644
index 0000000..64ee489
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiField.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.value.DateValueStream.CastingDateValueStream;
+import org.apache.solr.schema.TrieDateField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link TrieDateField} with DocValues enabled.
+ */
+public class DateMultiField extends LongMultiField implements CastingDateValueStream {
+
+  public DateMultiField(String fieldName) {
+    super(fieldName);
+  }
+  
+  @Override
+  public void streamDates(Consumer<Date> cons) {
+    streamLongs(value -> cons.accept(new Date(value)));
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamLongs(value -> cons.accept(Instant.ofEpochMilli(value).toString()));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamLongs(value -> cons.accept(new Date(value)));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiPointField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiPointField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiPointField.java
new file mode 100644
index 0000000..a1560ef
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DateMultiPointField.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.value.DateValueStream.CastingDateValueStream;
+import org.apache.solr.schema.DatePointField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link DatePointField} with DocValues enabled.
+ */
+public class DateMultiPointField extends LongMultiPointField implements CastingDateValueStream {
+
+  public DateMultiPointField(String fieldName) {
+    super(fieldName);
+  }
+  
+  @Override
+  public void streamDates(Consumer<Date> cons) {
+    streamLongs(value -> cons.accept(new Date(value)));
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamLongs(value -> cons.accept(Instant.ofEpochMilli(value).toString()));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamLongs(value -> cons.accept(new Date(value)));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleField.java
new file mode 100644
index 0000000..68941a4
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleField.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.value.DoubleValue.CastingDoubleValue;
+import org.apache.solr.schema.DoublePointField;
+import org.apache.solr.schema.TrieDoubleField;
+
+/**
+ * An analytics wrapper for a single-valued {@link TrieDoubleField} or {@link DoublePointField} with DocValues enabled.
+ */
+public class DoubleField extends AnalyticsField implements CastingDoubleValue {
+  private NumericDocValues docValues;
+  private double value;
+  private boolean exists;
+
+  public DoubleField(String fieldName) {
+    super(fieldName);
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getNumeric(context.reader(), fieldName);
+  }
+
+  @Override
+  public void collect(int doc) throws IOException {
+    exists = docValues.advanceExact(doc);
+    if (exists) {
+      value = NumericUtils.sortableLongToDouble(docValues.longValue());
+    }
+  }
+
+  @Override
+  public double getDouble() {
+    return value;
+  }
+  @Override
+  public String getString() {
+    return exists ? Double.toString(value) : null;
+  }
+  @Override
+  public Object getObject() {
+    return exists ? value : null;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    if (exists) {
+      cons.accept(Double.toString(value));
+    }
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+
+  @Override
+  public ExpressionComparator<Double> getObjectComparator(String expression) {
+    return new ExpressionComparator<>(expression);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiField.java
new file mode 100644
index 0000000..3d58634
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiField.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.value.DoubleValueStream.CastingDoubleValueStream;
+import org.apache.solr.legacy.LegacyNumericUtils;
+import org.apache.solr.schema.TrieDoubleField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link TrieDoubleField} with DocValues enabled.
+ */
+public class DoubleMultiField extends AnalyticsField implements CastingDoubleValueStream {
+  private SortedSetDocValues docValues;
+  private int count;
+  private double[] values;
+
+  public DoubleMultiField(String fieldName) {
+    super(fieldName);
+    count = 0;
+    values = new double[initialArrayLength];
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSortedSet(context.reader(), fieldName);
+  }
+  @Override
+  public void collect(int doc) throws IOException {
+    count = 0;
+    if (docValues.advanceExact(doc)) {
+      int term;
+      while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+        if (count == values.length) {
+          resizeValues();
+        }
+        values[count++] = NumericUtils.sortableLongToDouble(LegacyNumericUtils.prefixCodedToLong(docValues.lookupOrd(term)));
+      }
+    }
+  }
+  
+  private void resizeValues() {
+    double[] newValues = new double[values.length*2];
+    for (int i = 0; i < count; ++i) {
+      newValues[i] = values[i];
+    }
+    values = newValues;
+  }
+  
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    for (int i = 0; i < count; ++i) {
+      cons.accept(values[i]);
+    }
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamDoubles(value -> cons.accept(Double.toString(value)));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamDoubles(value -> cons.accept(value));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiPointField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiPointField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiPointField.java
new file mode 100644
index 0000000..0933f60
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/DoubleMultiPointField.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedNumericDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.value.DoubleValueStream.CastingDoubleValueStream;
+import org.apache.solr.schema.DoublePointField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link DoublePointField} with DocValues enabled.
+ */
+public class DoubleMultiPointField extends AnalyticsField implements CastingDoubleValueStream {
+  private SortedNumericDocValues docValues;
+  private int count;
+  private double[] values;
+
+  public DoubleMultiPointField(String fieldName) {
+    super(fieldName);
+    count = 0;
+    values = new double[initialArrayLength];
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSortedNumeric(context.reader(), fieldName);
+  }
+  @Override
+  public void collect(int doc) throws IOException {
+    if (docValues.advanceExact(doc)) {
+      count = docValues.docValueCount();
+      resizeEmptyValues(count);
+      for (int i = 0; i < count; ++i) {
+        values[i] = NumericUtils.sortableLongToDouble(docValues.nextValue());
+      }
+    } else {
+      count = 0;
+    }
+  }
+  
+  private void resizeEmptyValues(int count) {
+    if (count > values.length) {
+      values = new double[count];
+    }
+  }
+  
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    for (int i = 0; i < count; ++i) {
+      cons.accept(values[i]);
+    }
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamDoubles(value -> cons.accept(Double.toString(value)));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamDoubles(value -> cons.accept(value));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatField.java
new file mode 100644
index 0000000..c382d61
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatField.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.FloatValue.CastingFloatValue;
+import org.apache.solr.schema.FloatPointField;
+import org.apache.solr.schema.TrieFloatField;
+
+/**
+ * An analytics wrapper for a single-valued {@link TrieFloatField} or {@link FloatPointField} with DocValues enabled.
+ */
+public class FloatField extends AnalyticsField implements CastingFloatValue {
+  private NumericDocValues docValues;
+  private float value;
+  private boolean exists;
+
+  public FloatField(String fieldName) {
+    super(fieldName);
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getNumeric(context.reader(), fieldName);
+  }
+
+  @Override
+  public void collect(int doc) throws IOException {
+    exists = docValues.advanceExact(doc);
+    if (exists) {
+      value = NumericUtils.sortableIntToFloat((int)docValues.longValue());
+    }
+  }
+
+  @Override
+  public float getFloat() {
+    return value;
+  }
+  @Override
+  public double getDouble() {
+    return (double)value;
+  }
+  @Override
+  public String getString() {
+    return exists ? Float.toString(value) : null;
+  }
+  @Override
+  public Object getObject() {
+    return exists ? value : null;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    if (exists) {
+      cons.accept((double)value);
+    }
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    if (exists) {
+      cons.accept(Float.toString(value));
+    }
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+
+  @Override
+  public ExpressionComparator<Float> getObjectComparator(String expression) {
+    return new ExpressionComparator<>(expression);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiField.java
new file mode 100644
index 0000000..acfce18
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiField.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.FloatValueStream.CastingFloatValueStream;
+import org.apache.solr.legacy.LegacyNumericUtils;
+import org.apache.solr.schema.TrieFloatField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link TrieFloatField} with DocValues enabled.
+ */
+public class FloatMultiField extends AnalyticsField implements CastingFloatValueStream {
+  private SortedSetDocValues docValues;
+  private int count;
+  private float[] values;
+
+  public FloatMultiField(String fieldName) {
+    super(fieldName);
+    count = 0;
+    values = new float[initialArrayLength];
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSortedSet(context.reader(), fieldName);
+  }
+  
+  @Override
+  public void collect(int doc) throws IOException {
+    count = 0;
+    if (docValues.advanceExact(doc)) {
+      int term;
+      while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+        if (count == values.length) {
+          resizeValues();
+        }
+        values[count++] = NumericUtils.sortableIntToFloat(LegacyNumericUtils.prefixCodedToInt(docValues.lookupOrd(term)));
+      }
+    }
+  }
+  
+  private void resizeValues() {
+    float[] newValues = new float[values.length*2];
+    for (int i = 0; i < count; ++i) {
+      newValues[i] = values[i];
+    }
+    values = newValues;
+  }
+  
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    for (int i = 0; i < count; ++i) {
+      cons.accept(values[i]);
+    }
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    streamFloats(value -> cons.accept((double)value));
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamFloats(value -> cons.accept(Float.toString(value)));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamFloats(value -> cons.accept(value));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiPointField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiPointField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiPointField.java
new file mode 100644
index 0000000..947035e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/FloatMultiPointField.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedNumericDocValues;
+import org.apache.lucene.util.NumericUtils;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.FloatValueStream.CastingFloatValueStream;
+import org.apache.solr.schema.FloatPointField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link FloatPointField} with DocValues enabled.
+ */
+public class FloatMultiPointField extends AnalyticsField implements CastingFloatValueStream {
+  private SortedNumericDocValues docValues;
+  private int count;
+  private float[] values;
+
+  public FloatMultiPointField(String fieldName) {
+    super(fieldName);
+    count = 0;
+    values = new float[initialArrayLength];
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSortedNumeric(context.reader(), fieldName);
+  }
+  
+  @Override
+  public void collect(int doc) throws IOException {
+    if (docValues.advanceExact(doc)) {
+      count = docValues.docValueCount();
+      resizeEmptyValues(count);
+      for (int i = 0; i < count; ++i) {
+        values[i] = NumericUtils.sortableIntToFloat((int)docValues.nextValue());
+      }
+    } else {
+      count = 0;
+    }
+  }
+  
+  private void resizeEmptyValues(int count) {
+    if (count > values.length) {
+      values = new float[count];
+    }
+  }
+  
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    for (int i = 0; i < count; ++i) {
+      cons.accept(values[i]);
+    }
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    streamFloats(value -> cons.accept((double)value));
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamFloats(value -> cons.accept(Float.toString(value)));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamFloats(value -> cons.accept(value));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntField.java
new file mode 100644
index 0000000..e9ae52b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntField.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.IntValue.CastingIntValue;
+import org.apache.solr.schema.IntPointField;
+import org.apache.solr.schema.TrieIntField;
+
+/**
+ * An analytics wrapper for a single-valued {@link TrieIntField} or {@link IntPointField} with DocValues enabled.
+ */
+public class IntField extends AnalyticsField implements CastingIntValue {
+  private NumericDocValues docValues;
+  private int value;
+  private boolean exists;
+  
+  public IntField(String fieldName) {
+    super(fieldName);
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getNumeric(context.reader(), fieldName);
+  }
+
+  @Override
+  public void collect(int doc) throws IOException {
+    exists = docValues.advanceExact(doc);
+    if (exists) {
+      value = (int)docValues.longValue();
+    }
+  }
+
+  @Override
+  public int getInt() {
+    return value;
+  }
+  @Override
+  public long getLong() {
+    return (long)value;
+  }
+  @Override
+  public float getFloat() {
+    return (float)value;
+  }
+  @Override
+  public double getDouble() {
+    return (double)value;
+  }
+  @Override
+  public String getString() {
+    return exists ? Integer.toString(value) : null;
+  }
+  @Override
+  public Object getObject() {
+    return exists ? value : null;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public void streamInts(IntConsumer cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    if (exists) {
+      cons.accept((long)value);
+    }
+  }
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    if (exists) {
+      cons.accept((float)value);
+    }
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    if (exists) {
+      cons.accept((double)value);
+    }
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    if (exists) {
+      cons.accept(Integer.toString(value));
+    }
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    if (exists) {
+      cons.accept(value);
+    }
+  }
+
+  @Override
+  public ExpressionComparator<Integer> getObjectComparator(String expression) {
+    return new ExpressionComparator<>(expression);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiField.java
new file mode 100644
index 0000000..657b1f3
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiField.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.IntValueStream.CastingIntValueStream;
+import org.apache.solr.legacy.LegacyNumericUtils;
+import org.apache.solr.schema.TrieIntField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link TrieIntField} with DocValues enabled.
+ */
+public class IntMultiField extends AnalyticsField implements CastingIntValueStream {
+  private SortedSetDocValues docValues;
+  private int count;
+  private int[] values;
+
+  public IntMultiField(String fieldName) {
+    super(fieldName);
+    count = 0;
+    values = new int[initialArrayLength];
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSortedSet(context.reader(), fieldName);
+  }
+  
+  @Override
+  public void collect(int doc) throws IOException {
+    count = 0;
+    if (docValues.advanceExact(doc)) {
+      int term;
+      while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+        if (count == values.length) {
+          resizeValues();
+        }
+        values[count++] = LegacyNumericUtils.prefixCodedToInt(docValues.lookupOrd(term));
+      }
+    }
+  }
+  
+  private void resizeValues() {
+    int[] newValues = new int[values.length*2];
+    for (int i = 0; i < count; ++i) {
+      newValues[i] = values[i];
+    }
+    values = newValues;
+  }
+  
+  @Override
+  public void streamInts(IntConsumer cons) {
+    for (int i = 0; i < count; ++i) {
+      cons.accept(values[i]);
+    }
+  }
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    streamInts(value -> cons.accept((long)value));
+  }
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    streamInts(value -> cons.accept((float)value));
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    streamInts(value -> cons.accept((double)value));
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamInts(value -> cons.accept(Integer.toString(value)));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamInts(value -> cons.accept(value));
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiPointField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiPointField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiPointField.java
new file mode 100644
index 0000000..2608fa1
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/IntMultiPointField.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedNumericDocValues;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.IntValueStream.CastingIntValueStream;
+import org.apache.solr.schema.IntPointField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link IntPointField} with DocValues enabled.
+ */
+public class IntMultiPointField extends AnalyticsField implements CastingIntValueStream {
+  private SortedNumericDocValues docValues;
+  private int count;
+  private int[] values;
+
+  public IntMultiPointField(String fieldName) {
+    super(fieldName);
+    count = 0;
+    values = new int[initialArrayLength];
+  }
+  
+  @Override
+  public void doSetNextReader(LeafReaderContext context) throws IOException {
+    docValues = DocValues.getSortedNumeric(context.reader(), fieldName);
+  }
+  
+  @Override
+  public void collect(int doc) throws IOException {
+    if (docValues.advanceExact(doc)) {
+      count = docValues.docValueCount();
+      resizeEmptyValues(count);
+      for (int i = 0; i < count; ++i) {
+        values[i] = (int)docValues.nextValue();
+      }
+    } else {
+      count = 0;
+    }
+  }
+  
+  private void resizeEmptyValues(int count) {
+    if (count > values.length) {
+      values = new int[count];
+    }
+  }
+  
+  @Override
+  public void streamInts(IntConsumer cons) {
+    for (int i = 0; i < count; ++i) {
+      cons.accept(values[i]);
+    }
+  }
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    streamInts(value -> cons.accept((long)value));
+  }
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    streamInts(value -> cons.accept((float)value));
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    streamInts(value -> cons.accept((double)value));
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    streamInts(value -> cons.accept(Integer.toString(value)));
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    streamInts(value -> cons.accept(value));
+  }
+}


[15/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/FillMissingFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/FillMissingFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/FillMissingFunction.java
new file mode 100644
index 0000000..188d698
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/FillMissingFunction.java
@@ -0,0 +1,842 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.AnalyticsValue;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.BooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.AnalyticsValue.AbstractAnalyticsValue;
+import org.apache.solr.analytics.value.BooleanValue.AbstractBooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream.AbstractBooleanValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DateValueStream.AbstractDateValueStream;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream.AbstractDoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.FloatValueStream.AbstractFloatValueStream;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.IntValueStream.AbstractIntValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.LongValueStream.AbstractLongValueStream;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.value.StringValueStream.AbstractStringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A mapping function to fill all non-existing values with a given value. 
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If two Values are passed in, a Value mimicking the first parameter with the second parameter used as filler will be returned.
+ * <li>If two ValueStreams are passed in, a ValueStream mimicking the first parameter with the second parameter used as filler will be returned.
+ * </ul>
+ * <p>
+ * The resulting Value or ValueStream will be typed with the closest super-type of the two parameters.
+ * (e.g. {@value #name}(double,int) will return a double)
+ */
+public class FillMissingFunction {
+  public static final String name = "fillmissing";
+
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramaters, " + params.length + " found.");
+    }
+
+    AnalyticsValueStream baseExpr = params[0];
+    AnalyticsValueStream fillExpr = params[1];
+    if (baseExpr instanceof DateValue && fillExpr instanceof DateValue) {
+      return new DateFillMissingFunction((DateValue)baseExpr,(DateValue)fillExpr);
+    }
+    if (baseExpr instanceof DateValueStream && fillExpr instanceof DateValueStream) {
+      return new DateStreamFillMissingFunction((DateValueStream)baseExpr,(DateValueStream)fillExpr);
+    }
+    if (baseExpr instanceof BooleanValue && fillExpr instanceof BooleanValue) {
+      return new BooleanFillMissingFunction((BooleanValue)baseExpr,(BooleanValue)fillExpr);
+    }
+    if (baseExpr instanceof BooleanValueStream && fillExpr instanceof BooleanValueStream) {
+      return new BooleanStreamFillMissingFunction((BooleanValueStream)baseExpr,(BooleanValueStream)fillExpr);
+    }
+    if (baseExpr instanceof IntValue && fillExpr instanceof IntValue) {
+      return new IntFillMissingFunction((IntValue)baseExpr,(IntValue)fillExpr);
+    }
+    if (baseExpr instanceof IntValueStream && fillExpr instanceof IntValueStream) {
+      return new IntStreamFillMissingFunction((IntValueStream)baseExpr,(IntValueStream)fillExpr);
+    }
+    if (baseExpr instanceof LongValue && fillExpr instanceof LongValue) {
+      return new LongFillMissingFunction((LongValue)baseExpr,(LongValue)fillExpr);
+    }
+    if (baseExpr instanceof LongValueStream && fillExpr instanceof LongValueStream) {
+      return new LongStreamFillMissingFunction((LongValueStream)baseExpr,(LongValueStream)fillExpr);
+    }
+    if (baseExpr instanceof FloatValue && fillExpr instanceof FloatValue) {
+      return new FloatFillMissingFunction((FloatValue)baseExpr,(FloatValue)fillExpr);
+    }
+    if (baseExpr instanceof FloatValueStream && fillExpr instanceof FloatValueStream) {
+      return new FloatStreamFillMissingFunction((FloatValueStream)baseExpr,(FloatValueStream)fillExpr);
+    }
+    if (baseExpr instanceof DoubleValue && fillExpr instanceof DoubleValue) {
+      return new DoubleFillMissingFunction((DoubleValue)baseExpr,(DoubleValue)fillExpr);
+    }
+    if (baseExpr instanceof DoubleValueStream && fillExpr instanceof DoubleValueStream) {
+      return new DoubleStreamFillMissingFunction((DoubleValueStream)baseExpr,(DoubleValueStream)fillExpr);
+    }
+    if (baseExpr instanceof StringValue && fillExpr instanceof StringValue) {
+      return new StringFillMissingFunction((StringValue)baseExpr,(StringValue)fillExpr);
+    }
+    if (baseExpr instanceof StringValueStream && fillExpr instanceof StringValueStream) {
+      return new StringStreamFillMissingFunction((StringValueStream)baseExpr,(StringValueStream)fillExpr);
+    }
+    if (baseExpr instanceof AnalyticsValue && fillExpr instanceof AnalyticsValue) {
+      return new ValueFillMissingFunction((AnalyticsValue)baseExpr,(AnalyticsValue)fillExpr);
+    }
+    return new StreamFillMissingFunction(baseExpr,fillExpr);
+  });
+}
+class StreamFillMissingFunction implements AnalyticsValueStream, Consumer<Object> {
+  private final AnalyticsValueStream baseExpr;
+  private final AnalyticsValueStream fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StreamFillMissingFunction(AnalyticsValueStream baseExpr, AnalyticsValueStream fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+
+  boolean exists = false;
+  Consumer<Object> cons;
+
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    exists = false;
+    this.cons = cons;
+    baseExpr.streamObjects(this);
+    if (!exists) {
+      fillExpr.streamObjects(cons);
+    }
+  }
+  @Override
+  public void accept(Object value) {
+    exists = true;
+    cons.accept(value);
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class ValueFillMissingFunction extends AbstractAnalyticsValue {
+  private final AnalyticsValue baseExpr;
+  private final AnalyticsValue fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public ValueFillMissingFunction(AnalyticsValue baseExpr, AnalyticsValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public Object getObject() {
+    Object value = baseExpr.getObject();
+    exists = true;
+    if (!baseExpr.exists()) {
+      value = fillExpr.getObject();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanStreamFillMissingFunction extends AbstractBooleanValueStream implements BooleanConsumer {
+  private final BooleanValueStream baseExpr;
+  private final BooleanValueStream fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanStreamFillMissingFunction(BooleanValueStream baseExpr, BooleanValueStream fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+
+  boolean exists = false;
+  BooleanConsumer cons;
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    exists = false;
+    this.cons = cons;
+    baseExpr.streamBooleans(this);
+    if (!exists) {
+      fillExpr.streamBooleans(cons);
+    }
+  }
+  @Override
+  public void accept(boolean value) {
+    exists = true;
+    cons.accept(value);
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanFillMissingFunction extends AbstractBooleanValue {
+  private final BooleanValue baseExpr;
+  private final BooleanValue fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanFillMissingFunction(BooleanValue baseExpr, BooleanValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public boolean getBoolean() {
+    boolean value = baseExpr.getBoolean();
+    exists = true;
+    if (!baseExpr.exists()) {
+      value = fillExpr.getBoolean();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntStreamFillMissingFunction extends AbstractIntValueStream implements IntConsumer {
+  private final IntValueStream baseExpr;
+  private final IntValueStream fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntStreamFillMissingFunction(IntValueStream baseExpr, IntValueStream fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+
+  boolean exists = false;
+  IntConsumer cons;
+
+  @Override
+  public void streamInts(IntConsumer cons) {
+    exists = false;
+    this.cons = cons;
+    baseExpr.streamInts(this);
+    if (!exists) {
+      fillExpr.streamInts(cons);
+    }
+  }
+  @Override
+  public void accept(int value) {
+    exists = true;
+    cons.accept(value);
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntFillMissingFunction extends AbstractIntValue {
+  private final IntValue baseExpr;
+  private final IntValue fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntFillMissingFunction(IntValue baseExpr, IntValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public int getInt() {
+    int value = baseExpr.getInt();
+    exists = true;
+    if (!baseExpr.exists()) {
+      value = fillExpr.getInt();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongStreamFillMissingFunction extends AbstractLongValueStream implements LongConsumer {
+  private final LongValueStream baseExpr;
+  private final LongValueStream fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongStreamFillMissingFunction(LongValueStream baseExpr, LongValueStream fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+
+  boolean exists = false;
+  LongConsumer cons;
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    exists = false;
+    this.cons = cons;
+    baseExpr.streamLongs(this);
+    if (!exists) {
+      fillExpr.streamLongs(cons);
+    }
+  }
+  @Override
+  public void accept(long value) {
+    exists = true;
+    cons.accept(value);
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongFillMissingFunction extends AbstractLongValue {
+  private final LongValue baseExpr;
+  private final LongValue fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongFillMissingFunction(LongValue baseExpr, LongValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public long getLong() {
+    long value = baseExpr.getLong();
+    exists = true;
+    if (!baseExpr.exists()) {
+      value = fillExpr.getLong();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatStreamFillMissingFunction extends AbstractFloatValueStream implements FloatConsumer {
+  private final FloatValueStream baseExpr;
+  private final FloatValueStream fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatStreamFillMissingFunction(FloatValueStream baseExpr, FloatValueStream fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+
+  boolean exists = false;
+  FloatConsumer cons;
+
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    exists = false;
+    this.cons = cons;
+    baseExpr.streamFloats(this);
+    if (!exists) {
+      fillExpr.streamFloats(cons);
+    }
+  }
+  @Override
+  public void accept(float value) {
+    exists = true;
+    cons.accept(value);
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatFillMissingFunction extends AbstractFloatValue {
+  private final FloatValue baseExpr;
+  private final FloatValue fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatFillMissingFunction(FloatValue baseExpr, FloatValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public float getFloat() {
+    float value = baseExpr.getFloat();
+    exists = true;
+    if (!baseExpr.exists()) {
+      value = fillExpr.getFloat();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DoubleStreamFillMissingFunction extends AbstractDoubleValueStream implements DoubleConsumer {
+  private final DoubleValueStream baseExpr;
+  private final DoubleValueStream fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DoubleStreamFillMissingFunction(DoubleValueStream baseExpr, DoubleValueStream fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+
+  boolean exists = false;
+  DoubleConsumer cons;
+
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    exists = false;
+    this.cons = cons;
+    baseExpr.streamDoubles(this);
+    if (!exists) {
+      fillExpr.streamDoubles(cons);
+    }
+  }
+  @Override
+  public void accept(double value) {
+    exists = true;
+    cons.accept(value);
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DoubleFillMissingFunction extends AbstractDoubleValue {
+  private final DoubleValue baseExpr;
+  private final DoubleValue fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DoubleFillMissingFunction(DoubleValue baseExpr, DoubleValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public double getDouble() {
+    double value = baseExpr.getDouble();
+    exists = true;
+    if (!baseExpr.exists()) {
+      value = fillExpr.getDouble();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DateStreamFillMissingFunction extends AbstractDateValueStream implements LongConsumer {
+  private final DateValueStream baseExpr;
+  private final DateValueStream fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateStreamFillMissingFunction(DateValueStream baseExpr, DateValueStream fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+
+  boolean exists = false;
+  LongConsumer cons;
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    exists = false;
+    this.cons = cons;
+    baseExpr.streamLongs(this);
+    if (!exists) {
+      fillExpr.streamLongs(cons);
+    }
+  }
+  @Override
+  public void accept(long value) {
+    exists = true;
+    cons.accept(value);
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DateFillMissingFunction extends AbstractDateValue {
+  private final DateValue baseExpr;
+  private final DateValue fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateFillMissingFunction(DateValue baseExpr, DateValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public long getLong() {
+    long value = baseExpr.getLong();
+    exists = true;
+    if (!baseExpr.exists()) {
+      value = fillExpr.getLong();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringStreamFillMissingFunction extends AbstractStringValueStream implements Consumer<String> {
+  private final StringValueStream baseExpr;
+  private final StringValueStream fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StringStreamFillMissingFunction(StringValueStream baseExpr, StringValueStream fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+
+  boolean exists = false;
+  Consumer<String> cons;
+
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    exists = false;
+    this.cons = cons;
+    baseExpr.streamStrings(this);
+    if (!exists) {
+      fillExpr.streamStrings(cons);
+    }
+  }
+  @Override
+  public void accept(String value) {
+    exists = true;
+    cons.accept(value);
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringFillMissingFunction extends AbstractStringValue {
+  private final StringValue baseExpr;
+  private final StringValue fillExpr;
+  public static final String name = FillMissingFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StringFillMissingFunction(StringValue baseExpr, StringValue fillExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.fillExpr = fillExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,fillExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,fillExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public String getString() {
+    String value = baseExpr.getString();
+    exists = true;
+    if (!baseExpr.exists()) {
+      value = fillExpr.getString();
+      exists = fillExpr.exists();
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/FilterFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/FilterFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/FilterFunction.java
new file mode 100644
index 0000000..84a3e30
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/FilterFunction.java
@@ -0,0 +1,722 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.AnalyticsValue;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.BooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.AnalyticsValue.AbstractAnalyticsValue;
+import org.apache.solr.analytics.value.BooleanValue.AbstractBooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream.AbstractBooleanValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DateValueStream.AbstractDateValueStream;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream.AbstractDoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.FloatValueStream.AbstractFloatValueStream;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.IntValueStream.AbstractIntValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.LongValueStream.AbstractLongValueStream;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.value.StringValueStream.AbstractStringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A mapping function to filter a Value or ValueStream. For each document, the value exists if the second parameter 
+ * is true and it doesn't exist otherwise.
+ * <p>
+ * The first parameter can be any type of analytics expression. (Required)
+ * <br>
+ * The second parameter must be a {@link BooleanValue}. (Required)
+ */
+public class FilterFunction {
+  public static final String name = "filter";
+
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramaters, " + params.length + " found.");
+    }
+    if (!(params[1] instanceof BooleanValue)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires the second paramater to be single-valued and boolean.");
+    }
+
+    AnalyticsValueStream baseExpr = params[0];
+    BooleanValue filterExpr = (BooleanValue)params[1];
+
+    if (baseExpr instanceof DateValue) {
+      return new DateFilterFunction((DateValue)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof DateValueStream) {
+      return new DateStreamFilterFunction((DateValueStream)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof BooleanValue) {
+      return new BooleanFilterFunction((BooleanValue)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof BooleanValueStream) {
+      return new BooleanStreamFilterFunction((BooleanValueStream)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof IntValue) {
+      return new IntFilterFunction((IntValue)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof IntValueStream) {
+      return new IntStreamFilterFunction((IntValueStream)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof LongValue) {
+      return new LongFilterFunction((LongValue)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof LongValueStream) {
+      return new LongStreamFilterFunction((LongValueStream)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof FloatValue) {
+      return new FloatFilterFunction((FloatValue)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof FloatValueStream) {
+      return new FloatStreamFilterFunction((FloatValueStream)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof DoubleValue) {
+      return new DoubleFilterFunction((DoubleValue)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof DoubleValueStream) {
+      return new DoubleStreamFilterFunction((DoubleValueStream)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof StringValue) {
+      return new StringFilterFunction((StringValue)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof StringValueStream) {
+      return new StringStreamFilterFunction((StringValueStream)baseExpr,filterExpr);
+    }
+    if (baseExpr instanceof AnalyticsValue) {
+      return new ValueFilterFunction((AnalyticsValue)baseExpr,filterExpr);
+    }
+    return new StreamFilterFunction(baseExpr,filterExpr);
+  });
+}
+class StreamFilterFunction implements AnalyticsValueStream {
+  private final AnalyticsValueStream baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StreamFilterFunction(AnalyticsValueStream baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    if (filterExpr.getBoolean() && filterExpr.exists()) {
+      baseExpr.streamObjects(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class ValueFilterFunction extends AbstractAnalyticsValue {
+  private final AnalyticsValue baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public ValueFilterFunction(AnalyticsValue baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public Object getObject() {
+    Object value = baseExpr.getObject();
+    exists = baseExpr.exists() && filterExpr.getBoolean() && filterExpr.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanStreamFilterFunction extends AbstractBooleanValueStream {
+  private final BooleanValueStream baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanStreamFilterFunction(BooleanValueStream baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    if (filterExpr.getBoolean() && filterExpr.exists()) {
+      baseExpr.streamBooleans(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanFilterFunction extends AbstractBooleanValue {
+  private final BooleanValue baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanFilterFunction(BooleanValue baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public boolean getBoolean() {
+    boolean value = baseExpr.getBoolean();
+    exists = baseExpr.exists() && filterExpr.getBoolean() && filterExpr.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntStreamFilterFunction extends AbstractIntValueStream {
+  private final IntValueStream baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntStreamFilterFunction(IntValueStream baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+
+  @Override
+  public void streamInts(IntConsumer cons) {
+    if (filterExpr.getBoolean() && filterExpr.exists()) {
+      baseExpr.streamInts(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntFilterFunction extends AbstractIntValue {
+  private final IntValue baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntFilterFunction(IntValue baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public int getInt() {
+    int value = baseExpr.getInt();
+    exists = baseExpr.exists() && filterExpr.getBoolean() && filterExpr.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongStreamFilterFunction extends AbstractLongValueStream {
+  private final LongValueStream baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongStreamFilterFunction(LongValueStream baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    if (filterExpr.getBoolean() && filterExpr.exists()) {
+      baseExpr.streamLongs(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongFilterFunction extends AbstractLongValue {
+  private final LongValue baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongFilterFunction(LongValue baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public long getLong() {
+    long value = baseExpr.getLong();
+    exists = baseExpr.exists() && filterExpr.getBoolean() && filterExpr.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatStreamFilterFunction extends AbstractFloatValueStream {
+  private final FloatValueStream baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatStreamFilterFunction(FloatValueStream baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    if (filterExpr.getBoolean() && filterExpr.exists()) {
+      baseExpr.streamFloats(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatFilterFunction extends AbstractFloatValue {
+  private final FloatValue baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatFilterFunction(FloatValue baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public float getFloat() {
+    float value = baseExpr.getFloat();
+    exists = baseExpr.exists() && filterExpr.getBoolean() && filterExpr.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DoubleStreamFilterFunction extends AbstractDoubleValueStream {
+  private final DoubleValueStream baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DoubleStreamFilterFunction(DoubleValueStream baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    if (filterExpr.getBoolean() && filterExpr.exists()) {
+      baseExpr.streamDoubles(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DoubleFilterFunction extends AbstractDoubleValue {
+  private final DoubleValue baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DoubleFilterFunction(DoubleValue baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public double getDouble() {
+    double value = baseExpr.getDouble();
+    exists = baseExpr.exists() && filterExpr.getBoolean() && filterExpr.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DateStreamFilterFunction extends AbstractDateValueStream {
+  private final DateValueStream baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateStreamFilterFunction(DateValueStream baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    if (filterExpr.getBoolean() && filterExpr.exists()) {
+      baseExpr.streamLongs(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DateFilterFunction extends AbstractDateValue {
+  private final DateValue baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateFilterFunction(DateValue baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public long getLong() {
+    long value = baseExpr.getLong();
+    exists = baseExpr.exists() && filterExpr.getBoolean() && filterExpr.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringStreamFilterFunction extends AbstractStringValueStream {
+  private final StringValueStream baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StringStreamFilterFunction(StringValueStream baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    if (filterExpr.getBoolean() && filterExpr.exists()) {
+      baseExpr.streamStrings(cons);
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringFilterFunction extends AbstractStringValue {
+  private final StringValue baseExpr;
+  private final BooleanValue filterExpr;
+  public static final String name = FilterFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StringFilterFunction(StringValue baseExpr, BooleanValue filterExpr) throws SolrException {
+    this.baseExpr = baseExpr;
+    this.filterExpr = filterExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,baseExpr,filterExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,baseExpr,filterExpr);
+  }
+  
+  boolean exists = false;
+
+  @Override
+  public String getString() {
+    String value = baseExpr.getString();
+    exists = baseExpr.exists() && filterExpr.getBoolean() && filterExpr.exists();
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/IfFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/IfFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/IfFunction.java
new file mode 100644
index 0000000..e2fd163
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/IfFunction.java
@@ -0,0 +1,892 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.AnalyticsValue;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.BooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.AnalyticsValue.AbstractAnalyticsValue;
+import org.apache.solr.analytics.value.BooleanValue.AbstractBooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream.AbstractBooleanValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DateValueStream.AbstractDateValueStream;
+import org.apache.solr.analytics.value.DoubleValue.AbstractDoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream.AbstractDoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue.AbstractFloatValue;
+import org.apache.solr.analytics.value.FloatValueStream.AbstractFloatValueStream;
+import org.apache.solr.analytics.value.IntValue.AbstractIntValue;
+import org.apache.solr.analytics.value.IntValueStream.AbstractIntValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.analytics.value.LongValueStream.AbstractLongValueStream;
+import org.apache.solr.analytics.value.StringValue.AbstractStringValue;
+import org.apache.solr.analytics.value.StringValueStream.AbstractStringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * An if-else mapping function. 
+ * <p>
+ * Three arguments are required. The first, the conditional parameter, must be a {@link BooleanValue} and
+ * the later two, the if and else parameters, can be any type of {@link AnalyticsValueStream}. 
+ * For each document, if the conditional value is true then the if-value is used otherwise the else-value is used.
+ * <p>
+ * The resulting Value or ValueStream will be typed with the closest super-type of the two non-conditional parameters.
+ * (e.g. {@value #name}(boolean,double,int) will return a double)
+ * If two {@link AnalyticsValue}s are passed as the if-else parameters, an {@link AnalyticsValue} will be returned.
+ * If either parameter isn't single-valued, a {@link AnalyticsValueStream} will be returned.
+ */
+public class IfFunction implements AnalyticsValueStream {
+  private final BooleanValue ifExpr;
+  private final AnalyticsValueStream thenExpr;
+  private final AnalyticsValueStream elseExpr;
+  public static final String name = "if";
+  private final String exprStr;
+  private final ExpressionType funcType;
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 3) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 3 paramaters, " + params.length + " found.");
+    }
+    if (!(params[0] instanceof BooleanValue)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires single-valued numeric parameters. " + 
+                      "Incorrect parameter: "+params[0].getExpressionStr());
+    }
+    
+    BooleanValue castedIf = (BooleanValue) params[0];
+    AnalyticsValueStream thenExpr = params[1];
+    AnalyticsValueStream elseExpr = params[2];
+
+    if (thenExpr instanceof DateValue && elseExpr instanceof DateValue) {
+      return new DateIfFunction(castedIf,(DateValue)thenExpr,(DateValue)elseExpr);
+    }
+    if (thenExpr instanceof DateValueStream && elseExpr instanceof DateValueStream) {
+      return new DateStreamIfFunction(castedIf,(DateValueStream)thenExpr,(DateValueStream)elseExpr);
+    }
+    if (thenExpr instanceof BooleanValue && elseExpr instanceof BooleanValue) {
+      return new BooleanIfFunction(castedIf,(BooleanValue)thenExpr,(BooleanValue)elseExpr);
+    }
+    if (thenExpr instanceof BooleanValueStream && elseExpr instanceof BooleanValueStream) {
+      return new BooleanStreamIfFunction(castedIf,(BooleanValueStream)thenExpr,(BooleanValueStream)elseExpr);
+    }
+    if (thenExpr instanceof IntValue && elseExpr instanceof IntValue) {
+      return new IntIfFunction(castedIf,(IntValue)thenExpr,(IntValue)elseExpr);
+    }
+    if (thenExpr instanceof IntValueStream && elseExpr instanceof IntValueStream) {
+      return new IntStreamIfFunction(castedIf,(IntValueStream)thenExpr,(IntValueStream)elseExpr);
+    }
+    if (thenExpr instanceof LongValue && elseExpr instanceof LongValue) {
+      return new LongIfFunction(castedIf,(LongValue)thenExpr,(LongValue)elseExpr);
+    }
+    if (thenExpr instanceof LongValueStream && elseExpr instanceof LongValueStream) {
+      return new LongStreamIfFunction(castedIf,(LongValueStream)thenExpr,(LongValueStream)elseExpr);
+    }
+    if (thenExpr instanceof FloatValue && elseExpr instanceof FloatValue) {
+      return new FloatIfFunction(castedIf,(FloatValue)thenExpr,(FloatValue)elseExpr);
+    }
+    if (thenExpr instanceof FloatValueStream && elseExpr instanceof FloatValueStream) {
+      return new FloatStreamIfFunction(castedIf,(FloatValueStream)thenExpr,(FloatValueStream)elseExpr);
+    }
+    if (thenExpr instanceof DoubleValue && elseExpr instanceof DoubleValue) {
+      return new DoubleIfFunction(castedIf,(DoubleValue)thenExpr,(DoubleValue)elseExpr);
+    }
+    if (thenExpr instanceof DoubleValueStream && elseExpr instanceof DoubleValueStream) {
+      return new DoubleStreamIfFunction(castedIf,(DoubleValueStream)thenExpr,(DoubleValueStream)elseExpr);
+    }
+    if (thenExpr instanceof StringValue && elseExpr instanceof StringValue) {
+      return new StringIfFunction(castedIf,(StringValue)thenExpr,(StringValue)elseExpr);
+    }
+    if (thenExpr instanceof StringValueStream && elseExpr instanceof StringValueStream) {
+      return new StringStreamIfFunction(castedIf,(StringValueStream)thenExpr,(StringValueStream)elseExpr);
+    }
+    if (thenExpr instanceof AnalyticsValue && elseExpr instanceof AnalyticsValue) {
+      return new ValueIfFunction(castedIf,(AnalyticsValue)thenExpr,(AnalyticsValue)elseExpr);
+    }
+    return new IfFunction(castedIf,thenExpr,elseExpr);
+  });
+  
+  public IfFunction(BooleanValue ifExpr, AnalyticsValueStream thenExpr, AnalyticsValueStream elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        thenExpr.streamObjects(cons);
+      }
+      else {
+        elseExpr.streamObjects(cons);
+      }
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class ValueIfFunction extends AbstractAnalyticsValue {
+  private final BooleanValue ifExpr;
+  private final AnalyticsValue thenExpr;
+  private final AnalyticsValue elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public ValueIfFunction(BooleanValue ifExpr, AnalyticsValue thenExpr, AnalyticsValue elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public Object getObject() {
+    exists = false;
+    Object value = null;
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        value = thenExpr.getObject();
+        exists = thenExpr.exists();
+      }
+      else {
+        value = elseExpr.getObject();
+        exists = elseExpr.exists();
+      }
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanStreamIfFunction extends AbstractBooleanValueStream {
+  private final BooleanValue ifExpr;
+  private final BooleanValueStream thenExpr;
+  private final BooleanValueStream elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanStreamIfFunction(BooleanValue ifExpr, BooleanValueStream thenExpr, BooleanValueStream elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        thenExpr.streamBooleans(cons);
+      }
+      else {
+        elseExpr.streamBooleans(cons);
+      }
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class BooleanIfFunction extends AbstractBooleanValue {
+  private final BooleanValue ifExpr;
+  private final BooleanValue thenExpr;
+  private final BooleanValue elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public BooleanIfFunction(BooleanValue ifExpr, BooleanValue thenExpr, BooleanValue elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public boolean getBoolean() {
+    exists = false;
+    boolean value = false;
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        value = thenExpr.getBoolean();
+        exists = thenExpr.exists();
+      }
+      else {
+        value = elseExpr.getBoolean();
+        exists = elseExpr.exists();
+      }
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntStreamIfFunction extends AbstractIntValueStream {
+  private final BooleanValue ifExpr;
+  private final IntValueStream thenExpr;
+  private final IntValueStream elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntStreamIfFunction(BooleanValue ifExpr, IntValueStream thenExpr, IntValueStream elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  @Override
+  public void streamInts(IntConsumer cons) {
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        thenExpr.streamInts(cons);
+      }
+      else {
+        elseExpr.streamInts(cons);
+      }
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class IntIfFunction extends AbstractIntValue {
+  private final BooleanValue ifExpr;
+  private final IntValue thenExpr;
+  private final IntValue elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public IntIfFunction(BooleanValue ifExpr, IntValue thenExpr, IntValue elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public int getInt() {
+    exists = false;
+    int value = 0;
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        value = thenExpr.getInt();
+        exists = thenExpr.exists();
+      }
+      else {
+        value = elseExpr.getInt();
+        exists = elseExpr.exists();
+      }
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongStreamIfFunction extends AbstractLongValueStream {
+  private final BooleanValue ifExpr;
+  private final LongValueStream thenExpr;
+  private final LongValueStream elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongStreamIfFunction(BooleanValue ifExpr, LongValueStream thenExpr, LongValueStream elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        thenExpr.streamLongs(cons);
+      }
+      else {
+        elseExpr.streamLongs(cons);
+      }
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class LongIfFunction extends AbstractLongValue {
+  private final BooleanValue ifExpr;
+  private final LongValue thenExpr;
+  private final LongValue elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public LongIfFunction(BooleanValue ifExpr, LongValue thenExpr, LongValue elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public long getLong() {
+    exists = false;
+    long value = 0;
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        value = thenExpr.getLong();
+        exists = thenExpr.exists();
+      }
+      else {
+        value = elseExpr.getLong();
+        exists = elseExpr.exists();
+      }
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatStreamIfFunction extends AbstractFloatValueStream {
+  private final BooleanValue ifExpr;
+  private final FloatValueStream thenExpr;
+  private final FloatValueStream elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatStreamIfFunction(BooleanValue ifExpr, FloatValueStream thenExpr, FloatValueStream elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        thenExpr.streamFloats(cons);
+      }
+      else {
+        elseExpr.streamFloats(cons);
+      }
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class FloatIfFunction extends AbstractFloatValue {
+  private final BooleanValue ifExpr;
+  private final FloatValue thenExpr;
+  private final FloatValue elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public FloatIfFunction(BooleanValue ifExpr, FloatValue thenExpr, FloatValue elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public float getFloat() {
+    exists = false;
+    float value = 0;
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        value = thenExpr.getFloat();
+        exists = thenExpr.exists();
+      }
+      else {
+        value = elseExpr.getFloat();
+        exists = elseExpr.exists();
+      }
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DoubleStreamIfFunction extends AbstractDoubleValueStream {
+  private final BooleanValue ifExpr;
+  private final DoubleValueStream thenExpr;
+  private final DoubleValueStream elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DoubleStreamIfFunction(BooleanValue ifExpr, DoubleValueStream thenExpr, DoubleValueStream elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        thenExpr.streamDoubles(cons);
+      }
+      else {
+        elseExpr.streamDoubles(cons);
+      }
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DoubleIfFunction extends AbstractDoubleValue {
+  private final BooleanValue ifExpr;
+  private final DoubleValue thenExpr;
+  private final DoubleValue elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DoubleIfFunction(BooleanValue ifExpr, DoubleValue thenExpr, DoubleValue elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public double getDouble() {
+    exists = false;
+    double value = 0;
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        value = thenExpr.getDouble();
+        exists = thenExpr.exists();
+      }
+      else {
+        value = elseExpr.getDouble();
+        exists = elseExpr.exists();
+      }
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DateStreamIfFunction extends AbstractDateValueStream {
+  private final BooleanValue ifExpr;
+  private final DateValueStream thenExpr;
+  private final DateValueStream elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateStreamIfFunction(BooleanValue ifExpr, DateValueStream thenExpr, DateValueStream elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        thenExpr.streamLongs(cons);
+      }
+      else {
+        elseExpr.streamLongs(cons);
+      }
+    }
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class DateIfFunction extends AbstractDateValue {
+  private final BooleanValue ifExpr;
+  private final DateValue thenExpr;
+  private final DateValue elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public DateIfFunction(BooleanValue ifExpr, DateValue thenExpr, DateValue elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public long getLong() {
+    exists = false;
+    long value = 0;
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        value = thenExpr.getLong();
+        exists = thenExpr.exists();
+      }
+      else {
+        value = elseExpr.getLong();
+        exists = elseExpr.exists();
+      }
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringStreamIfFunction extends AbstractStringValueStream {
+  private final BooleanValue ifExpr;
+  private final StringValueStream thenExpr;
+  private final StringValueStream elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StringStreamIfFunction(BooleanValue ifExpr, StringValueStream thenExpr, StringValueStream elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        thenExpr.streamStrings(cons);
+      }
+      else {
+        elseExpr.streamStrings(cons);
+      }
+    }
+  }
+  
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
+class StringIfFunction extends AbstractStringValue {
+  private final BooleanValue ifExpr;
+  private final StringValue thenExpr;
+  private final StringValue elseExpr;
+  public static final String name = IfFunction.name;
+  private final String exprStr;
+  private final ExpressionType funcType;
+  
+  public StringIfFunction(BooleanValue ifExpr, StringValue thenExpr, StringValue elseExpr) throws SolrException {
+    this.ifExpr = ifExpr;
+    this.thenExpr = thenExpr;
+    this.elseExpr = elseExpr;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,ifExpr,thenExpr,elseExpr);
+    this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,ifExpr,thenExpr,elseExpr);
+  }
+
+  private boolean exists = false;
+
+  @Override
+  public String getString() {
+    exists = false;
+    String value = null;
+    boolean ifValue = ifExpr.getBoolean();
+    if (ifExpr.exists()) {
+      if (ifValue) {
+        value = thenExpr.getString();
+        exists = thenExpr.exists();
+      }
+      else {
+        value = elseExpr.getString();
+        exists = elseExpr.exists();
+      }
+    }
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  @Override
+  public ExpressionType getExpressionType() {
+    return funcType;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/JoinFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/JoinFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/JoinFunction.java
new file mode 100644
index 0000000..528aae2
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/JoinFunction.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.mapping;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.constant.ConstantStringValue;
+
+/**
+ * A string join mapping function.
+ * <p>
+ * Takes a {@link StringValueStream} as the first parameter and a {@link ConstantStringValue} (e.g. ",") as the second parameter
+ * and a {@link StringValue} is returned.
+ * <br>
+ * The second parameter is used as the separator while joining all values the first parameter has for a document.
+ * No order is guaranteed while joining the string values
+ */
+public class JoinFunction {
+  public static final String name = "join";
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 2) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 parameters.");
+    } 
+    AnalyticsValueStream param1 = params[0];
+    AnalyticsValueStream param2 = params[1];
+    if (!(param2 instanceof ConstantStringValue)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires the second parameter to be a constant string");
+    }
+    String sep = ((StringValue)param2).getString();
+    if (!(param1 instanceof StringValueStream)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires the first parameter to be castable to a string");
+    }
+    if (param1 instanceof StringValue) {
+      return param1;
+    }
+    String uniqueName = name + "(" + sep + ")";
+    return LambdaFunction.createStringLambdaFunction(uniqueName, (a,b) -> a + sep + b, (StringValueStream)params[0]);
+  });
+}
\ No newline at end of file


[11/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/UniqueFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/UniqueFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/UniqueFunction.java
new file mode 100644
index 0000000..f62f7d9
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/UniqueFunction.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+import java.util.function.UnaryOperator;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.function.reduction.data.ReductionDataCollector;
+import org.apache.solr.analytics.function.reduction.data.UniqueCollector;
+import org.apache.solr.analytics.function.reduction.data.UniqueCollector.UniqueDoubleCollector;
+import org.apache.solr.analytics.function.reduction.data.UniqueCollector.UniqueFloatCollector;
+import org.apache.solr.analytics.function.reduction.data.UniqueCollector.UniqueIntCollector;
+import org.apache.solr.analytics.function.reduction.data.UniqueCollector.UniqueLongCollector;
+import org.apache.solr.analytics.function.reduction.data.UniqueCollector.UniqueStringCollector;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.LongValue.AbstractLongValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A reduction function which returns the number of unique values of the given expression.
+ */
+public class UniqueFunction extends AbstractLongValue implements ReductionFunction {
+  private UniqueCollector<?> collector;
+  public static final String name = "unique";
+  private final String exprStr;
+  public static final CreatorFunction creatorFunction = (params -> {
+    if (params.length != 1) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+    }
+    AnalyticsValueStream param = params[0];
+    UniqueCollector<?> collector;
+    if (param instanceof IntValueStream) {
+      collector = new UniqueIntCollector((IntValueStream)param);
+    } else if (param instanceof LongValueStream) {
+      collector = new UniqueLongCollector((LongValueStream)param);
+    } else if (param instanceof FloatValueStream) {
+      collector = new UniqueFloatCollector((FloatValueStream)param);
+    } else if (param instanceof DoubleValueStream) {
+      collector = new UniqueDoubleCollector((DoubleValueStream)param);
+    } else if (param instanceof StringValueStream) {
+      collector = new UniqueStringCollector((StringValueStream)param);
+    } else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter.");
+    }
+    return new UniqueFunction(param, collector);
+  });
+  
+  public UniqueFunction(AnalyticsValueStream param, UniqueCollector<?> collector) {
+    this.collector = collector;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+
+  @Override
+  public long getLong() {
+    return collector.count();
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void synchronizeDataCollectors(UnaryOperator<ReductionDataCollector<?>> sync) {
+    collector = (UniqueCollector<?>)sync.apply(collector);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.REDUCTION;
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/CountCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/CountCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/CountCollector.java
new file mode 100644
index 0000000..135b587
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/CountCollector.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction.data;
+
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.stream.reservation.LongReservation;
+import org.apache.solr.analytics.stream.reservation.ReductionDataReservation;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+
+public abstract class CountCollector extends ReductionDataCollector<CountCollector.CountData> {
+  public static final String name = "count";
+  private final String exprStr;
+  
+  public CountCollector(String exprStr) {
+    this.exprStr = exprStr;
+  }
+
+  private long count;
+  private long docCount;
+
+  /**
+   * The number of Solr Documents for which the given analytics expression exists.
+   * 
+   * @return the count
+   */
+  public long count() {
+    return count;
+  }
+  /**
+   * The number of Solr Documents used in this reduction.
+   * 
+   * @return the number of documents
+   */
+  public long docCount() {
+    return docCount;
+  }
+
+  @Override
+  public CountData newData() {
+    CountData data = new CountData();
+    data.count = 0;
+    data.missing = 0;
+    data.docCount = 0;
+    return data;
+  }
+
+  @Override
+  public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+    // Count
+    consumer.accept(new LongReservation(
+        value -> ioData.count += value,
+        () -> ioData.count
+      ));
+    // DocCount
+    consumer.accept(new LongReservation(
+        value -> ioData.docCount += value,
+        () -> ioData.docCount
+      ));
+  }
+
+  @Override
+  public void setMergedData(ReductionData data) {
+    count = ((CountData)data).count;
+    docCount = ((CountData)data).docCount;
+  }
+
+  @Override
+  public void setData(ReductionData data) {
+    count = ((CountData)data).count;
+    docCount = ((CountData)data).docCount;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  
+  public static class CountData extends ReductionData {
+    long count;
+    long missing;
+    long docCount;
+  }
+
+  /**
+   * Represents a {@code count(expr)} expression. This collects 3 values:
+   * 
+   * docCount - The number of Solr Documents for which the wrapped expression exists.
+   * count - The number of values which wrapped expression contains.
+   * missing - The number of Solr Documents for which the wrapped expression does not exist.
+   */
+  public static class ExpressionCountCollector extends CountCollector {
+    private final AnalyticsValueStream param;
+    
+    public ExpressionCountCollector(AnalyticsValueStream param) {
+      super(AnalyticsValueStream.createExpressionString(name, param));
+      this.param = param;
+    }
+    
+    private long missing;
+    
+    /**
+     * The number of Solr Documents for which the given analytics expression does not exist.
+     * 
+     * @return the number of missing values
+     */
+    public long missing() {
+      return missing;
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setMergedData(data);
+      missing = ((CountData)data).missing;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      missing = ((CountData)data).missing;
+    }
+    
+    long tempCount;
+    int tempMissing;
+    int tempDocCount;
+    @Override
+    public void collect() {
+      tempCount = 0;
+      param.streamObjects( obj -> {
+        ++tempCount;
+      });
+      tempMissing = tempCount == 0 ? 1 : 0;
+      tempDocCount = tempCount > 0 ? 1 : 0;
+    }
+    
+    @Override
+    protected void apply(CountData data) {
+      data.count += tempCount;
+      data.missing += tempMissing;
+      data.docCount += tempDocCount;
+    }
+
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      super.submitReservations(consumer);
+      // Missing
+      consumer.accept(new LongReservation(
+          value -> ioData.missing += value,
+          () -> ioData.missing
+        ));
+    }
+  }
+  
+  /**
+   * Represents a {@code count()} expression. This collects the number of Solr Documents used in a result set.
+   */
+  public static class TotalCountCollector extends CountCollector {
+    
+    public TotalCountCollector() {
+      super(AnalyticsValueStream.createExpressionString(name));
+    }
+    
+    @Override
+    protected void apply(CountData data) {
+      data.count += 1;
+      data.docCount += 1;
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/MaxCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/MaxCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/MaxCollector.java
new file mode 100644
index 0000000..bf49907
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/MaxCollector.java
@@ -0,0 +1,476 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction.data;
+
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.stream.reservation.DoubleCheckedReservation;
+import org.apache.solr.analytics.stream.reservation.FloatCheckedReservation;
+import org.apache.solr.analytics.stream.reservation.IntCheckedReservation;
+import org.apache.solr.analytics.stream.reservation.LongCheckedReservation;
+import org.apache.solr.analytics.stream.reservation.ReductionDataReservation;
+import org.apache.solr.analytics.stream.reservation.StringCheckedReservation;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+
+/**
+ * Collector of max values.
+ * <p>
+ * Supported types are:
+ * <ul>
+ * <li>Int
+ * <li>Long
+ * <li>Float
+ * <li>Double
+ * <li>Date (through longs)
+ * <li>String
+ * </ul>
+ *
+ * @param <T> The type of data being processed.
+ */
+public abstract class MaxCollector<T extends ReductionData> extends ReductionDataCollector<T> {
+  public static final String name = "max";
+  private final String exprStr;
+  
+  protected MaxCollector(AnalyticsValueStream param) {
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+  
+  private boolean exists;
+  
+  /**
+   * Returns true if any of the values being reduce exist, and false if none of them do.
+   * 
+   * @return whether a max value exists
+   */
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public void setMergedData(ReductionData data) {
+    exists = data.exists;
+  }
+
+  @Override
+  public void setData(ReductionData data) {
+    exists = data.exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  public static class IntMaxCollector extends MaxCollector<IntMaxCollector.MaxData> {
+    private IntValueStream param;
+    
+    public IntMaxCollector(IntValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public MaxData newData() {
+      MaxData data = new MaxData();
+      data.exists = false;
+      return data;
+    }
+
+    int max;
+    
+    /**
+     * Returns the max value of the set data.
+     * 
+     * @return the max
+     */
+    public int max() {
+      return max;
+    }
+
+    int tempMax;
+    boolean tempExists;
+    @Override
+    public void collect() {
+      tempExists = false;
+      param.streamInts( val -> {
+        if (!tempExists || val > tempMax) {
+          tempMax = val;
+          tempExists = true;
+        }
+      });
+    }
+    @Override
+    protected void apply(MaxData data) {
+      if (tempExists && (!data.exists || tempMax > data.val)) {
+        data.val = tempMax;
+        data.exists = true;
+      }
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new IntCheckedReservation(
+          value -> {
+            if (!ioData.exists || value > ioData.val) {
+              ioData.val = value;
+              ioData.exists = true;
+            }
+          },
+          ()-> ioData.val,
+          ()-> ioData.exists
+        ));
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setData(data);
+      max = ((MaxData)data).val;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      max = ((MaxData)data).val;
+    }
+    
+    public static class MaxData extends ReductionData {
+      int val;
+    }
+  }
+  
+
+
+  public static class LongMaxCollector extends MaxCollector<LongMaxCollector.MaxData> {
+    private LongValueStream param;
+    
+    public LongMaxCollector(LongValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public MaxData newData() {
+      MaxData data = new MaxData();
+      data.exists = false;
+      return data;
+    }
+
+    long max;
+    
+    /**
+     * Returns the max value of the set data.
+     * 
+     * @return the max
+     */
+    public long max() {
+      return max;
+    }
+
+    long tempMax;
+    boolean tempExists;
+    @Override
+    public void collect() {
+      tempExists = false;
+      param.streamLongs( val -> {
+        if (!tempExists || val > tempMax) {
+          tempMax = val;
+          tempExists = true;
+        }
+      });
+    }
+    @Override
+    protected void apply(MaxData data) {
+      if (tempExists && (!data.exists || tempMax > data.val)) {
+        data.val = tempMax;
+        data.exists = true;
+      }
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new LongCheckedReservation(
+          value -> {
+            if (!ioData.exists || value > ioData.val) {
+              ioData.val = value;
+              ioData.exists = true;
+            }
+          },
+          ()-> ioData.val,
+          ()-> ioData.exists
+        ));
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setData(data);
+      max = ((MaxData)data).val;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      max = ((MaxData)data).val;
+    }
+    
+    public static class MaxData extends ReductionData {
+      long val;
+    }
+  }
+
+  public static class FloatMaxCollector extends MaxCollector<FloatMaxCollector.MaxData> {
+    private FloatValueStream param;
+    
+    public FloatMaxCollector(FloatValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public MaxData newData() {
+      MaxData data = new MaxData();
+      data.exists = false;
+      return data;
+    }
+
+    float max;
+    
+    /**
+     * Returns the max value of the set data.
+     * 
+     * @return the max
+     */
+    public float max() {
+      return max;
+    }
+
+    float tempMax;
+    boolean tempExists;
+    @Override
+    public void collect() {
+      tempExists = false;
+      param.streamFloats( val -> {
+        if (!tempExists || val > tempMax) {
+          tempMax = val;
+          tempExists = true;
+        }
+      });
+    }
+    @Override
+    protected void apply(MaxData data) {
+      if (tempExists && (!data.exists || tempMax > data.val)) {
+        data.val = tempMax;
+        data.exists = true;
+      }
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new FloatCheckedReservation(
+          value -> {
+            if (!ioData.exists || value > ioData.val) {
+              ioData.val = value;
+              ioData.exists = true;
+            }
+          },
+          ()-> ioData.val,
+          ()-> ioData.exists
+        ));
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setData(data);
+      max = ((MaxData)data).val;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      max = ((MaxData)data).val;
+    }
+    
+    public static class MaxData extends ReductionData {
+      float val;
+    }
+  }
+
+  public static class DoubleMaxCollector extends MaxCollector<DoubleMaxCollector.MaxData> {
+    private DoubleValueStream param;
+    
+    public DoubleMaxCollector(DoubleValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public MaxData newData() {
+      MaxData data = new MaxData();
+      data.exists = false;
+      return data;
+    }
+
+    double max;
+    
+    /**
+     * Returns the max value of the set data.
+     * 
+     * @return the max
+     */
+    public double max() {
+      return max;
+    }
+
+    double tempMax;
+    boolean tempExists;
+    @Override
+    public void collect() {
+      tempExists = false;
+      param.streamDoubles( val -> {
+        if (!tempExists || val > tempMax) {
+          tempMax = val;
+          tempExists = true;
+        }
+      });
+    }
+    @Override
+    protected void apply(MaxData data) {
+      if (tempExists && (!data.exists || tempMax > data.val)) {
+        data.val = tempMax;
+        data.exists = true;
+      }
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new DoubleCheckedReservation(
+          value -> {
+            if (!ioData.exists || value > ioData.val) {
+              ioData.val = value;
+              ioData.exists = true;
+            }
+          },
+          ()-> ioData.val,
+          ()-> ioData.exists
+        ));
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setData(data);
+      max = ((MaxData)data).val;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      max = ((MaxData)data).val;
+    }
+    
+    public static class MaxData extends ReductionData {
+      double val;
+    }
+  }
+  
+
+
+  public static class StringMaxCollector extends MaxCollector<StringMaxCollector.MaxData> {
+    private StringValueStream param;
+    
+    public StringMaxCollector(StringValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public MaxData newData() {
+      MaxData data = new MaxData();
+      data.exists = false;
+      return data;
+    }
+
+    String max;
+    
+    /**
+     * Returns the max value of the set data.
+     * 
+     * @return the max
+     */
+    public String max() {
+      return max;
+    }
+
+    String tempMax;
+    boolean tempExists;
+    @Override
+    public void collect() {
+      tempExists = false;
+      param.streamStrings( val -> {
+        if (!tempExists || val.compareTo(tempMax) > 0) {
+          tempMax = val;
+          tempExists = true;
+        }
+      });
+    }
+    @Override
+    protected void apply(MaxData data) {
+      if (tempExists && (!data.exists || tempMax.compareTo(data.val) > 0)) {
+        data.val = tempMax;
+        data.exists = true;
+      }
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new StringCheckedReservation(
+          value -> {
+            if (!ioData.exists || value.compareTo(ioData.val) > 0) {
+              ioData.val = value;
+              ioData.exists = true;
+            }
+          },
+          ()-> ioData.val,
+          ()-> ioData.exists
+        ));
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setData(data);
+      max = ((MaxData)data).val;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      max = ((MaxData)data).val;
+    }
+    
+    public static class MaxData extends ReductionData {
+      String val;
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/MinCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/MinCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/MinCollector.java
new file mode 100644
index 0000000..3a33660
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/MinCollector.java
@@ -0,0 +1,476 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction.data;
+
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.stream.reservation.DoubleCheckedReservation;
+import org.apache.solr.analytics.stream.reservation.FloatCheckedReservation;
+import org.apache.solr.analytics.stream.reservation.IntCheckedReservation;
+import org.apache.solr.analytics.stream.reservation.LongCheckedReservation;
+import org.apache.solr.analytics.stream.reservation.ReductionDataReservation;
+import org.apache.solr.analytics.stream.reservation.StringCheckedReservation;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+
+/**
+ * Collector of min values.
+ * <p>
+ * Supported types are:
+ * <ul>
+ * <li>Int
+ * <li>Long
+ * <li>Float
+ * <li>Double
+ * <li>Date (through longs)
+ * <li>String
+ * </ul>
+ *
+ * @param <T> The type of data being processed.
+ */
+public abstract class MinCollector<T extends ReductionData> extends ReductionDataCollector<T> {
+  public static final String name = "min";
+  private final String exprStr;
+  
+  protected MinCollector(AnalyticsValueStream param) {
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+  
+  private boolean exists;
+  
+  /**
+   * Returns true if any of the values being reduce exist, and false if none of them do.
+   * 
+   * @return whether a min value exists
+   */
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public void setMergedData(ReductionData data) {
+    exists = data.exists;
+  }
+
+  @Override
+  public void setData(ReductionData data) {
+    exists = data.exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  public static class IntMinCollector extends MinCollector<IntMinCollector.MinData> {
+    private IntValueStream param;
+    
+    public IntMinCollector(IntValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public MinData newData() {
+      MinData data = new MinData();
+      data.exists = false;
+      return data;
+    }
+
+    int min;
+    
+    /**
+     * Returns the min value of the set data.
+     * 
+     * @return the min
+     */
+    public int min() {
+      return min;
+    }
+
+    int tempMin;
+    boolean tempExists;
+    @Override
+    public void collect() {
+      tempExists = false;
+      param.streamInts( val -> {
+        if (!tempExists || val < tempMin) {
+          tempMin = val;
+          tempExists = true;
+        }
+      });
+    }
+    @Override
+    protected void apply(MinData data) {
+      if (tempExists && (!data.exists || tempMin < data.val)) {
+        data.val = tempMin;
+        data.exists = true;
+      }
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new IntCheckedReservation(
+          value -> {
+            if (!ioData.exists || value < ioData.val) {
+              ioData.val = value;
+              ioData.exists = true;
+            }
+          },
+          ()-> ioData.val,
+          ()-> ioData.exists
+        ));
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setData(data);
+      min = ((MinData)data).val;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      min = ((MinData)data).val;
+    }
+    
+    public static class MinData extends ReductionData {
+      int val;
+    }
+  }
+  
+
+
+  public static class LongMinCollector extends MinCollector<LongMinCollector.MinData> {
+    private LongValueStream param;
+    
+    public LongMinCollector(LongValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public MinData newData() {
+      MinData data = new MinData();
+      data.exists = false;
+      return data;
+    }
+
+    long min;
+    
+    /**
+     * Returns the min value of the set data.
+     * 
+     * @return the min
+     */
+    public long min() {
+      return min;
+    }
+
+    long tempMin;
+    boolean tempExists;
+    @Override
+    public void collect() {
+      tempExists = false;
+      param.streamLongs( val -> {
+        if (!tempExists || val < tempMin) {
+          tempMin = val;
+          tempExists = true;
+        }
+      });
+    }
+    @Override
+    protected void apply(MinData data) {
+      if (tempExists && (!data.exists || tempMin < data.val)) {
+        data.val = tempMin;
+        data.exists = true;
+      }
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new LongCheckedReservation(
+          value -> {
+            if (!ioData.exists || value < ioData.val) {
+              ioData.val = value;
+              ioData.exists = true;
+            }
+          },
+          ()-> ioData.val,
+          ()-> ioData.exists
+        ));
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setData(data);
+      min = ((MinData)data).val;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      min = ((MinData)data).val;
+    }
+    
+    public static class MinData extends ReductionData {
+      long val;
+    }
+  }
+
+  public static class FloatMinCollector extends MinCollector<FloatMinCollector.MinData> {
+    private FloatValueStream param;
+    
+    public FloatMinCollector(FloatValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public MinData newData() {
+      MinData data = new MinData();
+      data.exists = false;
+      return data;
+    }
+
+    float min;
+    
+    /**
+     * Returns the min value of the set data.
+     * 
+     * @return the min
+     */
+    public float min() {
+      return min;
+    }
+
+    float tempMin;
+    boolean tempExists;
+    @Override
+    public void collect() {
+      tempExists = false;
+      param.streamFloats( val -> {
+        if (!tempExists || val < tempMin) {
+          tempMin = val;
+          tempExists = true;
+        }
+      });
+    }
+    @Override
+    protected void apply(MinData data) {
+      if (tempExists && (!data.exists || tempMin < data.val)) {
+        data.val = tempMin;
+        data.exists = true;
+      }
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new FloatCheckedReservation(
+          value -> {
+            if (!ioData.exists || value < ioData.val) {
+              ioData.val = value;
+              ioData.exists = true;
+            }
+          },
+          ()-> ioData.val,
+          ()-> ioData.exists
+        ));
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setData(data);
+      min = ((MinData)data).val;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      min = ((MinData)data).val;
+    }
+    
+    public static class MinData extends ReductionData {
+      float val;
+    }
+  }
+
+  public static class DoubleMinCollector extends MinCollector<DoubleMinCollector.MinData> {
+    private DoubleValueStream param;
+    
+    public DoubleMinCollector(DoubleValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public MinData newData() {
+      MinData data = new MinData();
+      data.exists = false;
+      return data;
+    }
+
+    double min;
+    
+    /**
+     * Returns the min value of the set data.
+     * 
+     * @return the min
+     */
+    public double min() {
+      return min;
+    }
+
+    double tempMin;
+    boolean tempExists;
+    @Override
+    public void collect() {
+      tempExists = false;
+      param.streamDoubles( val -> {
+        if (!tempExists || val < tempMin) {
+          tempMin = val;
+          tempExists = true;
+        }
+      });
+    }
+    @Override
+    protected void apply(MinData data) {
+      if (tempExists && (!data.exists || tempMin < data.val)) {
+        data.val = tempMin;
+        data.exists = true;
+      }
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new DoubleCheckedReservation(
+          value -> {
+            if (!ioData.exists || value < ioData.val) {
+              ioData.val = value;
+              ioData.exists = true;
+            }
+          },
+          ()-> ioData.val,
+          ()-> ioData.exists
+        ));
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setData(data);
+      min = ((MinData)data).val;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      min = ((MinData)data).val;
+    }
+    
+    public static class MinData extends ReductionData {
+      double val;
+    }
+  }
+  
+
+
+  public static class StringMinCollector extends MinCollector<StringMinCollector.MinData> {
+    private StringValueStream param;
+    
+    public StringMinCollector(StringValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public MinData newData() {
+      MinData data = new MinData();
+      data.exists = false;
+      return data;
+    }
+
+    String min;
+    
+    /**
+     * Returns the min value of the set data.
+     * 
+     * @return the min
+     */
+    public String min() {
+      return min;
+    }
+
+    String tempMin;
+    boolean tempExists;
+    @Override
+    public void collect() {
+      tempExists = false;
+      param.streamStrings( val -> {
+        if (!tempExists || val.compareTo(tempMin) < 0) {
+          tempMin = val;
+          tempExists = true;
+        }
+      });
+    }
+    @Override
+    protected void apply(MinData data) {
+      if (tempExists && (!data.exists || tempMin.compareTo(data.val) < 0)) {
+        data.val = tempMin;
+        data.exists = true;
+      }
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new StringCheckedReservation(
+          value -> {
+            if (!ioData.exists || value.compareTo(ioData.val) < 0) {
+              ioData.val = value;
+              ioData.exists = true;
+            }
+          },
+          ()-> ioData.val,
+          ()-> ioData.exists
+        ));
+    }
+
+    @Override
+    public void setMergedData(ReductionData data) {
+      super.setData(data);
+      min = ((MinData)data).val;
+    }
+
+    @Override
+    public void setData(ReductionData data) {
+      super.setData(data);
+      min = ((MinData)data).val;
+    }
+    
+    public static class MinData extends ReductionData {
+      String val;
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/ReductionData.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/ReductionData.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/ReductionData.java
new file mode 100644
index 0000000..8c265fd
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/ReductionData.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction.data;
+
+/**
+ * Base class to store data for {@link ReductionDataCollector}s
+ */
+public class ReductionData {
+  public boolean exists;
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/ReductionDataCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/ReductionDataCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/ReductionDataCollector.java
new file mode 100644
index 0000000..9674d98
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/ReductionDataCollector.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction.data;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.function.ReductionFunction;
+import org.apache.solr.analytics.stream.reservation.ReductionDataReservation;
+import org.apache.solr.analytics.value.AnalyticsValue;
+
+/**
+ * Manager of a specific instance of {@link ReductionData} collection. 
+ * 
+ * @param <T> the type of reduction data being collected
+ */
+public abstract class ReductionDataCollector<T extends ReductionData> {
+
+  protected ArrayList<T> lastingTargets;
+  protected ArrayList<T> collectionTargets;
+  protected T ioData;
+  
+  protected ReductionDataCollector() {
+    lastingTargets = new ArrayList<>();
+    collectionTargets = new ArrayList<>();
+  }
+  
+  /**
+   * Submits the data reservations needed for this data collector.
+   * 
+   * @param consumer the consumer which the reservations are submitted to
+   */
+  public abstract void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer);
+
+  /**
+   * A clean slate to start a new reduction.
+   * 
+   * @return the new reduction data
+   */
+  public abstract T newData();
+  
+  /**
+   * Add a reduction data to target during collection.
+   * The given target is valid until the lasting targets are cleared.
+   * 
+   * @param data the data to target
+   */
+  @SuppressWarnings("unchecked")
+  public void addLastingCollectTarget(ReductionData data) {
+    lastingTargets.add((T) data);
+  }
+  
+  /**
+   * Clear the lasting collection targets. After this is called the current lasting
+   * targets will not be affected by future {@link #collectAndApply()} calls. 
+   */
+  public void clearLastingCollectTargets() {
+    lastingTargets.clear();
+  }
+  
+  /**
+   * Create a new reduction data to target during collection.
+   * The given target is only valid for one call to {@link #collectAndApply()}.
+   * 
+   * @return the reduction data created
+   */
+  public T newDataTarget() {
+    T data = newData();
+    collectionTargets.add(data);
+    return data;
+  }
+  
+  /**
+   * Add a reduction data to target during collection.
+   * The given target is only valid for one call to {@link #collectAndApply()}.
+   * 
+   * @param data the data to target
+   */
+  @SuppressWarnings("unchecked")
+  public void addCollectTarget(ReductionData data) {
+    collectionTargets.add((T)data);
+  }
+
+  /**
+   * Collect the info for the current Solr Document and apply the results to the
+   * given collection targets.
+   * 
+   * After application, all non-lasting targets are removed.
+   */
+  public void collectAndApply() {
+    collect();
+    lastingTargets.forEach( target -> apply(target) );
+    collectionTargets.forEach( target -> apply(target) );
+    collectionTargets.clear();
+  }
+  
+  /**
+   * Collect the information from current Solr Document.
+   */
+  protected void collect() { }
+  
+  /**
+   * Apply the collected info to the given reduction data.
+   * Should always be called after a {@link #collect()} call.
+   * 
+   * @param data reduction data to apply collected info to
+   */
+  protected abstract void apply(T data);
+  
+  /**
+   * Create a new reduction data to use in exporting and merging.
+   * 
+   * @return the created reduction data
+   */
+  public T newDataIO() {
+    ioData = newData();
+    return ioData;
+  }
+  
+  /**
+   * Set the reduction data to use in exporting and merging.
+   * 
+   * @param data the data to use
+   */
+  @SuppressWarnings("unchecked")
+  public void dataIO(ReductionData data) {
+    ioData = (T)data;
+  }
+
+  /**
+   * Finalize the reduction with the merged data stored in the parameter.
+   * Once the reduction is finalized, the {@link ReductionFunction}s that use this 
+   * data collector act like regular {@link AnalyticsValue} classes that 
+   * can be accessed through their {@code get<value-type>} methods.
+   * 
+   * (FOR CLOUD)
+   * 
+   * @param data the merged data to compute a reduction for
+   */
+  public abstract void setMergedData(ReductionData data);
+
+  /**
+   * Finalize the reduction with the collected data stored in the parameter.
+   * Once the reduction is finalized, the {@link ReductionFunction}s that use this 
+   * data collector act like regular {@link AnalyticsValue} classes that 
+   * can be accessed through their {@code get<value-type>} methods.
+   * 
+   * (FOR SINGLE-SHARD)
+   * 
+   * @param data the collected data to compute a reduction for
+   */
+  public abstract void setData(ReductionData data);
+  
+  /**
+   * Get the name of the reduction data collector. This is the same across all instances of the data collector.
+   * 
+   * @return the name
+   */
+  public abstract String getName();
+  
+  /**
+   * The unique expression string of the reduction data collector, given all inputs and parameters.
+   * Used during {@link ReductionDataCollector} syncing. Since the string should be unique,
+   * only one of expression is kept.
+   * 
+   * @return the expression string 
+   */
+  public abstract String getExpressionStr();
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/SortedListCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/SortedListCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/SortedListCollector.java
new file mode 100644
index 0000000..c0de54b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/SortedListCollector.java
@@ -0,0 +1,363 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction.data;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.stream.reservation.DoubleArrayReservation;
+import org.apache.solr.analytics.stream.reservation.FloatArrayReservation;
+import org.apache.solr.analytics.stream.reservation.IntArrayReservation;
+import org.apache.solr.analytics.stream.reservation.LongArrayReservation;
+import org.apache.solr.analytics.stream.reservation.ReductionDataReservation;
+import org.apache.solr.analytics.stream.reservation.StringArrayReservation;
+import org.apache.solr.analytics.util.OrdinalCalculator;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+
+/**
+ * Collector of sorted lists.
+ * 
+ * Once the sorted list has been collected, it can be reduced by calculating a median, percentiles, or ordinals.
+ * All of the above reductions over the same data share one {@link SortedListCollector}.
+ * <p>
+ * Supported types are:
+ * <ul>
+ * <li>Int
+ * <li>Long
+ * <li>Float
+ * <li>Double
+ * <li>Date (through longs)
+ * <li>String
+ * </ul>
+ *
+ * @param <T> The type of data being processed.
+ */
+public abstract class SortedListCollector<T extends Comparable<T>> extends ReductionDataCollector<SortedListCollector.SortedListData<T>> {
+  public static final String name = "sorted";
+  private final String exprStr;
+  
+  protected SortedListCollector(AnalyticsValueStream param, String specificationName) {
+    this.exprStr = AnalyticsValueStream.createExpressionString(name + "_" + specificationName,param);
+    
+    tempList = new ArrayList<>();
+    
+    calcMedian = false;
+    calcPercs = new HashSet<>();
+    calcOrds = new HashSet<>();
+    calcRevOrds = new HashSet<>();
+  }
+  
+  private List<T> list;
+  
+  private boolean calcMedian;
+  private Set<Double> calcPercs;
+  private Set<Integer> calcOrds;
+  private Set<Integer> calcRevOrds;
+
+  public int size() {
+    return list.size();
+  }
+
+  /**
+   * Informs the collector that the median needs to be computed.
+   */
+  public void calcMedian() {
+    calcMedian = true;
+  }
+  
+  /**
+   * Informs the collector that the following percentile needs to be computed.
+   * 
+   * @param percentile requested percentile
+   */
+  public void calcPercentile(double percentile) {
+    calcPercs.add(percentile);
+  }
+
+  /**
+   * Informs the collector that the following ordinal needs to be computed.
+   * 
+   * @param ordinal requested ordinal
+   */
+  public void calcOrdinal(int ordinal) {
+    calcOrds.add(ordinal);
+  }
+
+  /**
+   * Informs the collector that the following reverse ordinal needs to be computed.
+   * Reverse ordinals are ordinals that start at the end of the list.
+   * 
+   * @param reverseOrdinal requested reverseOrdinal
+   */
+  public void calcReverseOrdinal(int reverseOrdinal) {
+    calcRevOrds.add(reverseOrdinal);
+  }
+
+  /**
+   * Once the data has been set by either {@link #setData} or {@link #setMergedData},
+   * this returns the value at the given sorted index. 
+   * 
+   * Only the indices specified by {@link #calcMedian}, {@link #calcPercentile}, {@link #calcOrdinal}, and {@link #calcReverseOrdinal}
+   * will contain valid data. All other indices may return unsorted data.
+   * 
+   * @param index the index of the sorted data to return
+   */
+  public T get(int index) {
+    return list.get(index);
+  }
+
+  @Override
+  public SortedListData<T> newData() {
+    SortedListData<T> data = new SortedListData<>();
+    data.list = new ArrayList<T>();
+    data.exists = false;
+    return data;
+  }
+  
+  ArrayList<T> tempList; 
+  @Override
+  protected void apply(SortedListData<T> data) {
+    data.list.addAll(tempList);
+  }
+  
+  /**
+   * Starts the import of the shard data.
+   * 
+   * @param size the size of the incoming shard list
+   */
+  protected void startImport(int size) {
+    ioData.list.ensureCapacity(ioData.list.size() + size);
+  }
+  
+  /**
+   * Merges the current list with the incoming value.
+   * 
+   * @param value the next imported value to add
+   */
+  protected void importNext(T value) {
+    ioData.list.add(value);
+  }
+  
+  Iterator<T> iter;
+  /**
+   * The list to be exported is unsorted.
+   * The lists of all shards will be combined with the {@link #startImport} and {@link #importNext} methods.
+   * 
+   * @return the size of the list being exported.
+   */
+  public int startExport() {
+    iter = ioData.list.iterator();
+    return ioData.list.size();
+  }
+  /**
+   * Return the next value in the list.
+   * 
+   * @return the next sorted value
+   */
+  public T exportNext() {
+    return iter.next();
+  }
+
+  /**
+   * Put the given indices in their sorted positions
+   */
+  @Override
+  public void setMergedData(ReductionData data) {
+    setData(data);
+  }
+
+  /**
+   * This is where the given indices are put in their sorted positions.
+   * 
+   * Only the given indices are guaranteed to be in sorted order.
+   */
+  @SuppressWarnings("unchecked")
+  @Override
+  public void setData(ReductionData data) {
+    list = ((SortedListData<T>)data).list;
+    int size = list.size();
+    if (size <= 1) {
+      return;
+    }
+    
+    // Ordinals start at 0 and end at size-1
+    Set<Integer> ordinals = new HashSet<>();
+    for (double percentile : calcPercs) {
+      ordinals.add((int) Math.ceil(percentile * size) - 1);
+    }
+    ordinals.addAll(calcOrds);
+    for (int reverseOrdinal : calcRevOrds) {
+      ordinals.add(size + reverseOrdinal);
+    }
+    if (calcMedian) {
+      int mid = list.size() / 2;
+      ordinals.add(mid);
+      if (list.size() % 2 == 0) {
+        ordinals.add(mid - 1);
+      }
+    }
+    OrdinalCalculator.putOrdinalsInPosition(list, ordinals);
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  
+  public static class SortedListData<D extends Comparable<D>> extends ReductionData {
+    ArrayList<D> list;
+  }
+
+  public static class SortedIntListCollector extends SortedListCollector<Integer> {
+    private IntValueStream param;
+    
+    public SortedIntListCollector(IntValueStream param) {
+      super(param, "int");
+      this.param = param;
+    }
+
+    @Override
+    public void collect() {
+      tempList.clear();
+      param.streamInts( val -> tempList.add(val) );
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new IntArrayReservation(
+          value -> importNext(value),
+          importSize -> startImport(importSize),
+          () -> exportNext(),
+          () -> startExport()
+        ));
+    }
+  }
+  
+  public static class SortedLongListCollector extends SortedListCollector<Long> {
+    private LongValueStream param;
+    
+    public SortedLongListCollector(LongValueStream param) {
+      super(param, "long");
+      this.param = param;
+    }
+
+    @Override
+    public void collect() {
+      tempList.clear();
+      param.streamLongs( val -> tempList.add(val) );
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new LongArrayReservation(
+          value -> importNext(value),
+          importSize -> startImport(importSize),
+          () -> exportNext(),
+          () -> startExport()
+        ));
+    }
+  }
+  
+  public static class SortedFloatListCollector extends SortedListCollector<Float> {
+    private FloatValueStream param;
+    
+    public SortedFloatListCollector(FloatValueStream param) {
+      super(param, "float");
+      this.param = param;
+    }
+
+    @Override
+    public void collect() {
+      tempList.clear();
+      param.streamFloats( val -> tempList.add(val) );
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new FloatArrayReservation(
+          value -> importNext(value),
+          importSize -> startImport(importSize),
+          () -> exportNext(),
+          () -> startExport()
+        ));
+    }
+  }
+  
+  public static class SortedDoubleListCollector extends SortedListCollector<Double> {
+    private DoubleValueStream param;
+    
+    public SortedDoubleListCollector(DoubleValueStream param) {
+      super(param, "double");
+      this.param = param;
+    }
+
+    @Override
+    public void collect() {
+      tempList.clear();
+      param.streamDoubles( val -> tempList.add(val) );
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new DoubleArrayReservation(
+          value -> importNext(value),
+          importSize -> startImport(importSize),
+          () -> exportNext(),
+          () -> startExport()
+        ));
+    }
+  }
+  
+  public static class SortedStringListCollector extends SortedListCollector<String> {
+    private StringValueStream param;
+    
+    public SortedStringListCollector(StringValueStream param) {
+      super(param, "string");
+      this.param = param;
+    }
+
+    @Override
+    public void collect() {
+      tempList.clear();
+      param.streamStrings( val -> tempList.add(val) );
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new StringArrayReservation(
+          value -> importNext(value),
+          importSize -> startImport(importSize),
+          () -> exportNext(),
+          () -> startExport()
+        ));
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/SumCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/SumCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/SumCollector.java
new file mode 100644
index 0000000..6f4fc18
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/SumCollector.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction.data;
+
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.stream.reservation.DoubleCheckedReservation;
+import org.apache.solr.analytics.stream.reservation.ReductionDataReservation;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+
+/**
+ * Collects the sum of the given {@link DoubleValueStream} parameter. 
+ */
+public class SumCollector extends ReductionDataCollector<SumCollector.SumData> {
+  private final DoubleValueStream param;
+  public static final String name = "sum";
+  private final String exprStr;
+  
+  public SumCollector(DoubleValueStream param) {
+    this.param = param;
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+  }
+  
+  private double sum;
+  private boolean exists;
+
+  /**
+   * Return the sum of the set data
+   * 
+   * @return the sum
+   */
+  public double sum() {
+    return sum;
+  }
+  
+  /**
+   * Return whether a sum exists.
+   * A sum will always exist if there is at least one existing value for the parameter, 
+   * otherwise the sum does not exist.
+   * 
+   * @return whether a sum exists
+   */
+  public boolean exists() {
+    return exists;
+  }
+
+  @Override
+  public SumData newData() {
+    SumData data = new SumData();
+    data.sum = 0;
+    data.exists = false;
+    return data;
+  }
+
+  double tempSum;
+  boolean tempExists;
+  @Override
+  public void collect() {
+    tempSum = 0;
+    tempExists = false;
+    param.streamDoubles( val -> {
+      tempSum += val;
+      tempExists = true;
+    });
+  }
+  @Override
+  protected void apply(SumData data) {
+    data.sum += tempSum;
+    data.exists |= tempExists;
+  }
+
+  @Override
+  public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+    consumer.accept(new DoubleCheckedReservation(
+        value -> {
+          ioData.sum += value;
+          ioData.exists = true;
+        },
+        ()-> ioData.sum,
+        ()-> ioData.exists
+      ));
+  }
+
+  @Override
+  public void setMergedData(ReductionData data) {
+    sum = ((SumData)data).sum;
+    exists = data.exists;
+  }
+
+  @Override
+  public void setData(ReductionData data) {
+    sum = ((SumData)data).sum;
+    exists = data.exists;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  
+  public static class SumData extends ReductionData {
+    double sum;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/UniqueCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/UniqueCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/UniqueCollector.java
new file mode 100644
index 0000000..3e30114
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/UniqueCollector.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.function.reduction.data;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.function.reduction.data.ReductionData;
+import org.apache.solr.analytics.stream.reservation.DoubleArrayReservation;
+import org.apache.solr.analytics.stream.reservation.FloatArrayReservation;
+import org.apache.solr.analytics.stream.reservation.IntArrayReservation;
+import org.apache.solr.analytics.stream.reservation.LongArrayReservation;
+import org.apache.solr.analytics.stream.reservation.ReductionDataReservation;
+import org.apache.solr.analytics.stream.reservation.StringArrayReservation;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValueStream;
+
+/**
+ * Collects the number of unique values that exist for the given parameter. 
+ * <p>
+ * Supported types are:
+ * <ul>
+ * <li>Int
+ * <li>Long
+ * <li>Float
+ * <li>Double
+ * <li>Date (through longs)
+ * <li>String
+ * </ul>
+ */
+public abstract class UniqueCollector<T> extends ReductionDataCollector<UniqueCollector.UniqueData<T>> {
+  public static final String name = "unique";
+  private final String exprStr;
+  
+  public UniqueCollector(AnalyticsValueStream param) {
+    this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+    this.tempSet = new HashSet<T>();
+  }
+  
+  private long count;
+
+  /**
+   * Get the count of unique values in the set data.
+   * 
+   * @return the count of unique values
+   */
+  public long count() {
+    return count;
+  }
+
+  @Override
+  public UniqueData<T> newData() {
+    UniqueData<T> data = new UniqueData<T>();
+    data.set = new HashSet<>();
+    data.exists = false;
+    return data;
+  }
+  
+  Set<T> tempSet;
+  @Override
+  protected void apply(UniqueData<T> data) {
+    data.set.addAll(tempSet);
+  }
+  
+  Iterator<T> iter;
+  public int startExport() {
+    iter = ioData.set.iterator();
+    return ioData.set.size();
+  }
+  public T exportNext() {
+    return iter.next();
+  }
+
+  @Override
+  public void setMergedData(ReductionData data) {
+    count = ((UniqueData<?>)data).set.size();
+  }
+
+  @Override
+  public void setData(ReductionData data) {
+    count = ((UniqueData<?>)data).set.size();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+  
+  public static class UniqueData<T> extends ReductionData {
+    Set<T> set;
+  }
+
+  public static class UniqueIntCollector extends UniqueCollector<Integer> {
+    private IntValueStream param;
+    
+    public UniqueIntCollector(IntValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public void collect() {
+      tempSet.clear();
+      param.streamInts( val -> tempSet.add(val) );
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new IntArrayReservation(
+          value -> ioData.set.add(value),
+          size -> {},
+          () -> exportNext(),
+          () -> startExport()
+        ));
+    }
+  }
+  
+  public static class UniqueLongCollector extends UniqueCollector<Long> {
+    private LongValueStream param;
+    
+    public UniqueLongCollector(LongValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public void collect() {
+      tempSet.clear();
+      param.streamLongs( val -> tempSet.add(val) );
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new LongArrayReservation(
+          value -> ioData.set.add(value),
+          size -> {},
+          () -> exportNext(),
+          () -> startExport()
+        ));
+    }
+  }
+  
+  public static class UniqueFloatCollector extends UniqueCollector<Float> {
+    private FloatValueStream param;
+    
+    public UniqueFloatCollector(FloatValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public void collect() {
+      tempSet.clear();
+      param.streamFloats( val -> tempSet.add(val) );
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new FloatArrayReservation(
+          value -> ioData.set.add(value),
+          size -> {},
+          () -> exportNext(),
+          () -> startExport()
+        ));
+    }
+  }
+  
+  public static class UniqueDoubleCollector extends UniqueCollector<Double> {
+    private DoubleValueStream param;
+    
+    public UniqueDoubleCollector(DoubleValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public void collect() {
+      tempSet.clear();
+      param.streamDoubles( val -> tempSet.add(val) );
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new DoubleArrayReservation(
+          value -> ioData.set.add(value),
+          size -> {},
+          () -> exportNext(),
+          () -> startExport()
+        ));
+    }
+  }
+  
+  public static class UniqueStringCollector extends UniqueCollector<String> {
+    private StringValueStream param;
+    
+    public UniqueStringCollector(StringValueStream param) {
+      super(param);
+      this.param = param;
+    }
+
+    @Override
+    public void collect() {
+      tempSet.clear();
+      param.streamStrings( val -> tempSet.add(val) );
+    }
+    
+    @Override
+    public void submitReservations(Consumer<ReductionDataReservation<?,?>> consumer) {
+      consumer.accept(new StringArrayReservation(
+          value -> ioData.set.add(value),
+          size -> {},
+          () -> exportNext(),
+          () -> startExport()
+        ));
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/package-info.java
new file mode 100644
index 0000000..15b4d18
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/data/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Reduction data collectors to use while computing analytics expressions.
+ * For multi-sharded collections, this is the data that is sent from shard to shard.
+ */
+package org.apache.solr.analytics.function.reduction.data;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/package-info.java
new file mode 100644
index 0000000..ae45ef1
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/reduction/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Reduction functions to use for analytics expressions.
+ */
+package org.apache.solr.analytics.function.reduction;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/package-info.java
new file mode 100644
index 0000000..e5bd519
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * A solr component to compute complex analytics over search results. 
+ */
+package org.apache.solr.analytics;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AbstractFieldFacetRequest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AbstractFieldFacetRequest.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AbstractFieldFacetRequest.java
deleted file mode 100644
index 8121f56..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AbstractFieldFacetRequest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.request;
-
-import org.apache.solr.schema.SchemaField;
-
-/**
- * An abstract request for a facet over a single field, such as a field or range facet.
- */
-public abstract class AbstractFieldFacetRequest implements FacetRequest {
-  protected SchemaField field = null;
-  
-  public AbstractFieldFacetRequest(SchemaField field) {
-    this.field = field;
-  }
-
-  public SchemaField getField() {
-    return field;
-  }
-
-  public void setField(SchemaField field) {
-    this.field = field;
-  }
-
-  public String getName() {
-    return field.getName();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsContentHandler.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsContentHandler.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsContentHandler.java
deleted file mode 100644
index b93a59e..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/request/AnalyticsContentHandler.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.request;
-
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.List;
-
-import org.apache.solr.analytics.request.FieldFacetRequest.FacetSortDirection;
-import org.apache.solr.analytics.request.FieldFacetRequest.FacetSortSpecification;
-import org.apache.solr.common.params.FacetParams.FacetRangeInclude;
-import org.apache.solr.common.params.FacetParams.FacetRangeOther;
-import org.apache.solr.schema.IndexSchema;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-
-/**
- * Handles the parsing of the AnalysisRequestEnvelope elements if passed in through XML.
- */
-public class AnalyticsContentHandler implements ContentHandler {
-  // XML Element/Attribute Name Constants
-  public static final String ANALYTICS_REQUEST_ENVELOPE="analyticsRequestEnvelope";
-  
-  public static final String ANALYTICS_REQUEST="analyticsRequest";
-  public static final String NAME="name";
-  
-  public static final String STATISTIC="statistic";
-  public static final String EXPRESSION="expression";
-  
-  public static final String FIELD_FACET="fieldFacet";
-  public static final String FIELD="field";
-  public static final String SHOW_MISSING="showMissing";
-  public static final String LIMIT="limit";
-  public static final String MIN_COUNT="minCount";
-  
-  public static final String SORT_SPECIFICATION="sortSpecification";
-  public static final String STAT_NAME="statName";
-  public static final String DIRECTION="direction";
-  
-  public static final String RANGE_FACET="rangeFacet";
-  public static final String START="start";
-  public static final String END="end";
-  public static final String GAP="gap";
-  public static final String INCLUDE_BOUNDARY="includeBoundary";
-  public static final String OTHER_RANGE="otherRange";
-  public static final String HARD_END="hardend";
-  
-  public static final String QUERY_FACET="queryFacet";
-  public static final String QUERY="query";
-  
-  // Default Values
-  public static final int DEFAULT_FACET_LIMIT = -1;
-  public static final boolean DEFAULT_FACET_HARDEND = false;
-  public static final int DEFAULT_FACET_MINCOUNT = 0;
-  public static final boolean DEFAULT_FACET_FIELD_SHOW_MISSING = false;
-
-  boolean inEnvelope = false;
-  boolean inRequest = false;
-  boolean inStatistic = false;
-  boolean inFieldFacet = false;
-  boolean inSortSpecification = false;
-  boolean inQueryFacet = false;
-  boolean inRangeFacet = false;
-  
-  private final IndexSchema schema;
-  
-  // Objects to use while building the Analytics Requests
-  
-  String currentElementText;
-  
-  List<AnalyticsRequest> requests;
-  
-  AnalyticsRequest analyticsRequest;
-  List<ExpressionRequest> expressionList;
-  List<FieldFacetRequest> fieldFacetList;
-  List<RangeFacetRequest> rangeFacetList;
-  List<QueryFacetRequest> queryFacetList;
-  
-  ExpressionRequest expression;
-  
-  FieldFacetRequest fieldFacet;
-  int limit;
-  int minCount;
-  boolean showMissing;
-  FacetSortSpecification sortSpecification;
-  
-  RangeFacetRequest rangeFacet;
-  boolean hardend;
-  List<String> gaps;
-  EnumSet<FacetRangeInclude> includeBoundaries;
-  EnumSet<FacetRangeOther> otherRanges;
-  
-  String queryName;
-  List<String> queries;
-  
-  public AnalyticsContentHandler(IndexSchema schema) {
-    this.schema = schema;
-  }
-
-  @Override
-  public void setDocumentLocator(Locator locator) { }
-
-  @Override
-  public void startDocument() throws SAXException { }
-
-  @Override
-  public void endDocument() throws SAXException { }
-
-  @Override
-  public void startPrefixMapping(String prefix, String uri) throws SAXException { }
-
-  @Override
-  public void endPrefixMapping(String prefix) throws SAXException { }
-
-  @Override
-  public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
-    currentElementText = "";
-    if (inEnvelope) {
-      if (inRequest) {
-        if (localName.equals(STATISTIC)) {
-          // Start a Statistic Request
-          inStatistic = true;
-        } else if (inFieldFacet) {
-          if (localName.equals(SORT_SPECIFICATION)) {
-            // Start a Sort Specification
-            inSortSpecification = true;
-            sortSpecification = new FacetSortSpecification();
-          }
-        } else if (localName.equals(FIELD_FACET)) {
-          // Start a Field Facet Request
-          // Get attributes (limit, minCount, showMissing)
-          String att = atts.getValue(uri,LIMIT);
-          if (att!=null) {
-            limit = Integer.parseInt(att);
-          } else {
-            limit = DEFAULT_FACET_LIMIT;
-          }
-          att = atts.getValue(uri,MIN_COUNT);
-          if (att!=null) {
-            minCount = Integer.parseInt(att);
-          } else {
-            minCount = DEFAULT_FACET_MINCOUNT;
-          }
-          att = atts.getValue(uri,SHOW_MISSING);
-          if (att!=null) {
-            showMissing = Boolean.parseBoolean(att);
-          } else {
-            showMissing = DEFAULT_FACET_FIELD_SHOW_MISSING;
-          }
-          
-          inFieldFacet = true;
-        } else if (localName.equals(RANGE_FACET)) {
-          // Start a Range Facet Request
-          // Get attributes (hardEnd)
-          String att = atts.getValue(uri,HARD_END);
-          if (att!=null) {
-            hardend = Boolean.parseBoolean(att);
-          } else {
-            hardend = false;
-          }
-          
-          // Initiate Range Facet classes
-          gaps = new ArrayList<>();
-          includeBoundaries = EnumSet.noneOf(FacetRangeInclude.class);
-          otherRanges = EnumSet.noneOf(FacetRangeOther.class);
-          inRangeFacet = true;
-        } else if (localName.equals(QUERY_FACET)) {
-          // Start a Query Facet Request
-          queries = new ArrayList<>();
-          inQueryFacet = true;
-        }
-      } else if (localName.equals(ANALYTICS_REQUEST)){
-        // Start an Analytics Request
-        
-        // Renew each list.
-        fieldFacetList = new ArrayList<>();
-        rangeFacetList = new ArrayList<>();
-        queryFacetList = new ArrayList<>();
-        expressionList = new ArrayList<>();
-        inRequest = true;
-      }
-    } else if (localName.equals(ANALYTICS_REQUEST_ENVELOPE)){
-      //Begin the parsing of the Analytics Requests
-      requests = new ArrayList<>();
-      inEnvelope = true;
-    }
-  }
-
-  @Override
-  public void endElement(String uri, String localName, String qName) throws SAXException {
-    if (inEnvelope) {
-      if (inRequest) {
-        if (inStatistic) {
-          if (localName.equals(EXPRESSION)) {
-            expression = new ExpressionRequest(currentElementText,currentElementText);
-          } else if (localName.equals(NAME)) {
-            expression.setName(currentElementText);
-          } else if (localName.equals(STATISTIC)) {
-            // Finished Parsing the Statistic Request
-            expressionList.add(expression);
-            inStatistic = false;
-          } 
-        } else if (inFieldFacet) {
-          if (inSortSpecification) {
-            if (localName.equals(STAT_NAME)) {
-              sortSpecification.setStatistic(currentElementText);
-            } else if (localName.equals(DIRECTION)) {
-              sortSpecification.setDirection(FacetSortDirection.fromExternal(currentElementText));
-            } else if (localName.equals(SORT_SPECIFICATION)) {
-              // Finished Parsing the Sort Specification
-              fieldFacet.setSort(sortSpecification);
-              inSortSpecification = false;
-            } 
-          } else if (localName.equals(FIELD)) {
-            fieldFacet = new FieldFacetRequest(schema.getField(currentElementText));
-          } else if (localName.equals(FIELD_FACET)) {
-            // Finished Parsing the Field Facet Request
-            fieldFacet.setLimit(limit);
-            fieldFacet.showMissing(showMissing);
-            fieldFacetList.add(fieldFacet);
-            inFieldFacet = false;
-          } 
-        } else if (inRangeFacet) {
-          if (localName.equals(FIELD)) {
-            rangeFacet = new RangeFacetRequest(schema.getField(currentElementText), "", "", new String[1]);
-          } else if (localName.equals(START)) {
-            rangeFacet.setStart(currentElementText);
-          } else if (localName.equals(END)) {
-            rangeFacet.setEnd(currentElementText);
-          } else if (localName.equals(GAP)) {
-            gaps.add(currentElementText);
-          } else if (localName.equals(INCLUDE_BOUNDARY)) {
-            includeBoundaries.add(FacetRangeInclude.get(currentElementText));
-          } else if (localName.equals(OTHER_RANGE)) {
-            otherRanges.add(FacetRangeOther.get(currentElementText));
-          } else if (localName.equals(RANGE_FACET)) {
-            // Finished Parsing the Range Facet Request
-            rangeFacet.setHardEnd(hardend);
-            rangeFacet.setGaps(gaps.toArray(new String[1]));
-            rangeFacet.setInclude(includeBoundaries);
-            rangeFacet.setOthers(otherRanges);
-            inRangeFacet = false;
-            rangeFacetList.add(rangeFacet);
-          } 
-        } else if (inQueryFacet) {
-          if (localName.equals(NAME)) {
-            queryName = currentElementText;
-          } else if (localName.equals(QUERY)) {
-            queries.add(currentElementText);
-          } else if (localName.equals(QUERY_FACET)) {
-            // Finished Parsing the Query Facet Request
-            QueryFacetRequest temp = new QueryFacetRequest(queryName);
-            temp.setQueries(queries);
-            queryFacetList.add(temp);
-            inQueryFacet = false;
-          }
-        } else if (localName.equals(NAME)) {
-          analyticsRequest = new AnalyticsRequest(currentElementText);
-        } else if (localName.equals(ANALYTICS_REQUEST)){
-          // Finished Parsing the Analytics Request
-          analyticsRequest.setExpressions(expressionList);
-          analyticsRequest.setFieldFacets(fieldFacetList);
-          analyticsRequest.setRangeFacets(rangeFacetList);
-          analyticsRequest.setQueryFacets(queryFacetList);
-          requests.add(analyticsRequest);
-          inRequest = false;
-        }
-      } else if (localName.equals(ANALYTICS_REQUEST_ENVELOPE)){
-        // Finished Parsing
-        inEnvelope = false;
-      }
-    }
-  }
-
-  @Override
-  public void characters(char[] ch, int start, int length) throws SAXException {
-    currentElementText += new String(ch,start,length);
-  }
-
-  @Override
-  public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { }
-
-  @Override
-  public void processingInstruction(String target, String data) throws SAXException { }
-
-  @Override
-  public void skippedEntity(String name) throws SAXException { }
-  
-  /**
-   * Returns the list of Analytics Requests built during parsing.
-   * 
-   * @return List of {@link AnalyticsRequest} objects specified by the given XML file
-   */
-  public List<AnalyticsRequest> getAnalyticsRequests() {
-    return requests;
-  }
-
-}


[43/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10979: Randomize PointFields in schema-docValues*.xml and all affected tests

Posted by ab...@apache.org.
SOLR-10979: Randomize PointFields in schema-docValues*.xml and all affected tests


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/0159d494
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/0159d494
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/0159d494

Branch: refs/heads/jira/solr-10879
Commit: 0159d494f562a5a22c8e5ed7ad412fad62b5db55
Parents: b7fb61d
Author: Chris Hostetter <ho...@apache.org>
Authored: Thu Jun 29 15:09:39 2017 -0700
Committer: Chris Hostetter <ho...@apache.org>
Committed: Thu Jun 29 15:09:39 2017 -0700

----------------------------------------------------------------------
 solr/CHANGES.txt                                          |  1 +
 .../test-files/solr/collection1/conf/schema-docValues.xml | 10 +++++-----
 .../solr/collection1/conf/schema-docValuesFaceting.xml    | 10 +++++-----
 .../solr/collection1/conf/schema-docValuesJoin.xml        | 10 +++++-----
 .../solr/collection1/conf/schema-docValuesMissing.xml     | 10 +++++-----
 .../solr/collection1/conf/schema-docValuesMulti.xml       | 10 +++++-----
 .../test/org/apache/solr/schema/DocValuesMultiTest.java   | 10 +++++++---
 7 files changed, 33 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0159d494/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 30d334b..0d2226f 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -363,6 +363,7 @@ Other Changes
   - SOLR-10970: Randomize PointFields in all tests using schema-*sort* files (hossman)
   - SOLR-10971: Randomize PointFields in CdcrBootstrapTest (hossman)
   - SOLR-10977: Randomize the usage of Points based numerics in schema15.xml and all impacted tests (hossman)
+  - SOLR-10979: Randomize PointFields in schema-docValues*.xml and all affected tests (hossman)
 
 * SOLR-6807: Changed requestDispatcher's handleSelect to default to false, thus ignoring "qt".
   Simplified configs to not refer to handleSelect or "qt".  Switch all tests that assumed true to assume false

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0159d494/solr/core/src/test-files/solr/collection1/conf/schema-docValues.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-docValues.xml b/solr/core/src/test-files/solr/collection1/conf/schema-docValues.xml
index 0216791..4a5ab17 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-docValues.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-docValues.xml
@@ -38,14 +38,14 @@
        These are provided more for backward compatability, allowing one
        to create a schema that matches an existing lucene index.
   -->
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="float" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="double" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
   <!-- format for date is 1995-12-31T23:59:59.999Z and only the fractional
        seconds part (.999) is optional.
     -->
-  <fieldType name="date" class="solr.TrieDateField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
 
   <fieldType name="boolean" class="solr.BoolField"/>
   <fieldType name="string" class="solr.StrField"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0159d494/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml b/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml
index f7c6bfc..a8eed08 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-docValuesFaceting.xml
@@ -17,11 +17,11 @@
 -->
 
 <schema name="test" version="1.6">
-  <fieldType name="int" class="${solr.tests.IntegerFieldType}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="float" class="${solr.tests.FloatFieldType}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="long" class="${solr.tests.LongFieldType}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="double" class="${solr.tests.DoubleFieldType}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="date" class="${solr.tests.DateFieldType}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="float" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="double" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
 
   <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
   <fieldType name="pint" class="solr.IntPointField"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0159d494/solr/core/src/test-files/solr/collection1/conf/schema-docValuesJoin.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-docValuesJoin.xml b/solr/core/src/test-files/solr/collection1/conf/schema-docValuesJoin.xml
index d2188fc..844a472 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-docValuesJoin.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-docValuesJoin.xml
@@ -29,11 +29,11 @@
        1.5: omitNorms defaults to true for primitive field types (int, float, boolean, string...)
        1.6: useDocValuesAsStored defaults to true.
      -->
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="date" class="solr.TrieDateField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="float" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="double" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
   <fieldtype name="string" class="solr.StrField" sortMissingLast="true" useDocValuesAsStored="false"/>
   <fieldType name="text" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
     <analyzer type="index">

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0159d494/solr/core/src/test-files/solr/collection1/conf/schema-docValuesMissing.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-docValuesMissing.xml b/solr/core/src/test-files/solr/collection1/conf/schema-docValuesMissing.xml
index ac319e2..d80a426 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-docValuesMissing.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-docValuesMissing.xml
@@ -19,11 +19,11 @@
 <!-- schema file for testing sorting/faceting/functions on single-valued DV with missing values -->
 
 <schema name="schema-docValuesMissing" version="1.6">
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="date" class="solr.TrieDateField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="float" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="double" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
   <fieldType name="string" class="solr.StrField"/>
   <fieldType name="boolean" class="solr.BoolField"/>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0159d494/solr/core/src/test-files/solr/collection1/conf/schema-docValuesMulti.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-docValuesMulti.xml b/solr/core/src/test-files/solr/collection1/conf/schema-docValuesMulti.xml
index 81c7836..eb84189 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-docValuesMulti.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-docValuesMulti.xml
@@ -18,14 +18,14 @@
 
 <schema name="schema-docValuesMulti" version="1.6">
 
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="float" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="double" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
   <!-- format for date is 1995-12-31T23:59:59.999Z and only the fractional
        seconds part (.999) is optional.
     -->
-  <fieldType name="date" class="solr.TrieDateField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
 
   <fieldType name="boolean" class="solr.BoolField"/>
   <fieldType name="string" class="solr.StrField"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/0159d494/solr/core/src/test/org/apache/solr/schema/DocValuesMultiTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/schema/DocValuesMultiTest.java b/solr/core/src/test/org/apache/solr/schema/DocValuesMultiTest.java
index 30dea85..8697b26 100644
--- a/solr/core/src/test/org/apache/solr/schema/DocValuesMultiTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/DocValuesMultiTest.java
@@ -30,7 +30,7 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class DocValuesMultiTest extends SolrTestCaseJ4 {
-
+  
   @BeforeClass
   public static void beforeTests() throws Exception {
     initCore("solrconfig-basic.xml", "schema-docValuesMulti.xml");
@@ -55,6 +55,10 @@ public class DocValuesMultiTest extends SolrTestCaseJ4 {
 
   @Test
   public void testDocValues() throws IOException {
+
+    final DocValuesType expectedNumericDvType = Boolean.getBoolean(NUMERIC_POINTS_SYSPROP) ?
+      DocValuesType.SORTED_NUMERIC : DocValuesType.SORTED_SET;
+    
     assertU(adoc("id", "1", "floatdv", "4.5", "intdv", "-1", "intdv", "3",
         "stringdv", "value1", "stringdv", "value2",
         "booldv", "false", "booldv", "true"));
@@ -68,8 +72,8 @@ public class DocValuesMultiTest extends SolrTestCaseJ4 {
         final FieldInfos infos = reader.getFieldInfos();
         assertEquals(DocValuesType.SORTED_SET, infos.fieldInfo("stringdv").getDocValuesType());
         assertEquals(DocValuesType.SORTED_SET, infos.fieldInfo("booldv").getDocValuesType());
-        assertEquals(DocValuesType.SORTED_SET, infos.fieldInfo("floatdv").getDocValuesType());
-        assertEquals(DocValuesType.SORTED_SET, infos.fieldInfo("intdv").getDocValuesType());
+        assertEquals(expectedNumericDvType, infos.fieldInfo("floatdv").getDocValuesType());
+        assertEquals(expectedNumericDvType, infos.fieldInfo("intdv").getDocValuesType());
 
         SortedSetDocValues dv = reader.getSortedSetDocValues("stringdv");
         assertEquals(0, dv.nextDoc());


[26/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10971: Randomize PointFields in CdcrBootstrapTest

Posted by ab...@apache.org.
SOLR-10971: Randomize PointFields in CdcrBootstrapTest


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

Branch: refs/heads/jira/solr-10879
Commit: c98e2a528f13a3a05f9d4899bff54c2f519e5fb5
Parents: 89abc98
Author: Chris Hostetter <ho...@apache.org>
Authored: Wed Jun 28 14:55:29 2017 -0700
Committer: Chris Hostetter <ho...@apache.org>
Committed: Wed Jun 28 14:55:29 2017 -0700

----------------------------------------------------------------------
 solr/CHANGES.txt                                                   | 1 +
 .../solr/configsets/cdcr-source-disabled/conf/schema.xml           | 2 +-
 .../src/test-files/solr/configsets/cdcr-source/conf/schema.xml     | 2 +-
 .../src/test-files/solr/configsets/cdcr-target/conf/schema.xml     | 2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c98e2a52/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index bbda1a3..214b82e 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -358,6 +358,7 @@ Other Changes
   - SOLR-10946: Randomize the usage of Points based numerics in solrj test schemas (hossman)
   - SOLR-10947: Randomize the usage of Points based numerics in contrib test schemas (hossman)
   - SOLR-10970: Randomize PointFields in all tests using schema-*sort* files (hossman)
+  - SOLR-10971: Randomize PointFields in CdcrBootstrapTest (hossman)
 
 * SOLR-6807: Changed requestDispatcher's handleSelect to default to false, thus ignoring "qt".
   Simplified configs to not refer to handleSelect or "qt".  Switch all tests that assumed true to assume false

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c98e2a52/solr/core/src/test-files/solr/configsets/cdcr-source-disabled/conf/schema.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cdcr-source-disabled/conf/schema.xml b/solr/core/src/test-files/solr/configsets/cdcr-source-disabled/conf/schema.xml
index 2897315..2df6c0a 100644
--- a/solr/core/src/test-files/solr/configsets/cdcr-source-disabled/conf/schema.xml
+++ b/solr/core/src/test-files/solr/configsets/cdcr-source-disabled/conf/schema.xml
@@ -18,7 +18,7 @@
 <schema name="minimal" version="1.1">
   <types>
     <fieldType name="string" class="solr.StrField"/>
-    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
   </types>
   <fields>
     <field name="id" type="string" indexed="true" stored="true"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c98e2a52/solr/core/src/test-files/solr/configsets/cdcr-source/conf/schema.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cdcr-source/conf/schema.xml b/solr/core/src/test-files/solr/configsets/cdcr-source/conf/schema.xml
index 2897315..2df6c0a 100644
--- a/solr/core/src/test-files/solr/configsets/cdcr-source/conf/schema.xml
+++ b/solr/core/src/test-files/solr/configsets/cdcr-source/conf/schema.xml
@@ -18,7 +18,7 @@
 <schema name="minimal" version="1.1">
   <types>
     <fieldType name="string" class="solr.StrField"/>
-    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
   </types>
   <fields>
     <field name="id" type="string" indexed="true" stored="true"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/c98e2a52/solr/core/src/test-files/solr/configsets/cdcr-target/conf/schema.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/cdcr-target/conf/schema.xml b/solr/core/src/test-files/solr/configsets/cdcr-target/conf/schema.xml
index 2897315..2df6c0a 100644
--- a/solr/core/src/test-files/solr/configsets/cdcr-target/conf/schema.xml
+++ b/solr/core/src/test-files/solr/configsets/cdcr-target/conf/schema.xml
@@ -18,7 +18,7 @@
 <schema name="minimal" version="1.1">
   <types>
     <fieldType name="string" class="solr.StrField"/>
-    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" positionIncrementGap="0"/>
   </types>
   <fields>
     <field name="id" type="string" indexed="true" stored="true"/>


[05/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/AnalyticsValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/AnalyticsValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/AnalyticsValue.java
new file mode 100644
index 0000000..54a3003
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/AnalyticsValue.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+
+/**
+ * A single-valued analytics value.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #getObject()} and {@link #exists()},
+ * resulting in different values on each call.
+ */
+public interface AnalyticsValue extends AnalyticsValueStream {
+  /**
+   * Check whether the current value exists.
+   * <br>
+   * NOTE: The result of this method is only guaranteed after any {@code get<Type>()} method is called.
+   * 
+   * @return whether the current value exists
+   */
+  boolean exists();
+  /**
+   * Get the object representation of the current value.
+   * 
+   * @return the current value
+   */
+  Object getObject();
+  
+  /**
+   * An abstract base for {@link AnalyticsValue} that automatically casts to castable types.
+   */
+  public static abstract class AbstractAnalyticsValue implements AnalyticsValue {
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      Object value = getObject();
+      if (exists()) {
+        cons.accept(value);
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/AnalyticsValueStream.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/AnalyticsValueStream.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/AnalyticsValueStream.java
new file mode 100644
index 0000000..0c02115
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/AnalyticsValueStream.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.ExpressionFactory;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A multi-valued analytics value, the super-type of all Analytics value types.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #streamObjects},
+ * resulting in different values on each call.
+ */
+public interface AnalyticsValueStream {
+  /**
+   * Get the name of function or value.
+   * 
+   * @return the name of function/value
+   */
+  String getName();
+  /**
+   * Get the expression string of the analytics value stream. Must be unique to the expression. 
+   * If passed to {@link ExpressionFactory#createExpression(String)}, the exact same expression should be created. 
+   * 
+   * @return the name of function/value
+   */
+  String getExpressionStr();
+  /**
+   * Stream the object representations of all current values, if any exist.
+   * 
+   * @param cons The consumer to accept the values
+   */
+  void streamObjects(Consumer<Object> cons);
+  
+  /**
+   * The types of expressions.
+   */
+  static enum ExpressionType {
+    CONST             (true, true),
+    FIELD             (true,  false),
+    UNREDUCED_MAPPING (true,  false),
+    REDUCTION         (false, true),
+    REDUCED_MAPPING   (false, true);
+
+    private final boolean unreduced;
+    private final boolean reduced;
+    
+    ExpressionType(boolean unreduced, boolean reduced) {
+      this.unreduced = unreduced;
+      this.reduced = reduced;
+    }
+
+    public boolean isUnreduced() {
+      return unreduced;
+    }
+    public boolean isReduced() {
+      return reduced;
+    }
+  }
+
+  /**
+   * Get the type of the expression that this class represents.
+   * 
+   * @return the expression type
+   */
+  ExpressionType getExpressionType();
+  
+  /**
+   * Helper to create an expression string for a function.
+   * 
+   * @param funcName the name of the function
+   * @param params the parameters of the function
+   * @return a valid expression string for the function.
+   */
+  static String createExpressionString(String funcName, 
+                                       AnalyticsValueStream... params) {
+    return String.format(Locale.ROOT, "%s(%s)",
+                         funcName,
+                         Arrays.stream(params).
+                                map(param -> param.getExpressionStr()).
+                                reduce((a, b) -> a + "," + b).orElseGet(() -> ""));
+  }
+
+  /**
+   * Determine whether the expression is a unreduced mapping expression, a reduced mapping expression, or a constant.
+   * 
+   * @param exprString the string representing the expression, used when creating exceptions
+   * @param params the parameters 
+   * @return the expression type
+   * @throws SolrException if the params are incompatable types,
+   * for example if reduced and unreduced params are both included
+   */
+  static ExpressionType determineMappingPhase(String exprString, AnalyticsValueStream... params) throws SolrException {
+    boolean unreduced = true;
+    boolean reduced = true;
+    for (AnalyticsValueStream param : params) {
+      unreduced &= param.getExpressionType().isUnreduced();
+      reduced &= param.getExpressionType().isReduced();
+    }
+    if (unreduced && reduced) {
+      return ExpressionType.CONST;
+    }
+    else if (unreduced) {
+      return ExpressionType.UNREDUCED_MAPPING;
+    }
+    else if (reduced) {
+      return ExpressionType.REDUCED_MAPPING;
+    }
+    else {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The following expression contains incorrect parameters. " + 
+                            "(ReductionFunctions cannot be in the paramters of other ReductionFunctions): " + exprString);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/BooleanValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/BooleanValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/BooleanValue.java
new file mode 100644
index 0000000..5d58a8b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/BooleanValue.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+
+/**
+ * A single-valued analytics value that can be represented as a boolean.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #getBoolean()} and {@link #exists()},
+ * resulting in different values on each call.
+ */
+public interface BooleanValue extends BooleanValueStream, AnalyticsValue {
+  /**
+   * Get the boolean representation of the current value.
+   * <p>
+   * NOTE: The value returned is not valid unless calling {@link #exists()} afterwards returns {@code TRUE}.
+   * 
+   * @return the current value
+   */
+  boolean getBoolean();
+  
+  /**
+   * An interface that represents all of the types a {@link BooleanValue} should be able to cast to. 
+   */
+  public static interface CastingBooleanValue extends BooleanValue, StringValue, ComparableValue {}
+  
+  /**
+   * An abstract base for {@link CastingBooleanValue} that automatically casts to all types if {@link #getBoolean()} and {@link #exists()} are implemented.
+   */
+  public static abstract class AbstractBooleanValue implements CastingBooleanValue {
+    @Override
+    public String getString() {
+      boolean val = getBoolean();
+      return exists() ? Boolean.toString(val) : null;
+    }
+    @Override
+    public Object getObject() {
+      boolean val = getBoolean();
+      return exists() ? val : null;
+    }
+    @Override
+    public void streamBooleans(BooleanConsumer cons) {
+      boolean val = getBoolean();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      String val = getString();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      Object val = getObject();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public ExpressionComparator<Boolean> getObjectComparator(String expression) {
+      return new ExpressionComparator<>(expression);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/BooleanValueStream.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/BooleanValueStream.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/BooleanValueStream.java
new file mode 100644
index 0000000..0827aea
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/BooleanValueStream.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+
+/**
+ * A multi-valued analytics value that can be represented as a boolean.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #streamBooleans},
+ * resulting in different values on each call.
+ */
+public interface BooleanValueStream extends AnalyticsValueStream {
+  /**
+   * Stream the boolean representations of all current values, if any exist.
+   * 
+   * @param cons The consumer to accept the values
+   */
+  void streamBooleans(BooleanConsumer cons);
+  
+  /**
+   * An interface that represents all of the types a {@link BooleanValueStream} should be able to cast to. 
+   */
+  public static interface CastingBooleanValueStream extends BooleanValueStream, StringValueStream {}
+  
+  /**
+   * An abstract base for {@link CastingBooleanValueStream} that automatically casts to all types if {@link #streamBooleans} is implemented.
+   */
+  public static abstract class AbstractBooleanValueStream implements CastingBooleanValueStream {
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      streamBooleans((boolean val) -> cons.accept(Boolean.toString(val)));
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      streamBooleans((boolean val) -> cons.accept(val));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/ComparableValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/ComparableValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/ComparableValue.java
new file mode 100644
index 0000000..93cae48
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/ComparableValue.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import org.apache.solr.analytics.facet.compare.FacetResultsComparator;
+
+/**
+ * A single-valued analytics value that can be compared and used to sort a facet.
+ */
+public interface ComparableValue extends AnalyticsValue {
+  /**
+   * Create an entry comparator used to sort the facet-value buckets of a facet.
+   * 
+   * @param expression the name of the expression in the results array
+   * @return a comparator to sort the buckets with
+   */
+  FacetResultsComparator getObjectComparator(String expression);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DateValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DateValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DateValue.java
new file mode 100644
index 0000000..b105d58
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DateValue.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.function.Consumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+
+/**
+ * A single-valued analytics value that can be represented as a date.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #getDate()} and {@link #exists()},
+ * resulting in different values on each call.
+ * <p>
+ * NOTE: Most date expressions work with the {@code long} representation of the date, so that less
+ * objects need to be created during execution.
+ */
+public interface DateValue extends DateValueStream, LongValue {
+  /**
+   * Get the date representation of the current value.
+   * <p>
+   * NOTE: The value returned is not valid unless calling {@link #exists()} afterwards returns {@code TRUE}.
+   * 
+   * @return the current value
+   */
+  Date getDate();
+  
+  /**
+   * An interface that represents all of the types a {@link DateValue} should be able to cast to. 
+   */
+  public static interface CastingDateValue extends DateValue, LongValue, StringValue, ComparableValue {}
+
+  /**
+   * An abstract base for {@link CastingDateValue} that automatically casts to all types if {@link #getLong()} and {@link #exists()} are implemented.
+   */
+  public static abstract class AbstractDateValue implements CastingDateValue {
+    @Override
+    public Date getDate() {
+      long val = getLong();
+      return exists() ? new Date(val) : null;
+    }
+    @Override
+    public String getString() {
+      long val = getLong();
+      return exists() ? Instant.ofEpochMilli(val).toString() : null;
+    }
+    @Override
+    public Object getObject() {
+      long val = getLong();
+      return exists() ? new Date(val) : null;
+    }
+    @Override
+    public void streamDates(Consumer<Date> cons) {
+      Date val = getDate();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamLongs(LongConsumer cons) {
+      long val = getLong();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      String val = getString();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      Object val = getObject();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public ExpressionComparator<Date> getObjectComparator(String expression) {
+      return new ExpressionComparator<>(expression);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DateValueStream.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DateValueStream.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DateValueStream.java
new file mode 100644
index 0000000..f709264
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DateValueStream.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.function.Consumer;
+
+/**
+ * A multi-valued analytics value that can be represented as a date.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #streamDates},
+ * resulting in different values on each call.
+ * <p>
+ * NOTE: Most date expressions work with the {@code long} representation of the date, so that less
+ * objects need to be created during execution.
+ */
+public interface DateValueStream extends LongValueStream {
+  /**
+   * Stream the date representations of all current values, if any exist.
+   * 
+   * @param cons The consumer to accept the values
+   */
+  void streamDates(Consumer<Date> cons);
+  
+  /**
+   * An interface that represents all of the types a {@link DateValueStream} should be able to cast to. 
+   */
+  public static interface CastingDateValueStream extends DateValueStream, LongValueStream, StringValueStream {}
+
+  /**
+   * An abstract base for {@link CastingDateValueStream} that automatically casts to all types if {@link #streamLongs} is implemented.
+   */
+  public static abstract class AbstractDateValueStream implements CastingDateValueStream {
+    @Override
+    public void streamDates(Consumer<Date> cons) {
+      streamLongs((long val) -> cons.accept(new Date(val)));
+    }
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      streamLongs((long val) -> cons.accept(Instant.ofEpochMilli(val).toString()));
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      streamLongs((long val) -> cons.accept(new Date(val)));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DoubleValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DoubleValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DoubleValue.java
new file mode 100644
index 0000000..ba527f0
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DoubleValue.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+
+/**
+ * A single-valued analytics value that can be represented as a date.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #getDouble()} and {@link #exists()},
+ * resulting in different values on each call.
+ */
+public interface DoubleValue extends DoubleValueStream, AnalyticsValue {
+  /**
+   * Get the double representation of the current value.
+   * <p>
+   * NOTE: The value returned is not valid unless calling {@link #exists()} afterwards returns {@code TRUE}.
+   * 
+   * @return the current value
+   */
+  double getDouble();
+
+  /**
+   * An interface that represents all of the types a {@link DoubleValue} should be able to cast to. 
+   */
+  public static interface CastingDoubleValue extends DoubleValue, StringValue, ComparableValue {}
+  
+
+  /**
+   * An abstract base for {@link CastingDoubleValue} that automatically casts to all types if {@link #getDouble()} and {@link #exists()} are implemented.
+   */
+  public static abstract class AbstractDoubleValue implements CastingDoubleValue {
+    @Override
+    public String getString() {
+      double val = getDouble();
+      return exists() ? Double.toString(val) : null;
+    }
+    @Override
+    public Object getObject() {
+      double val = getDouble();
+      return exists() ? val : null;
+    }
+    @Override
+    public void streamDoubles(DoubleConsumer cons) {
+      double val = getDouble();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      String val = getString();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      Object val = getObject();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public ExpressionComparator<Double> getObjectComparator(String expression) {
+      return new ExpressionComparator<>(expression);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DoubleValueStream.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DoubleValueStream.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DoubleValueStream.java
new file mode 100644
index 0000000..a50c834
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/DoubleValueStream.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+/**
+ * A multi-valued analytics value that can be represented as a boolean.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #streamDoubles},
+ * resulting in different values on each call.
+ */
+public interface DoubleValueStream extends AnalyticsValueStream {
+  /**
+   * Stream the double representations of all current values, if any exist.
+   * 
+   * @param cons The consumer to accept the values
+   */
+  void streamDoubles(DoubleConsumer cons);
+
+  /**
+   * An interface that represents all of the types a {@link DoubleValueStream} should be able to cast to. 
+   */
+  public static interface CastingDoubleValueStream extends DoubleValueStream, StringValueStream {}
+
+  /**
+   * An abstract base for {@link CastingDoubleValueStream} that automatically casts to all types if {@link #streamDoubles} is implemented.
+   */
+  public static abstract class AbstractDoubleValueStream implements CastingDoubleValueStream {
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      streamDoubles((double val) -> cons.accept(Double.toString(val)));
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      streamDoubles((double val) -> cons.accept(val));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/FloatValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/FloatValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/FloatValue.java
new file mode 100644
index 0000000..16883d5
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/FloatValue.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+
+/**
+ * A single-valued analytics value that can be represented as a float.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #getFloat()} and {@link #exists()},
+ * resulting in different values on each call.
+ */
+public interface FloatValue extends FloatValueStream, AnalyticsValue {
+  /**
+   * Get the float representation of the current value.
+   * <p>
+   * NOTE: The value returned is not valid unless calling {@link #exists()} afterwards returns {@code TRUE}.
+   * 
+   * @return the current value
+   */
+  float getFloat();
+
+  /**
+   * An interface that represents all of the types a {@link FloatValue} should be able to cast to. 
+   */
+  public static interface CastingFloatValue extends FloatValue, DoubleValue, StringValue, ComparableValue {}
+
+  /**
+   * An abstract base for {@link CastingFloatValue} that automatically casts to all types if {@link #getFloat()} and {@link #exists()} are implemented.
+   */
+  public static abstract class AbstractFloatValue implements CastingFloatValue {
+    @Override
+    public double getDouble() {
+      return getFloat();
+    }
+    @Override
+    public String getString() {
+      float val = getFloat();
+      return exists() ? Float.toString(val) : null;
+    }
+    @Override
+    public Object getObject() {
+      float val = getFloat();
+      return exists() ? val : null;
+    }
+    @Override
+    public void streamFloats(FloatConsumer cons) {
+      float val = getFloat();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamDoubles(DoubleConsumer cons) {
+      double val = getDouble();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      String val = getString();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      Object val = getObject();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public ExpressionComparator<Float> getObjectComparator(String expression) {
+      return new ExpressionComparator<>(expression);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/FloatValueStream.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/FloatValueStream.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/FloatValueStream.java
new file mode 100644
index 0000000..cf15a21
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/FloatValueStream.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.solr.analytics.util.function.FloatConsumer;
+
+/**
+ * A multi-valued analytics value that can be represented as a float.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #streamFloats},
+ * resulting in different values on each call.
+ */
+public interface FloatValueStream extends AnalyticsValueStream {
+  /**
+   * Stream the float representations of all current values, if any exist.
+   * 
+   * @param cons The consumer to accept the values
+   */
+  void streamFloats(FloatConsumer cons);
+
+  /**
+   * An interface that represents all of the types a {@link FloatValueStream} should be able to cast to. 
+   */
+  public static interface CastingFloatValueStream extends FloatValueStream, DoubleValueStream, StringValueStream { }
+
+  /**
+   * An abstract base for {@link CastingFloatValueStream} that automatically casts to all types if {@link #streamFloats} is implemented.
+   */
+  public static abstract class AbstractFloatValueStream implements CastingFloatValueStream {
+    @Override
+    public void streamDoubles(DoubleConsumer cons) {
+      streamFloats((float val) -> cons.accept(val));
+    }
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      streamFloats((float val) -> cons.accept(Float.toString(val)));
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      streamFloats((float val) -> cons.accept(val));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/IntValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/IntValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/IntValue.java
new file mode 100644
index 0000000..5688357
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/IntValue.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+
+/**
+ * A single-valued analytics value that can be represented as an int.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #getInt()} and {@link #exists()},
+ * resulting in different values on each call.
+ */
+public interface IntValue extends IntValueStream, AnalyticsValue {
+  /**
+   * Get the int representation of the current value.
+   * <p>
+   * NOTE: The value returned is not valid unless calling {@link #exists()} afterwards returns {@code TRUE}.
+   * 
+   * @return the current value
+   */
+  int getInt();
+
+  /**
+   * An interface that represents all of the types a {@link IntValue} should be able to cast to. 
+   */
+  public static interface CastingIntValue extends IntValue, LongValue, FloatValue,DoubleValue, StringValue, ComparableValue { }
+
+  /**
+   * An abstract base for {@link CastingIntValue} that automatically casts to all types if {@link #getInt()} and {@link #exists()} are implemented.
+   */
+  public static abstract class AbstractIntValue implements CastingIntValue {
+    @Override
+    public long getLong() {
+      return getInt();
+    }
+    @Override
+    public float getFloat() {
+      return getInt();
+    }
+    @Override
+    public double getDouble() {
+      return getInt();
+    }
+    @Override
+    public String getString() {
+      int val = getInt();
+      return exists() ? Integer.toString(val) : null;
+    }
+    @Override
+    public Object getObject() {
+      int val = getInt();
+      return exists() ? val : null;
+    }
+    @Override
+    public void streamInts(IntConsumer cons) {
+      int val = getInt();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamLongs(LongConsumer cons) {
+      long val = getLong();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamFloats(FloatConsumer cons) {
+      float val = getFloat();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamDoubles(DoubleConsumer cons) {
+      double val = getDouble();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      String val = getString();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      Object val = getObject();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public ExpressionComparator<Integer> getObjectComparator(String expression) {
+      return new ExpressionComparator<>(expression);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/IntValueStream.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/IntValueStream.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/IntValueStream.java
new file mode 100644
index 0000000..9cbe28c
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/IntValueStream.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.util.function.FloatConsumer;
+
+/**
+ * A multi-valued analytics value that can be represented as a int.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #streamInts},
+ * resulting in different values on each call.
+ */
+public interface IntValueStream extends AnalyticsValueStream {
+  /**
+   * Stream the int representations of all current values, if any exist.
+   * 
+   * @param cons The consumer to accept the values
+   */
+  void streamInts(IntConsumer cons);
+
+  /**
+   * An interface that represents all of the types a {@link IntValueStream} should be able to cast to. 
+   */
+  public static interface CastingIntValueStream extends IntValueStream, LongValueStream, FloatValueStream, 
+                                                        DoubleValueStream, StringValueStream {}
+
+  /**
+   * An abstract base for {@link CastingIntValueStream} that automatically casts to all types if {@link #streamInts} is implemented.
+   */
+  public static abstract class AbstractIntValueStream implements CastingIntValueStream {
+    @Override
+    public void streamLongs(LongConsumer cons) {
+      streamInts((int val) -> cons.accept(val));
+    }
+    @Override
+    public void streamFloats(FloatConsumer cons) {
+      streamInts((int val) -> cons.accept(val));
+    }
+    @Override
+    public void streamDoubles(DoubleConsumer cons) {
+      streamInts((int val) -> cons.accept(val));
+    }
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      streamInts((int val) -> cons.accept(Integer.toString(val)));
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      streamInts((int val) -> cons.accept(val));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/LongValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/LongValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/LongValue.java
new file mode 100644
index 0000000..623cd13
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/LongValue.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+
+/**
+ * A single-valued analytics value that can be represented as a long.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #getLong()} and {@link #exists()},
+ * resulting in different values on each call.
+ */
+public interface LongValue extends LongValueStream, AnalyticsValue {
+  /**
+   * Get the long representation of the current value.
+   * <p>
+   * NOTE: The value returned is not valid unless calling {@link #exists()} afterwards returns {@code TRUE}.
+   * 
+   * @return the current value
+   */
+  long getLong();
+
+  /**
+   * An interface that represents all of the types a {@link LongValue} should be able to cast to. 
+   */
+  public static interface CastingLongValue extends LongValue, DoubleValue, StringValue, ComparableValue {}
+
+  /**
+   * An abstract base for {@link CastingLongValue} that automatically casts to all types if {@link #getLong()} and {@link #exists()} are implemented.
+   */
+  public static abstract class AbstractLongValue implements CastingLongValue {
+    @Override
+    public double getDouble() {
+      return getLong();
+    }
+    @Override
+    public String getString() {
+      long val = getLong();
+      return exists() ? Long.toString(val) : null;
+    }
+    @Override
+    public Object getObject() {
+      long val = getLong();
+      return exists() ? val : null;
+    }
+    @Override
+    public void streamLongs(LongConsumer cons) {
+      long val = getLong();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamDoubles(DoubleConsumer cons) {
+      double val = getDouble();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      String val = getString();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      Object val = getObject();
+      if (exists()) {
+        cons.accept(val);
+      }
+    }
+    @Override
+    public ExpressionComparator<Long> getObjectComparator(String expression) {
+      return new ExpressionComparator<>(expression);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/LongValueStream.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/LongValueStream.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/LongValueStream.java
new file mode 100644
index 0000000..d18cb03
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/LongValueStream.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.LongConsumer;
+
+/**
+ * A multi-valued analytics value that can be represented as a long.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #streamLongs},
+ * resulting in different values on each call.
+ */
+public interface LongValueStream extends AnalyticsValueStream {
+  /**
+   * Stream the long representations of all current values, if any exist.
+   * 
+   * @param cons The consumer to accept the values
+   */
+  void streamLongs(LongConsumer cons);
+
+  /**
+   * An interface that represents all of the types a {@link LongValueStream} should be able to cast to. 
+   */
+  public static interface CastingLongValueStream extends LongValueStream, DoubleValueStream, 
+                                                         StringValueStream { }
+
+  /**
+   * An abstract base for {@link CastingLongValueStream} that automatically casts to all types if {@link #streamLongs} is implemented.
+   */
+  public static abstract class AbstractLongValueStream implements CastingLongValueStream {
+    @Override
+    public void streamDoubles(DoubleConsumer cons) {
+      streamLongs((long val) -> cons.accept(val));
+    }
+    @Override
+    public void streamStrings(Consumer<String> cons) {
+      streamLongs((long val) -> cons.accept(Long.toString(val)));
+    }
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      streamLongs((long val) -> cons.accept(val));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/StringValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/StringValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/StringValue.java
new file mode 100644
index 0000000..7baf18e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/StringValue.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+
+/**
+ * A single-valued analytics value that can be represented as a string.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #getString()} and {@link #exists()},
+ * resulting in different values on each call.
+ */
+public interface StringValue extends StringValueStream, AnalyticsValue {
+  /**
+   * Get the String representation of the current value.
+   * <p>
+   * NOTE: The value returned is not valid unless calling {@link #exists()} afterwards returns {@code TRUE}.
+   * 
+   * @return the current value
+   */
+  String getString();
+
+  /**
+   * An interface that represents all of the types a {@link StringValue} should be able to cast to. 
+   */
+  public static interface CastingStringValue extends StringValue, ComparableValue {}
+
+  /**
+   * An abstract base for {@link CastingStringValue} that automatically casts to all types if {@link #getString()} and {@link #exists()} are implemented.
+   */
+  public static abstract class AbstractStringValue implements CastingStringValue {
+    @Override
+    public String getObject() {
+      return getString();
+    }
+    @Override
+    public void streamStrings(Consumer<String> func) {
+      String val = getString();
+      if (exists()) {
+        func.accept(val);
+      }
+    }
+    @Override
+    public void streamObjects(Consumer<Object> func) {
+      Object val = getObject();
+      if (exists()) {
+        func.accept(val);
+      }
+    }
+    @Override
+    public ExpressionComparator<String> getObjectComparator(String expression) {
+      return new ExpressionComparator<>(expression);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/StringValueStream.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/StringValueStream.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/StringValueStream.java
new file mode 100644
index 0000000..2269ac4
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/StringValueStream.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value;
+
+import java.util.function.Consumer;
+
+/**
+ * A multi-valued analytics value that can be represented as a String.
+ * <p>
+ * The back-end production of the value can change inbetween calls to {@link #streamStrings},
+ * resulting in different values on each call.
+ */
+public interface StringValueStream extends AnalyticsValueStream {
+  /**
+   * Stream the String representations of all current values, if any exist.
+   * 
+   * @param cons The consumer to accept the values
+   */
+  void streamStrings(Consumer<String> cons);
+
+  /**
+   * An interface that represents all of the types a {@link StringValueStream} should be able to cast to. 
+   */
+  public static interface CastingStringValueStream extends StringValueStream {}
+
+  /**
+   * An abstract base for {@link CastingStringValueStream} that automatically casts to all types if {@link #streamStrings} is implemented.
+   */
+  public static abstract class AbstractStringValueStream implements CastingStringValueStream {
+    @Override
+    public void streamObjects(Consumer<Object> cons) {
+      streamStrings((String val) -> cons.accept(val));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantBooleanValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantBooleanValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantBooleanValue.java
new file mode 100644
index 0000000..aeccaaa
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantBooleanValue.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.analytics.value.constant;
+
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.facet.compare.ConstantComparator;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.value.BooleanValue;
+import org.apache.solr.analytics.value.BooleanValue.CastingBooleanValue;
+
+/**
+ * A constant {@link BooleanValue}. Every call to {@link #getBoolean()} and other methods will return the same constant value.
+ */
+public class ConstantBooleanValue extends ConstantValue implements CastingBooleanValue {
+  private final boolean value;
+  private final String valueStr;
+  public static final String name = "const_bool";
+  private final String exprStr;
+
+  public ConstantBooleanValue(boolean value) {
+    this.value = value;
+    this.valueStr = Boolean.toString(value);
+    this.exprStr = ConstantValue.createExpressionString(this, valueStr);
+  }
+
+  @Override
+  public boolean getBoolean() {
+    return value;
+  }
+  @Override
+  public String getString() {
+    return valueStr;
+  }
+  @Override
+  public Object getObject() {
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void streamBooleans(BooleanConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    cons.accept(valueStr);
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    cons.accept(value);
+  }
+
+  @Override
+  public ConstantComparator getObjectComparator(String expression) {
+    return new ConstantComparator();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.CONST;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantDateValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantDateValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantDateValue.java
new file mode 100644
index 0000000..5614d6c
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantDateValue.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value.constant;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.function.Consumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.facet.compare.ConstantComparator;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValue.CastingDateValue;
+
+/**
+ * A constant {@link DateValue}. Every call to {@link #getDate()} and other methods will return the same constant value.
+ */
+public class ConstantDateValue extends ConstantValue implements CastingDateValue {
+  private final long value;
+  private final Date valueDate;
+  private final String valueStr;
+  public static final String name = "const_date";
+  private final String exprStr;
+
+  public ConstantDateValue(long value) {
+    this.value = value;
+    this.valueDate = new Date(value);
+    this.valueStr = Instant.ofEpochMilli(value).toString();
+    this.exprStr = ConstantValue.createExpressionString(this, valueStr);
+  }
+
+
+  @Override
+  public long getLong() {
+    return value;
+  }
+  @Override
+  public Date getDate() {
+    return valueDate;
+  }
+  @Override
+  public String getString() {
+    return valueStr;
+  }
+  @Override
+  public Object getObject() {
+    return valueDate;
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamDates(Consumer<Date> cons) {
+    cons.accept(valueDate);
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    cons.accept(valueStr);
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    cons.accept(valueDate);
+  }
+
+  @Override
+  public ConstantComparator getObjectComparator(String expression) {
+    return new ConstantComparator();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.CONST;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantDoubleValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantDoubleValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantDoubleValue.java
new file mode 100644
index 0000000..cf5682a
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantDoubleValue.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value.constant;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.solr.analytics.facet.compare.ConstantComparator;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValue.CastingDoubleValue;
+
+/**
+ * A constant {@link DoubleValue}. Every call to {@link #getDouble()} and other methods will return the same constant value.
+ */
+public class ConstantDoubleValue extends ConstantValue implements CastingDoubleValue {
+  private final double value;
+  private final String valueStr;
+  public static final String name = "const_double";
+  private final String exprStr;
+
+  public ConstantDoubleValue(double value) {
+    this.value = value;
+    this.valueStr = Double.toString(value);
+    this.exprStr = ConstantValue.createExpressionString(this, valueStr);
+  }
+
+  @Override
+  public double getDouble() {
+    return value;
+  }
+  @Override
+  public String getString() {
+    return valueStr;
+  }
+  @Override
+  public Object getObject() {
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    cons.accept(valueStr);
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    cons.accept(value);
+  }
+
+  @Override
+  public ConstantComparator getObjectComparator(String expression) {
+    return new ConstantComparator();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.CONST;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantFloatValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantFloatValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantFloatValue.java
new file mode 100644
index 0000000..ec495a4
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantFloatValue.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value.constant;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+
+import org.apache.solr.analytics.facet.compare.ConstantComparator;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValue.CastingFloatValue;
+
+/**
+ * A constant {@link FloatValue}. Every call to {@link #getFloat()} and other methods will return the same constant value.
+ */
+public class ConstantFloatValue extends ConstantValue implements CastingFloatValue {
+  private final float value;
+  private final String valueStr;
+  public static final String name = "const_float";
+  private final String exprStr;
+
+  public ConstantFloatValue(float value) {
+    this.value = value;
+    this.valueStr = Float.toString(value);
+    this.exprStr = ConstantValue.createExpressionString(this, valueStr);
+  }
+
+  @Override
+  public float getFloat() {
+    return value;
+  }
+  @Override
+  public double getDouble() {
+    return value;
+  }
+  @Override
+  public String getString() {
+    return valueStr;
+  }
+  @Override
+  public Object getObject() {
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    cons.accept(valueStr);
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    cons.accept(value);
+  }
+
+  @Override
+  public ConstantComparator getObjectComparator(String expression) {
+    return new ConstantComparator();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.CONST;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantIntValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantIntValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantIntValue.java
new file mode 100644
index 0000000..1e43359
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantIntValue.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value.constant;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.IntConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.facet.compare.ConstantComparator;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValue.CastingIntValue;
+
+/**
+ * A constant {@link IntValue}. Every call to {@link #getInt()} and other methods will return the same constant value.
+ */
+public class ConstantIntValue extends ConstantValue implements CastingIntValue {
+  private final int value;
+  private final String valueStr;
+  public static final String name = "const_int";
+  private final String exprStr;
+
+  public ConstantIntValue(int value) {
+    this.value = value;
+    this.valueStr = Integer.toString(value);
+    this.exprStr = ConstantValue.createExpressionString(this, valueStr);
+  }
+
+
+  @Override
+  public int getInt() {
+    return value;
+  }
+  @Override
+  public long getLong() {
+    return value;
+  }
+  @Override
+  public float getFloat() {
+    return value;
+  }
+  @Override
+  public double getDouble() {
+    return value;
+  }
+  @Override
+  public String getString() {
+    return valueStr;
+  }
+  @Override
+  public Object getObject() {
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void streamInts(IntConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamFloats(FloatConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    cons.accept(valueStr);
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    cons.accept(value);
+  }
+
+  @Override
+  public ConstantComparator getObjectComparator(String expression) {
+    return new ConstantComparator();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.CONST;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantLongValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantLongValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantLongValue.java
new file mode 100644
index 0000000..d4c54d0
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantLongValue.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value.constant;
+
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.facet.compare.ConstantComparator;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValue.CastingLongValue;
+
+/**
+ * A constant {@link LongValue}. Every call to {@link #getLong()} and other methods will return the same constant value.
+ */
+public class ConstantLongValue extends ConstantValue implements CastingLongValue {
+  private final long value;
+  private final String valueStr;
+  public static final String name = "const_long";
+  private final String exprStr;
+
+  public ConstantLongValue(long value) {
+    this.value = value;
+    this.valueStr = Long.toString(value);
+    this.exprStr = ConstantValue.createExpressionString(this, valueStr);
+  }
+
+
+  @Override
+  public long getLong() {
+    return value;
+  }
+  @Override
+  public double getDouble() {
+    return value;
+  }
+  @Override
+  public String getString() {
+    return valueStr;
+  }
+  @Override
+  public Object getObject() {
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void streamLongs(LongConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamDoubles(DoubleConsumer cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    cons.accept(valueStr);
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    cons.accept(value);
+  }
+
+  @Override
+  public ConstantComparator getObjectComparator(String expression) {
+    return new ConstantComparator();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.CONST;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantStringValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantStringValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantStringValue.java
new file mode 100644
index 0000000..c32a2a3
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantStringValue.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value.constant;
+
+import java.util.function.Consumer;
+
+import org.apache.solr.analytics.facet.compare.ConstantComparator;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValue.CastingStringValue;
+
+/**
+ * A constant {@link StringValue}. Every call to {@link #getString()} and other methods will return the same constant value.
+ */
+public class ConstantStringValue extends ConstantValue implements CastingStringValue {
+  String value;
+  public static final String name = "const_str";
+  private final String exprStr;
+
+  public ConstantStringValue(String value) {
+    this.value = value;
+    this.exprStr = ConstantValue.createExpressionString(this, value);
+  }
+
+  @Override
+  public String getString() {
+    return value;
+  }
+  @Override
+  public Object getObject() {
+    return value;
+  }
+  @Override
+  public boolean exists() {
+    return true;
+  }
+
+  @Override
+  public void streamStrings(Consumer<String> cons) {
+    cons.accept(value);
+  }
+  @Override
+  public void streamObjects(Consumer<Object> cons) {
+    cons.accept(value);
+  }
+
+  @Override
+  public ConstantComparator getObjectComparator(String expression) {
+    return new ConstantComparator();
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getExpressionStr() {
+    return exprStr;
+  }
+
+  @Override
+  public ExpressionType getExpressionType() {
+    return ExpressionType.CONST;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantValue.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantValue.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantValue.java
new file mode 100644
index 0000000..2e364b1
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/ConstantValue.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.value.constant;
+
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.solr.analytics.ExpressionFactory.ConstantFunction;
+import org.apache.solr.analytics.value.AnalyticsValue;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * The parent class of all constant Analytics values.
+ * <p>
+ * Constant values can be specified in the following ways in analytics requests:
+ * <ul>
+ * <li> Constant booleans must match one of the following in any case: true, t, false, f
+ * <li> Constant strings must be surrounded with "s or 's
+ * <li> Constant numbers do not have to be surrounded with anything
+ * <li> Constant dates must match one of the following patterns
+ * <ul> 
+ * <li> yyyy-MM-dd
+ * <li> yyyy-MM-ddXXX
+ * <li> yyyy-MM-dd'T'HH:mm:ssZ
+ * <li> yyyy-MM-dd'T'HH:mm:ssXXX
+ * <li> yyyy-MM-dd'T'HH:mm:ss.SSSZ
+ * <li> yyyy-MM-dd'T'HH:mm:ss.SSSXXX
+ * </ul>
+ * </li> 
+ * </ul>
+ */
+public abstract class ConstantValue {
+  private static final Pattern truePattern = Pattern.compile("^true|t$", Pattern.CASE_INSENSITIVE);
+  private static final Pattern falsePattern = Pattern.compile("^false|f$", Pattern.CASE_INSENSITIVE);
+  private static final SimpleDateFormat dateParserBase = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT);
+  private static final SimpleDateFormat dateParser1 = new SimpleDateFormat("yyyy-MM-ddZ", Locale.ROOT);
+  private static final SimpleDateFormat dateParser2 = new SimpleDateFormat("yyyy-MM-ddXXX", Locale.ROOT);
+  private static final SimpleDateFormat dateParser3 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ROOT);
+  private static final SimpleDateFormat dateParser4 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ROOT);
+  private static final SimpleDateFormat dateParser5 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.ROOT);
+  private static final SimpleDateFormat dateParser6 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ROOT);
+  
+  public static final ConstantFunction creatorFunction = (param -> {
+    param = param.trim();
+    
+    // Try to create a string
+    if ((param.charAt(0)=='"' && param.charAt(param.length()-1)=='"')
+        || (param.charAt(0)=='\'' && param.charAt(param.length()-1)=='\'')) {
+      return new ConstantStringValue(param.substring(1, param.length()-1));
+    }
+    
+    // Try to create a boolean
+    Matcher m = truePattern.matcher(param);
+    if (m.matches()) {
+      return new ConstantBooleanValue(true);
+    }
+    m = falsePattern.matcher(param);
+    if (m.matches()) {
+      return new ConstantBooleanValue(false);
+    }
+    
+    // Try to create a number
+    try {
+      AnalyticsValue value = new ConstantDoubleValue(Double.parseDouble(param));
+      try {
+        value = new ConstantLongValue(Long.parseLong(param));
+        value = new ConstantIntValue(Integer.parseInt(param));
+      } catch (NumberFormatException e) {
+        value = new ConstantFloatValue(Float.parseFloat(param));
+      }
+      return value;
+    } catch (NumberFormatException e) {
+      // The constant is not a number
+    }
+    
+    // Try to create a date
+    try {
+      AnalyticsValue value = new ConstantDateValue(dateParserBase.parse(param).getTime());
+      try {
+        return new ConstantDateValue(dateParser1.parse(param).getTime());
+      } catch (Exception e) {}
+      try {
+        return new ConstantDateValue(dateParser2.parse(param).getTime());
+      } catch (Exception e) {}
+      try {
+        return new ConstantDateValue(dateParser3.parse(param).getTime());
+      } catch (Exception e) {}
+      try {
+        return new ConstantDateValue(dateParser4.parse(param).getTime());
+      } catch (Exception e) {}
+      try {
+        return new ConstantDateValue(dateParser5.parse(param).getTime());
+      } catch (Exception e) {}
+      try {
+        return new ConstantDateValue(dateParser6.parse(param).getTime());
+      } catch (Exception e) {}
+      return value;
+    } catch (Exception e) {
+      throw new SolrException(ErrorCode.BAD_REQUEST,"The parameter "+param+" could not be cast to any constant.");
+    }
+    
+  });
+  
+  static String createExpressionString(AnalyticsValueStream func, 
+                                       Object param) {
+    return String.format(Locale.ROOT,"%s(%s)",
+                         func.getName(),
+                         param.toString());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/package-info.java
new file mode 100644
index 0000000..eb6f29d
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/value/constant/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Constant values to be used in analytics expressions.
+ */
+package org.apache.solr.analytics.value.constant;
+
+


[06/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/RangeEndpointCalculator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/RangeEndpointCalculator.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/RangeEndpointCalculator.java
deleted file mode 100644
index fa29022..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/RangeEndpointCalculator.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.solr.analytics.request.RangeFacetRequest;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.params.FacetParams.FacetRangeInclude;
-import org.apache.solr.common.params.FacetParams.FacetRangeOther;
-import org.apache.solr.schema.FieldType;
-import org.apache.solr.schema.SchemaField;
-import org.apache.solr.schema.TrieDateField;
-import org.apache.solr.schema.TrieField;
-import org.apache.solr.util.DateMathParser;
-
-
-public abstract class RangeEndpointCalculator<T extends Comparable<T>> {
-  protected final SchemaField field;
-  protected final RangeFacetRequest request;
-  
-  public RangeEndpointCalculator(final RangeFacetRequest request) {
-    this.field = request.getField();
-    this.request = request;
-  }
-
-  /**
-   * Formats a Range endpoint for use as a range label name in the response.
-   * Default Impl just uses toString()
-   */
-  public String formatValue(final T val) {
-    return val.toString();
-  }
-  
-  /**
-   * Parses a String param into an Range endpoint value throwing 
-   * a useful exception if not possible
-   */
-  public final T getValue(final String rawval) {
-    try {
-      return parseVal(rawval);
-    } catch (Exception e) {
-      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can't parse value "+rawval+" for field: " + field.getName(), e);
-    }
-  }
-  
-  /**
-   * Parses a String param into an Range endpoint. 
-   * Can throw a low level format exception as needed.
-   */
-  protected abstract T parseVal(final String rawval) throws java.text.ParseException;
-
-  /** 
-   * Parses a String param into a value that represents the gap and 
-   * can be included in the response, throwing 
-   * a useful exception if not possible.
-   *
-   * Note: uses Object as the return type instead of T for things like 
-   * Date where gap is just a DateMathParser string 
-   */
-  public final Object getGap(final String gap) {
-    try {
-      return parseGap(gap);
-    } catch (Exception e) {
-      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can't parse gap "+gap+" for field: " + field.getName(), e);
-    }
-  }
-
-  /**
-   * Parses a String param into a value that represents the gap and 
-   * can be included in the response. 
-   * Can throw a low level format exception as needed.
-   *
-   * Default Impl calls parseVal
-   */
-  protected Object parseGap(final String rawval) throws java.text.ParseException {
-    return parseVal(rawval);
-  }
-
-  /**
-   * Adds the String gap param to a low Range endpoint value to determine 
-   * the corrisponding high Range endpoint value, throwing 
-   * a useful exception if not possible.
-   */
-  public final T addGap(T value, String gap) {
-    try {
-      return parseAndAddGap(value, gap);
-    } catch (Exception e) {
-      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Can't add gap "+gap+" to value " + value + " for field: " + field.getName(), e);
-    }
-  }
-  
-  /**
-   * Adds the String gap param to a low Range endpoint value to determine 
-   * the corrisponding high Range endpoint value.
-   * Can throw a low level format exception as needed.
-   */
-  protected abstract T parseAndAddGap(T value, String gap) throws java.text.ParseException;
-
-  public static class FacetRange {
-    public final String name;
-    public final String lower;
-    public final String upper;
-    public final boolean includeLower;
-    public final boolean includeUpper;
-    
-    public FacetRange(String name, String lower, String upper, boolean includeLower, boolean includeUpper) {
-      this.name = name;
-      this.lower = lower;
-      this.upper = upper;
-      this.includeLower = includeLower;
-      this.includeUpper = includeUpper;
-    }
-  }
-  
-  public List<FacetRange> getRanges(){
-
-    final T start = getValue(request.getStart());
-    T end = getValue(request.getEnd()); // not final, hardend may change this
-    
-    if( end.compareTo(start) < 0 ){
-      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "range facet 'end' comes before 'start': "+end+" < "+start);
-    }
-    
-    // explicitly return the gap.  compute this early so we are more 
-    // likely to catch parse errors before attempting math
-    final String[] gaps = request.getGaps();
-    String gap = gaps[0];
-    
-    final EnumSet<FacetRangeInclude> include = request.getInclude();
-        
-    T low = start;
-    
-    List<FacetRange> ranges = new ArrayList<>();
-    
-    int gapCounter = 0;
-    
-    while (low.compareTo(end) < 0) {
-      if (gapCounter<gaps.length) {
-        gap = gaps[gapCounter++];
-      }
-      T high = addGap(low,gap);
-      if (end.compareTo(high) < 0) {
-        if (request.isHardEnd()){
-          high = end;
-        } else {
-          end = high;
-        }
-      }
-      
-      if (high.compareTo(low) < 0) {
-        throw new SolrException (SolrException.ErrorCode.BAD_REQUEST, "range facet infinite loop (is gap negative? did the math overflow?)");
-      }
-      
-      if (high.compareTo(low) == 0) {
-        throw new SolrException (SolrException.ErrorCode.BAD_REQUEST, "range facet infinite loop: gap is either zero, or too small relative start/end and caused underflow: " + low + " + " + gap + " = " + high );
-      }
-      
-      final boolean includeLower = (include.contains(FacetRangeInclude.ALL) ||
-                                    include.contains(FacetRangeInclude.LOWER) ||
-                                   (include.contains(FacetRangeInclude.EDGE) && 
-                                   0 == low.compareTo(start)));
-      final boolean includeUpper = (include.contains(FacetRangeInclude.ALL) ||
-                                    include.contains(FacetRangeInclude.UPPER) ||
-                                   (include.contains(FacetRangeInclude.EDGE) && 
-                                   0 == high.compareTo(end)));
-      
-      final String lowS = formatValue(low);
-      final String highS = formatValue(high);
-
-      ranges.add( new FacetRange(lowS,lowS,highS,includeLower,includeUpper) );
-      low = high;
-    }
-    
-    final Set<FacetRangeOther> others = request.getOthers();
-    if (null != others && 0 < others.size() ) {
-      
-      // no matter what other values are listed, we don't do
-      // anything if "none" is specified.
-      if( !others.contains(FacetRangeOther.NONE) ) {
-        
-        boolean all = others.contains(FacetRangeOther.ALL);
-
-        if (all || others.contains(FacetRangeOther.BEFORE)) {
-          // include upper bound if "outer" or if first gap doesn't already include it
-          ranges.add( new FacetRange(FacetRangeOther.BEFORE.toString(), 
-                                        null, formatValue(start), false, include.contains(FacetRangeInclude.OUTER) || include.contains(FacetRangeInclude.ALL) ||
-                                                            !(include.contains(FacetRangeInclude.LOWER) || include.contains(FacetRangeInclude.EDGE)) ) );
-          
-        }
-        if (all || others.contains(FacetRangeOther.AFTER)) {
-          // include lower bound if "outer" or if last gap doesn't already include it
-          ranges.add( new FacetRange(FacetRangeOther.AFTER.toString(), 
-                                        formatValue(end), null, include.contains(FacetRangeInclude.OUTER) || include.contains(FacetRangeInclude.ALL) ||
-                                                   !(include.contains(FacetRangeInclude.UPPER) || include.contains(FacetRangeInclude.EDGE)), false) );
-        }
-        if (all || others.contains(FacetRangeOther.BETWEEN)) {
-          ranges.add( new FacetRange(FacetRangeOther.BETWEEN.toString(), formatValue(start), formatValue(end),
-                                        include.contains(FacetRangeInclude.LOWER) || include.contains(FacetRangeInclude.EDGE) || include.contains(FacetRangeInclude.ALL),
-                                        include.contains(FacetRangeInclude.UPPER) || include.contains(FacetRangeInclude.EDGE) || include.contains(FacetRangeInclude.ALL)) );
-        }
-      }
-      
-    }
-  
-    return ranges;
-  }
-  
-  public static RangeEndpointCalculator<? extends Comparable<?>> create(RangeFacetRequest request){
-    final SchemaField sf = request.getField();
-    final FieldType ft = sf.getType();
-    final RangeEndpointCalculator<?> calc;
-    if (ft instanceof TrieField) {
-      switch (ft.getNumberType()) {
-        case FLOAT:
-          calc = new FloatRangeEndpointCalculator(request);
-          break;
-        case DOUBLE:
-          calc = new DoubleRangeEndpointCalculator(request);
-          break;
-        case INTEGER:
-          calc = new IntegerRangeEndpointCalculator(request);
-          break;
-        case LONG:
-          calc = new LongRangeEndpointCalculator(request);
-          break;
-        case DATE:
-          calc = new DateRangeEndpointCalculator(request, null);
-          break;
-        default:
-          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Unable to range facet on tried field of unexpected type:" + sf.getName());
-      }
-    } else {
-      throw new SolrException (SolrException.ErrorCode.BAD_REQUEST, "Unable to range facet on field:" + sf);
-    } 
-    return calc;
-  }
-  
-  public static class FloatRangeEndpointCalculator extends RangeEndpointCalculator<Float> {
-  
-    public FloatRangeEndpointCalculator(final RangeFacetRequest request) { super(request); }
-    
-    @Override
-    protected Float parseVal(String rawval) {
-      return Float.valueOf(rawval);
-    }
-    
-    @Override
-    public Float parseAndAddGap(Float value, String gap) {
-      return new Float(value.floatValue() + Float.parseFloat(gap));
-    }
-    
-  }
-  
-  public static class DoubleRangeEndpointCalculator extends RangeEndpointCalculator<Double> {
-  
-    public DoubleRangeEndpointCalculator(final RangeFacetRequest request) { super(request); }
-    
-    @Override
-    protected Double parseVal(String rawval) {
-      return Double.valueOf(rawval);
-    }
-    
-    @Override
-    public Double parseAndAddGap(Double value, String gap) {
-      return new Double(value.doubleValue() + Double.parseDouble(gap));
-    }
-    
-  }
-  
-  public static class IntegerRangeEndpointCalculator extends RangeEndpointCalculator<Integer> {
-  
-    public IntegerRangeEndpointCalculator(final RangeFacetRequest request) { super(request); }
-    
-    @Override
-    protected Integer parseVal(String rawval) {
-      return Integer.valueOf(rawval);
-    }
-    
-    @Override
-    public Integer parseAndAddGap(Integer value, String gap) {
-      return new Integer(value.intValue() + Integer.parseInt(gap));
-    }
-    
-  }
-  
-  public static class LongRangeEndpointCalculator extends RangeEndpointCalculator<Long> {
-  
-    public LongRangeEndpointCalculator(final RangeFacetRequest request) { super(request); }
-    
-    @Override
-    protected Long parseVal(String rawval) {
-      return Long.valueOf(rawval);
-    }
-    
-    @Override
-    public Long parseAndAddGap(Long value, String gap) {
-      return new Long(value.longValue() + Long.parseLong(gap));
-    }
-    
-  }
-  
-  public static class DateRangeEndpointCalculator extends RangeEndpointCalculator<Date> {
-    private final Date now;
-    public DateRangeEndpointCalculator(final RangeFacetRequest request, final Date now) { 
-      super(request); 
-      this.now = now;
-      if (! (field.getType() instanceof TrieDateField) ) {
-        throw new IllegalArgumentException("SchemaField must use field type extending TrieDateField");
-      }
-    }
-    
-    @Override
-    public String formatValue(Date val) {
-      return val.toInstant().toString();
-    }
-    
-    @Override
-    protected Date parseVal(String rawval) {
-      return DateMathParser.parseMath(now, rawval);
-    }
-    
-    @Override
-    protected Object parseGap(final String rawval) {
-      return rawval;
-    }
-    
-    @Override
-    public Date parseAndAddGap(Date value, String gap) throws java.text.ParseException {
-      final DateMathParser dmp = new DateMathParser();
-      dmp.setNow(value);
-      return dmp.parseMath(gap);
-    }
-    
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/BooleanConsumer.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/BooleanConsumer.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/BooleanConsumer.java
new file mode 100644
index 0000000..66d7a13
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/BooleanConsumer.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.util.function;
+
+import java.util.Objects;
+import java.util.function.Consumer;
+
+/**
+ * Represents an operation that accepts a single {@code boolean}-valued argument and
+ * returns no result.  This is the primitive type specialization of
+ * {@link Consumer} for {@code boolean}.  Unlike most other functional interfaces,
+ * {@code IntConsumer} is expected to operate via side-effects.
+ *
+ * <p>This is a <a href="package-summary.html">functional interface</a>
+ * whose functional method is {@link #accept(boolean)}.
+ *
+ * @see Consumer
+ */
+@FunctionalInterface
+public interface BooleanConsumer {
+
+  /**
+   * Performs this operation on the given argument.
+   *
+   * @param value the input argument
+   */
+  void accept(boolean value);
+
+  /**
+   * Returns a composed {@code DoubleConsumer} that performs, in sequence, this
+   * operation followed by the {@code after} operation. If performing either
+   * operation throws an exception, it is relayed to the caller of the
+   * composed operation.  If performing this operation throws an exception,
+   * the {@code after} operation will not be performed.
+   *
+   * @param after the operation to perform after this operation
+   * @return a composed {@code DoubleConsumer} that performs in sequence this
+   * operation followed by the {@code after} operation
+   * @throws NullPointerException if {@code after} is null
+   */
+  default BooleanConsumer andThen(BooleanConsumer after) {
+    Objects.requireNonNull(after);
+    return (boolean t) -> { accept(t); after.accept(t); };
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/FloatConsumer.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/FloatConsumer.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/FloatConsumer.java
new file mode 100644
index 0000000..baa5c12
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/FloatConsumer.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.util.function;
+
+import java.util.Objects;
+import java.util.function.Consumer;
+
+/**
+ * Represents an operation that accepts a single {@code float}-valued argument and
+ * returns no result.  This is the primitive type specialization of
+ * {@link Consumer} for {@code float}.  Unlike most other functional interfaces,
+ * {@code IntConsumer} is expected to operate via side-effects.
+ *
+ * <p>This is a <a href="package-summary.html">functional interface</a>
+ * whose functional method is {@link #accept(float)}.
+ *
+ * @see Consumer
+ */
+@FunctionalInterface
+public interface FloatConsumer {
+
+  /**
+   * Performs this operation on the given argument.
+   *
+   * @param value the input argument
+   */
+  void accept(float value);
+
+  /**
+   * Returns a composed {@code DoubleConsumer} that performs, in sequence, this
+   * operation followed by the {@code after} operation. If performing either
+   * operation throws an exception, it is relayed to the caller of the
+   * composed operation.  If performing this operation throws an exception,
+   * the {@code after} operation will not be performed.
+   *
+   * @param after the operation to perform after this operation
+   * @return a composed {@code DoubleConsumer} that performs in sequence this
+   * operation followed by the {@code after} operation
+   * @throws NullPointerException if {@code after} is null
+   */
+  default FloatConsumer andThen(FloatConsumer after) {
+    Objects.requireNonNull(after);
+    return (float t) -> { accept(t); after.accept(t); };
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/FloatSupplier.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/FloatSupplier.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/FloatSupplier.java
new file mode 100644
index 0000000..9801ea7
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/FloatSupplier.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.util.function;
+
+import java.util.function.Supplier;
+
+/**
+ * Represents a supplier of {@code float}-valued results.  This is the
+ * {@code float}-producing primitive specialization of {@link Supplier}.
+ *
+ * <p>There is no requirement that a new or distinct result be returned each
+ * time the supplier is invoked.
+ *
+ * <p>This is a <a href="package-summary.html">functional interface</a>
+ * whose functional method is {@link #getAsFloat()}.
+ *
+ * @see Supplier
+ */
+@FunctionalInterface
+public interface FloatSupplier {
+  /**
+   * Gets a result.
+   *
+   * @return a result
+   */
+  float getAsFloat();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/package-info.java
new file mode 100644
index 0000000..9d07e10
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/function/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Pure java functional interfaces. Not specific to analytics.
+ */
+package org.apache.solr.analytics.util.function;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/package-info.java
index a5676f1..49602c7 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/package-info.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/package-info.java
@@ -16,9 +16,8 @@
  */
  
 /** 
- * Utilities used by analytics component
+ * Utility classes for the analytics component.
  */
 package org.apache.solr.analytics.util;
 
 
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/AbsoluteValueDoubleFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/AbsoluteValueDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/AbsoluteValueDoubleFunction.java
deleted file mode 100644
index f1e996c..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/AbsoluteValueDoubleFunction.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>AbsoluteValueDoubleFunction</code> takes the absolute value of the double value of the source it contains.
- */
-public class AbsoluteValueDoubleFunction extends SingleDoubleFunction {
-  public final static String NAME = AnalyticsParams.ABSOLUTE_VALUE;
-  
-  public AbsoluteValueDoubleFunction(ValueSource source) {
-    super(source);
-  }
-
-  protected String name() {
-    return NAME;
-  }
-
-  @Override
-  public String description() {
-    return name()+"("+source.description()+")";
-  }
-
-  protected double func(int doc, FunctionValues vals) throws IOException {
-    double d = vals.doubleVal(doc);
-    if (d<0) {
-      return d*-1;
-    } else {
-      return d;
-    }
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (getClass() != o.getClass()) return false;
-    AbsoluteValueDoubleFunction other = (AbsoluteValueDoubleFunction)o;
-    return this.source.equals(other.source);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/AddDoubleFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/AddDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/AddDoubleFunction.java
deleted file mode 100644
index c47a0a3..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/AddDoubleFunction.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>AddDoubleFunction</code> returns the sum of its components.
- */
-public class AddDoubleFunction extends MultiDoubleFunction {
-  public final static String NAME = AnalyticsParams.ADD;
-
-  public AddDoubleFunction(ValueSource[] sources) {
-    super(sources);
-  }
-
-  @Override
-  protected String name() {
-    return NAME;
-  }
-
-  @Override
-  protected double func(int doc, FunctionValues[] valsArr) throws IOException {
-    double sum = 0d;
-    for (FunctionValues val : valsArr) {
-      sum += val.doubleVal(doc);
-    }
-    return sum;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java
deleted file mode 100644
index 3ce608f..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDateSource.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-import java.time.Instant;
-import java.util.Date;
-import java.util.Map;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.docvalues.FloatDocValues;
-import org.apache.lucene.util.mutable.MutableValue;
-import org.apache.lucene.util.mutable.MutableValueDate;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>ConstDateSource</code> returns a constant date for all documents
- */
-public class ConstDateSource extends ConstDoubleSource {
-  public final static String NAME = AnalyticsParams.CONSTANT_DATE;
-
-  public ConstDateSource(Date constant) {
-    super(constant.getTime());
-  }
-
-  public ConstDateSource(Long constant) {
-    super(constant);
-  }
-
-  @SuppressWarnings("deprecation")
-  @Override
-  public String description() {
-    return name()+"(" + Instant.ofEpochMilli(getLong()) + ")";
-  }
-
-  protected String name() {
-    return NAME;
-  }
-  
-  @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    return new FloatDocValues(this) {
-      @Override
-      public float floatVal(int doc) {
-        return getFloat();
-      }
-      @Override
-      public int intVal(int doc) {
-        return getInt();
-      }
-      @Override
-      public long longVal(int doc) {
-        return getLong();
-      }
-      @Override
-      public double doubleVal(int doc) {
-        return getDouble();
-      }
-      @Override
-      public String toString(int doc) {
-        return description();
-      }
-      @Override
-      public Object objectVal(int doc) {
-        return new Date(longVal(doc));
-      }
-      @SuppressWarnings("deprecation")
-      @Override
-      public String strVal(int doc) {
-        return Instant.ofEpochMilli(longVal(doc)).toString();
-      }
-      @Override
-      public boolean boolVal(int doc) {
-        return getFloat() != 0.0f;
-      }
-
-      @Override
-      public ValueFiller getValueFiller() {
-        return new ValueFiller() {
-          private final MutableValueDate mval = new MutableValueDate();
-
-          @Override
-          public MutableValue getValue() {
-            return mval;
-          }
-
-          @Override
-          public void fillValue(int doc) {
-            mval.value = longVal(doc);
-            mval.exists = true;
-          }
-        };
-      }
-    };
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDoubleSource.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDoubleSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDoubleSource.java
deleted file mode 100644
index e0ebad6..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstDoubleSource.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
-import org.apache.lucene.queries.function.valuesource.ConstNumberSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>ConstDoubleSource</code> returns a constant double for all documents
- */
-public class ConstDoubleSource extends ConstNumberSource {
-  public final static String NAME = AnalyticsParams.CONSTANT_NUMBER;
-  final double constant;
-
-  public ConstDoubleSource(double constant) {
-    this.constant = constant;
-  }
-
-  @Override
-  public String description() {
-    return name()+"(" + getFloat() + ")";
-  }
-
-  protected String name() {
-    return NAME;
-  }
-
-  @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    return new DoubleDocValues(this) {
-      @Override
-      public double doubleVal(int doc) {
-        return constant;
-      }
-      @Override
-      public boolean exists(int doc) {
-        return true;
-      }
-    };
-  }
-
-  @Override
-  public int hashCode() {
-    return (int)Double.doubleToLongBits(constant) * 31;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (!(o instanceof ConstDoubleSource)) return false;
-    ConstDoubleSource other = (ConstDoubleSource)o;
-    return  this.constant == other.constant;
-  }
-
-  @Override
-  public int getInt() {
-    return (int)constant;
-  }
-
-  @Override
-  public long getLong() {
-    return (long)constant;
-  }
-
-  @Override
-  public float getFloat() {
-    return (float)constant;
-  }
-
-  @Override
-  public double getDouble() {
-    return constant;
-  }
-
-  @Override
-  public Number getNumber() {
-    return new Double(constant);
-  }
-
-  @Override
-  public boolean getBool() {
-    return constant != 0.0f;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstStringSource.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstStringSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstStringSource.java
deleted file mode 100644
index 52bdf52..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ConstStringSource.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import org.apache.lucene.queries.function.valuesource.LiteralValueSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>ConstStringSource</code> returns a constant string for all documents
- */
-public class ConstStringSource extends LiteralValueSource {
-  public final static String NAME = AnalyticsParams.CONSTANT_STRING;
-
-  public ConstStringSource(String string) {
-    super(string);
-  }
-
-  @Override
-  public String description() {
-    return name()+"(" + string + ")";
-  }
-
-  protected String name() {
-    return NAME;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) return true;
-    if (!(o instanceof ConstStringSource)) return false;
-    ConstStringSource that = (ConstStringSource) o;
-
-    return getValue().equals(that.getValue());
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java
deleted file mode 100644
index 803d8e0..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateFieldSource.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-import java.time.Instant;
-import java.util.Date;
-import java.util.Map;
-
-import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.NumericDocValues;
-import org.apache.solr.legacy.LegacyNumericUtils;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.docvalues.LongDocValues;
-import org.apache.lucene.queries.function.valuesource.LongFieldSource;
-import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.mutable.MutableValue;
-import org.apache.lucene.util.mutable.MutableValueDate;
-
-/**
- * Extends {@link LongFieldSource} to have a field source that takes in 
- * and returns {@link Date} values while working with long values internally.
- */
-public class DateFieldSource extends LongFieldSource {
-
-  public DateFieldSource(String field) {
-    super(field);
-  }
-
-  public long externalToLong(String extVal) {
-    return LegacyNumericUtils.prefixCodedToLong(new BytesRef(extVal));
-  }
-
-  public Object longToObject(long val) {
-    return new Date(val);
-  }
-
-  @SuppressWarnings("deprecation")
-  public String longToString(long val) {
-    return Instant.ofEpochMilli(val).toString();
-  }
-
-  @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    final NumericDocValues arr = DocValues.getNumeric(readerContext.reader(), field);
-    return new LongDocValues(this) {
-
-      private long getDocValue(int doc) throws IOException {
-        int arrDocID = arr.docID();
-        if (arrDocID < doc) {
-          arrDocID = arr.advance(doc);
-        }
-        if (arrDocID == doc) {
-          return arr.longValue();
-        } else {
-          return 0;
-        }
-      }
-      
-      @Override
-      public long longVal(int doc) throws IOException {
-        return getDocValue(doc);
-      }
-
-      @Override
-      public boolean exists(int doc) throws IOException {
-        getDocValue(doc);
-        return arr.docID() == doc;
-      }
-
-      @Override
-      public Object objectVal(int doc) throws IOException {
-        return exists(doc) ? longToObject(getDocValue(doc)) : null;
-      }
-
-      @Override
-      public String strVal(int doc) throws IOException {
-        return exists(doc) ? longToString(getDocValue(doc)) : null;
-      }
-
-      @Override
-      public ValueFiller getValueFiller() {
-        return new ValueFiller() {
-          private final MutableValueDate mval = new MutableValueDate();
-
-          @Override
-          public MutableValue getValue() {
-            return mval;
-          }
-
-          @Override
-          public void fillValue(int doc) throws IOException {
-            mval.value = getDocValue(doc);
-            mval.exists = exists(doc);
-          }
-        };
-      }
-
-    };
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (o.getClass() != this.getClass()) return false;
-    DateFieldSource other = (DateFieldSource) o;
-    return field.equals(other.field);
-  }
-
-  @Override
-  public int hashCode() {
-    int h = this.getClass().hashCode();
-    h += super.hashCode();
-    return h;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateMathFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateMathFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateMathFunction.java
deleted file mode 100644
index 77b172a..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DateMathFunction.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-import java.text.ParseException;
-import java.util.Date;
-
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.queries.function.valuesource.BytesRefFieldSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.util.DateMathParser;
-
-/**
- * <code>DateMathFunction</code> returns a start date modified by a list of DateMath operations.
- */
-public class DateMathFunction extends MultiDateFunction {
-  public final static String NAME = AnalyticsParams.DATE_MATH;
-  final private DateMathParser parser;
-  
-  /**
-   * @param sources A list of ValueSource objects. The first element in the list
-   * should be a {@link DateFieldSource} or {@link ConstDateSource} object which
-   * represents the starting date. The rest of the field should be {@link BytesRefFieldSource}
-   * or {@link ConstStringSource} objects which contain the DateMath operations to perform on 
-   * the start date.
-   */
-  public DateMathFunction(ValueSource[] sources) {
-    super(sources);
-    parser = new DateMathParser();
-  }
-
-  @Override
-  protected String name() {
-    return NAME;
-  }
-
-  @Override
-  protected long func(int doc, FunctionValues[] valsArr) throws IOException {
-    long time = 0;
-    Date date = (Date)valsArr[0].objectVal(doc);
-    try {
-      parser.setNow(date);
-      for (int count = 1; count < valsArr.length; count++) {
-          date = parser.parseMath(valsArr[count].strVal(doc));
-        parser.setNow(date);
-      }
-      time = parser.getNow().getTime();
-    } catch (ParseException e) {
-      e.printStackTrace();
-      time = date.getTime();
-    }
-    return time;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DivDoubleFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DivDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DivDoubleFunction.java
deleted file mode 100644
index 25c4c96..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DivDoubleFunction.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>DivDoubleFunction</code> returns the quotient of 'a' and 'b'.
- */
-public class DivDoubleFunction extends DualDoubleFunction {
-  public final static String NAME = AnalyticsParams.DIVIDE;
-
-  /**
-    * @param   a  the numerator.
-    * @param   b  the denominator.
-    */
-  public DivDoubleFunction(ValueSource a, ValueSource b) {
-    super(a, b);
-  }
-
-  protected String name() {
-    return NAME;
-  }
-
-  @Override
-  protected double func(int doc, FunctionValues aVals, FunctionValues bVals) throws IOException {
-    return aVals.doubleVal(doc)/bVals.doubleVal(doc);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DualDoubleFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DualDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DualDoubleFunction.java
deleted file mode 100644
index 97b8af7..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/DualDoubleFunction.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
-import org.apache.lucene.search.IndexSearcher;
-
-/**
- * Abstract {@link ValueSource} implementation which wraps two ValueSources
- * and applies an extendible double function to their values.
- **/
-public abstract class DualDoubleFunction extends ValueSource {
-  protected final ValueSource a;
-  protected final ValueSource b;
-
-  public DualDoubleFunction(ValueSource a, ValueSource b) {
-    this.a = a;
-    this.b = b;
-  }
-
-  protected abstract String name();
-  protected abstract double func(int doc, FunctionValues aVals, FunctionValues bVals) throws IOException;
-
-  @Override
-  public String description() {
-    return name() + "(" + a.description() + "," + b.description() + ")";
-  }
-
-  @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    final FunctionValues aVals =  a.getValues(context, readerContext);
-    final FunctionValues bVals =  b.getValues(context, readerContext);
-    return new DoubleDocValues(this) {
-      @Override
-      public double doubleVal(int doc) throws IOException {
-        return func(doc, aVals, bVals);
-      }
-      
-      @Override
-      public boolean exists(int doc) throws IOException {
-        return aVals.exists(doc) & bVals.exists(doc);
-      }
-
-      @Override
-      public String toString(int doc) throws IOException {
-        return name() + '(' + aVals.toString(doc) + ',' + bVals.toString(doc) + ')';
-      }
-    };
-  }
-
-  @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
-    a.createWeight(context,searcher);
-    b.createWeight(context,searcher);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (getClass() != o.getClass()) return false;
-    DualDoubleFunction other = (DualDoubleFunction)o;
-    return this.a.equals(other.a)
-        && this.b.equals(other.b);
-  }
-
-  @Override
-  public int hashCode() {
-    int h = a.hashCode();
-    h ^= (h << 13) | (h >>> 20);
-    h += b.hashCode();
-    h ^= (h << 23) | (h >>> 10);
-    h += name().hashCode();
-    return h;
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java
deleted file mode 100644
index 3f374dc..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/FilterFieldSource.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-import java.util.Date;
-import java.util.Map;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.util.mutable.MutableValue;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>DefaultIsMissingFieldSource</code> wraps a field source to return missing values 
- * if the value is equal to the default value.
- */
-public class FilterFieldSource extends ValueSource {
-  public final static String NAME = AnalyticsParams.FILTER;
-  public final Object missValue;
-  protected final ValueSource source;
-  
-  public FilterFieldSource(ValueSource source, Object missValue) {
-    this.source = source;
-    this.missValue = missValue;
-  }
-
-  protected String name() {
-    return NAME;
-  }
-
-  @SuppressWarnings("deprecation")
-  @Override
-  public String description() {
-    if (missValue.getClass().equals(Date.class)) {
-      return name()+"("+source.description()+","+ ((Date)missValue).toInstant() +")";
-    } else {
-      return name()+"("+source.description()+","+missValue.toString()+")";
-    }
-  }
-
-  @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    final FunctionValues vals =  source.getValues(context, readerContext);
-    return new FunctionValues() {
-
-      @Override
-      public byte byteVal(int doc) throws IOException {
-        return vals.byteVal(doc);
-      }
-
-      @Override
-      public short shortVal(int doc) throws IOException {
-        return vals.shortVal(doc);
-      }
-
-      @Override
-      public float floatVal(int doc) throws IOException {
-        return vals.floatVal(doc);
-      }
-
-      @Override
-      public int intVal(int doc) throws IOException {
-        return vals.intVal(doc);
-      }
-
-      @Override
-      public long longVal(int doc) throws IOException {
-        return vals.longVal(doc);
-      }
-
-      @Override
-      public double doubleVal(int doc) throws IOException {
-        return vals.doubleVal(doc);
-      }
-
-      @Override
-      public String strVal(int doc) throws IOException {
-        return vals.strVal(doc);
-      }
-
-      @Override
-      public Object objectVal(int doc) throws IOException {
-        return exists(doc)? vals.objectVal(doc) : null;
-      }
-
-      @Override
-      public boolean exists(int doc) throws IOException {
-        Object other = vals.objectVal(doc);
-        return other!=null&&!missValue.equals(other);
-      }
-
-      @Override
-      public String toString(int doc) throws IOException {
-        return NAME + '(' + vals.toString(doc) + ')';
-      }
-
-      @Override
-      public ValueFiller getValueFiller() {
-        return new ValueFiller() {
-          private final ValueFiller delegateFiller = vals.getValueFiller();
-          private final MutableValue mval = delegateFiller.getValue();
-
-          @Override
-          public MutableValue getValue() {
-            return mval;
-          }
-
-          @Override
-          public void fillValue(int doc) throws IOException {
-            delegateFiller.fillValue(doc);
-            mval.exists = exists(doc);
-          }
-        };
-      }
-    };
-  }
-  
-  public ValueSource getRootSource() {
-    if (source instanceof FilterFieldSource) {
-      return ((FilterFieldSource)source).getRootSource();
-    } else {
-      return source;
-    }
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (getClass() != o.getClass()) return false;
-    FilterFieldSource other = (FilterFieldSource)o;
-    return this.source.equals(other.source) && this.missValue.equals(other.missValue);
-  }
-
-  @Override
-  public int hashCode() {
-    return source.hashCode()+name().hashCode();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/LogDoubleFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/LogDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/LogDoubleFunction.java
deleted file mode 100644
index 41a6b67..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/LogDoubleFunction.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>LogDoubleFunction</code> returns the log of a double value with a given base.
- */
-public class LogDoubleFunction extends DualDoubleFunction {
-  public final static String NAME = AnalyticsParams.LOG;
-  
-  public LogDoubleFunction(ValueSource a, ValueSource b) {
-    super(a,b);
-  }
-
-  protected String name() {
-    return NAME;
-  }
-
-  @Override
-  protected double func(int doc, FunctionValues aVals, FunctionValues bVals) throws IOException {
-    return Math.log(aVals.doubleVal(doc))/Math.log(bVals.doubleVal(doc));
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDateFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDateFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDateFunction.java
deleted file mode 100644
index beeaaa7..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDateFunction.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Map;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.queries.function.docvalues.LongDocValues;
-import org.apache.lucene.util.mutable.MutableValue;
-import org.apache.lucene.util.mutable.MutableValueDate;
-
-/**
- * Abstract {@link ValueSource} implementation which wraps multiple ValueSources
- * and applies an extendible date function to their values.
- **/
-public abstract class MultiDateFunction extends ValueSource {
-  protected final ValueSource[] sources;
-  
-  public MultiDateFunction(ValueSource[] sources) {
-    this.sources = sources;
-  }
-
-  abstract protected String name();
-  abstract protected long func(int doc, FunctionValues[] valsArr) throws IOException;
-
-  @Override
-  public String description() {
-    StringBuilder sb = new StringBuilder();
-    sb.append(name()).append('(');
-    boolean firstTime=true;
-    for (ValueSource source : sources) {
-      if (firstTime) {
-        firstTime=false;
-      } else {
-        sb.append(',');
-      }
-      sb.append(source);
-    }
-    sb.append(')');
-    return sb.toString();
-  }
-
-  @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    final FunctionValues[] valsArr = new FunctionValues[sources.length];
-    for (int i=0; i<sources.length; i++) {
-      valsArr[i] = sources[i].getValues(context, readerContext);
-    }
-
-    return new LongDocValues(this) {
-      @Override
-      public long longVal(int doc) throws IOException {
-        return func(doc, valsArr);
-      }
-      
-      @Override
-      public boolean exists(int doc) throws IOException {
-        boolean exists = true;
-        for (FunctionValues val : valsArr) {
-          exists = exists & val.exists(doc);
-        }
-        return exists;
-      }
-      
-      @Override
-      public String toString(int doc) throws IOException {
-        StringBuilder sb = new StringBuilder();
-        sb.append(name()).append('(');
-        boolean firstTime=true;
-        for (FunctionValues vals : valsArr) {
-          if (firstTime) {
-            firstTime=false;
-          } else {
-            sb.append(',');
-          }
-          sb.append(vals.toString(doc));
-        }
-        sb.append(')');
-        return sb.toString();
-      }
-
-      @Override
-      public ValueFiller getValueFiller() {
-        return new ValueFiller() {
-          private final MutableValueDate mval = new MutableValueDate();
-
-          @Override
-          public MutableValue getValue() {
-            return mval;
-          }
-
-          @Override
-          public void fillValue(int doc) throws IOException {
-            mval.value = longVal(doc);
-            mval.exists = exists(doc);
-          }
-        };
-      }
-    };
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (getClass() != o.getClass()) return false;
-    MultiDateFunction other = (MultiDateFunction)o;
-    return this.name().equals(other.name())
-            && Arrays.equals(this.sources, other.sources);
-  }
-
-  @Override
-  public int hashCode() {
-    return Arrays.hashCode(sources) + name().hashCode();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDoubleFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDoubleFunction.java
deleted file mode 100644
index 09956f2..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiDoubleFunction.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Map;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
-import org.apache.lucene.search.IndexSearcher;
-
-/**
- * Abstract {@link ValueSource} implementation which wraps multiple ValueSources
- * and applies an extendible double function to their values.
- **/
-public abstract class MultiDoubleFunction extends ValueSource {
-  protected final ValueSource[] sources;
-
-  public MultiDoubleFunction(ValueSource[] sources) {
-    this.sources = sources;
-  }
-
-  abstract protected String name();
-  abstract protected double func(int doc, FunctionValues[] valsArr) throws IOException;
-
-  @Override
-  public String description() {
-    StringBuilder sb = new StringBuilder();
-    sb.append(name()).append('(');
-    boolean firstTime=true;
-    for (ValueSource source : sources) {
-      if (firstTime) {
-        firstTime=false;
-      } else {
-        sb.append(',');
-      }
-      sb.append(source);
-    }
-    sb.append(')');
-    return sb.toString();
-  }
-
-  @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    final FunctionValues[] valsArr = new FunctionValues[sources.length];
-    for (int i=0; i<sources.length; i++) {
-      valsArr[i] = sources[i].getValues(context, readerContext);
-    }
-
-    return new DoubleDocValues(this) {
-      @Override
-      public double doubleVal(int doc) throws IOException {
-        return func(doc, valsArr);
-      }
-      
-      @Override
-      public boolean exists(int doc) throws IOException {
-        boolean exists = true;
-        for (FunctionValues val : valsArr) {
-          exists = exists & val.exists(doc);
-        }
-        return exists;
-      }
-       
-      @Override
-      public String toString(int doc) throws IOException {
-        StringBuilder sb = new StringBuilder();
-        sb.append(name()).append('(');
-        boolean firstTime=true;
-        for (FunctionValues vals : valsArr) {
-          if (firstTime) {
-            firstTime=false;
-          } else {
-            sb.append(',');
-          }
-          sb.append(vals.toString(doc));
-        }
-        sb.append(')');
-        return sb.toString();
-      }
-    };
-  }
-
-  @Override
-  public void createWeight(Map context, IndexSearcher searcher) throws IOException {
-    for (ValueSource source : sources)
-      source.createWeight(context, searcher);
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (getClass() != o.getClass()) return false;
-    MultiDoubleFunction other = (MultiDoubleFunction)o;
-    return this.name().equals(other.name())
-            && Arrays.equals(this.sources, other.sources);
-  }
-
-  @Override
-  public int hashCode() {
-    return Arrays.hashCode(sources) + name().hashCode();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiplyDoubleFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiplyDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiplyDoubleFunction.java
deleted file mode 100644
index 83f26f0..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/MultiplyDoubleFunction.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>MultiplyDoubleFunction</code> returns the product of its components.
- */
-public class MultiplyDoubleFunction extends MultiDoubleFunction {
-  public final static String NAME = AnalyticsParams.MULTIPLY;
-
-  public MultiplyDoubleFunction(ValueSource[] sources) {
-    super(sources);
-  }
-
-  @Override
-  protected String name() {
-    return NAME;
-  }
-
-  @Override
-  protected double func(int doc, FunctionValues[] valsArr) throws IOException {
-    double product = 1d;
-    for (FunctionValues val : valsArr) {
-      product *= val.doubleVal(doc);
-    }
-    return product;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/NegateDoubleFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/NegateDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/NegateDoubleFunction.java
deleted file mode 100644
index 9c8445d..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/NegateDoubleFunction.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>NegateDoubleFunction</code> negates the double value of the source it contains.
- */
-public class NegateDoubleFunction extends SingleDoubleFunction {
-  public final static String NAME = AnalyticsParams.NEGATE;
-  
-  public NegateDoubleFunction(ValueSource source) {
-    super(source);
-  }
-
-  protected String name() {
-    return NAME;
-  }
-
-  @Override
-  public String description() {
-    return name()+"("+source.description()+")";
-  }
-
-  protected double func(int doc, FunctionValues vals) throws IOException {
-    return vals.doubleVal(doc)*-1;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (getClass() != o.getClass()) return false;
-    NegateDoubleFunction other = (NegateDoubleFunction)o;
-    return this.source.equals(other.source);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/PowDoubleFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/PowDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/PowDoubleFunction.java
deleted file mode 100644
index 043313b..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/PowDoubleFunction.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>PowDoubleFunction</code> returns 'a' raised to the power of 'b'.
- */
-public class PowDoubleFunction extends DualDoubleFunction {
-  public final static String NAME = AnalyticsParams.POWER;
-
-  /**
-    * @param   a  the base.
-    * @param   b  the exponent.
-    */
-  public PowDoubleFunction(ValueSource a, ValueSource b) {
-    super(a, b);
-  }
-
-  @Override
-  protected String name() {
-    return NAME;
-  }
-
-  @Override
-  protected double func(int doc, FunctionValues aVals, FunctionValues bVals) throws IOException {
-    return Math.pow(aVals.doubleVal(doc), bVals.doubleVal(doc));
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ReverseStringFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ReverseStringFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ReverseStringFunction.java
deleted file mode 100644
index 4fa0f99..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/ReverseStringFunction.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.solr.analytics.util.AnalyticsParams;
-
-/**
- * <code>ReverseStringFunction</code> reverses the string value of the source it contains.
- */
-public class ReverseStringFunction extends SingleStringFunction {
-  public final static String NAME = AnalyticsParams.REVERSE;
-  
-  public ReverseStringFunction(ValueSource source) {
-    super(source);
-  }
-
-  protected String name() {
-    return NAME;
-  }
-
-  protected CharSequence func(int doc, FunctionValues vals) throws IOException {
-    String val = vals.strVal(doc);
-    return val != null ? StringUtils.reverse(val) : null;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleDoubleFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleDoubleFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleDoubleFunction.java
deleted file mode 100644
index 04f79ed..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleDoubleFunction.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
-
-/**
- * Abstract {@link ValueSource} implementation which wraps one ValueSource
- * and applies an extendible double function to its values.
- */
-public abstract class SingleDoubleFunction extends ValueSource {
-  protected final ValueSource source;
-  
-  public SingleDoubleFunction(ValueSource source) {
-    this.source = source;
-  }
-
-  @Override
-  public String description() {
-    return name()+"("+source.description()+")";
-  }
-
-  abstract String name();
-  abstract double func(int doc, FunctionValues vals) throws IOException;
-
-  @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    final FunctionValues vals =  source.getValues(context, readerContext);
-    return new DoubleDocValues(this) {
-      @Override
-      public double doubleVal(int doc) throws IOException {
-        return func(doc, vals);
-      }
-      
-      @Override
-      public boolean exists(int doc) throws IOException {
-        return vals.exists(doc);
-      }
-
-      @Override
-      public String toString(int doc) throws IOException {
-        return name() + '(' + vals.toString(doc) + ')';
-      }
-    };
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (getClass() != o.getClass()) return false;
-    SingleDoubleFunction other = (SingleDoubleFunction)o;
-    return this.source.equals(other.source);
-  }
-
-  @Override
-  public int hashCode() {
-    return source.hashCode()+name().hashCode();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleStringFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleStringFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleStringFunction.java
deleted file mode 100644
index b3357f9..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/SingleStringFunction.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.util.valuesource;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.queries.function.FunctionValues;
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.queries.function.docvalues.StrDocValues;
-import org.apache.lucene.util.BytesRefBuilder;
-import org.apache.lucene.util.mutable.MutableValue;
-import org.apache.lucene.util.mutable.MutableValueStr;
-
-/**
- * Abstract {@link ValueSource} implementation which wraps one ValueSource
- * and applies an extendible string function to its values.
- */
-public abstract class SingleStringFunction extends ValueSource {
-  protected final ValueSource source;
-  
-  public SingleStringFunction(ValueSource source) {
-    this.source = source;
-  }
-
-  @Override
-  public String description() {
-    return name()+"("+source.description()+")";
-  }
-
-  abstract String name();
-  abstract CharSequence func(int doc, FunctionValues vals) throws IOException;
-
-  @Override
-  public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
-    final FunctionValues vals =  source.getValues(context, readerContext);
-    return new StrDocValues(this) {
-      @Override
-      public String strVal(int doc) throws IOException {
-        CharSequence cs = func(doc, vals);
-        return cs != null ? cs.toString() : null;
-      }
-      
-      @Override
-      public boolean bytesVal(int doc, BytesRefBuilder bytes) throws IOException {
-        CharSequence cs = func(doc, vals);
-        if( cs != null ){
-          bytes.copyChars(func(doc,vals));
-          return true;
-        } else {
-          bytes.clear();
-          return false;
-        }
-      }
-
-      @Override
-      public Object objectVal(int doc) throws IOException {
-        return strVal(doc);
-      }
-      
-      @Override
-      public boolean exists(int doc) throws IOException {
-        return vals.exists(doc);
-      }
-
-      @Override
-      public String toString(int doc) throws IOException {
-        return name() + '(' + strVal(doc) + ')';
-      }
-
-      @Override
-      public ValueFiller getValueFiller() {
-        return new ValueFiller() {
-          private final MutableValueStr mval = new MutableValueStr();
-
-          @Override
-          public MutableValue getValue() {
-            return mval;
-          }
-
-          @Override
-          public void fillValue(int doc) throws IOException {
-            mval.exists = bytesVal(doc, mval.value);
-          }
-        };
-      }
-    };
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (getClass() != o.getClass()) return false;
-    SingleStringFunction other = (SingleStringFunction)o;
-    return this.source.equals(other.source);
-  }
-
-  @Override
-  public int hashCode() {
-    return source.hashCode()+name().hashCode();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/package-info.java
deleted file mode 100644
index 72a23d2..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/util/valuesource/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-/** 
- * ValueSource function/sources used by analytics component
- */
-package org.apache.solr.analytics.util.valuesource;
-
-
-


[28/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-6807: fix _stateVer_ param check to not depend on handleSelect setting

Posted by ab...@apache.org.
SOLR-6807: fix _stateVer_ param check to not depend on handleSelect setting


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/811621c6
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/811621c6
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/811621c6

Branch: refs/heads/jira/solr-10879
Commit: 811621c6ea63318fb593a08970e8652b2501af25
Parents: d0c86d0
Author: David Smiley <ds...@apache.org>
Authored: Wed Jun 28 23:44:03 2017 -0400
Committer: David Smiley <ds...@apache.org>
Committed: Wed Jun 28 23:44:03 2017 -0400

----------------------------------------------------------------------
 solr/CHANGES.txt                                       |  3 +++
 .../src/java/org/apache/solr/servlet/HttpSolrCall.java | 13 ++++++-------
 2 files changed, 9 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/811621c6/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 214b82e..39fc14c 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -229,6 +229,9 @@ Bug Fixes
 * SOLR-10506: Fix memory leak (upon collection reload or ZooKeeper session expiry) in ZkIndexSchemaReader.
   (Torsten Bøgh Köster, Christine Poerschke, Jörg Rathlev, Mike Drob)
 
+* SOLR-6807: CloudSolrClient's ZK state version check with the server was ignored when handleSelect=false
+  (David Smiley)
+
 Optimizations
 ----------------------
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/811621c6/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
index 5542d4c..a548c05 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -327,6 +327,8 @@ public class HttpSolrCall {
           solrReq = parser.parse(core, path, req);
         }
 
+        invalidStates = checkStateVersionsAreValid(solrReq.getParams().get(CloudSolrClient.STATE_VERSION));
+
         if (usingAliases) {
           processAliases(aliases, collectionsList);
         }
@@ -388,8 +390,6 @@ public class HttpSolrCall {
 
   /**
    * Extract handler from the URL path if not set.
-   * This returns true if the action is set.
-   * 
    */
   protected void extractHandlerFromURLPath(SolrRequestParsers parser) throws Exception {
     if (handler == null && path.length() > 1) { // don't match "" or "/" as valid path
@@ -411,14 +411,12 @@ public class HttpSolrCall {
             return;
           }
         }
-
       }
-      // no handler yet but allowed to handle select; let's check
 
+      // no handler yet but <requestDispatcher> allows us to handle /select with a 'qt' param
       if (handler == null && parser.isHandleSelect()) {
         if ("/select".equals(path) || "/select/".equals(path)) {
           solrReq = parser.parse(core, path, req);
-          invalidStates = checkStateIsValid(solrReq.getParams().get(CloudSolrClient.STATE_VERSION));
           String qt = solrReq.getParams().get(CommonParams.QT);
           handler = core.getRequestHandler(qt);
           if (handler == null) {
@@ -438,7 +436,7 @@ public class HttpSolrCall {
     if (core == null && idx > 0) {
       coreUrl = getRemotCoreUrl(corename, origCorename);
       // don't proxy for internal update requests
-      invalidStates = checkStateIsValid(queryParams.get(CloudSolrClient.STATE_VERSION));
+      invalidStates = checkStateVersionsAreValid(queryParams.get(CloudSolrClient.STATE_VERSION));
       if (coreUrl != null
           && queryParams
           .get(DistributingUpdateProcessorFactory.DISTRIB_UPDATE_PARAM) == null) {
@@ -813,7 +811,8 @@ public class HttpSolrCall {
     }
   }
 
-  private Map<String, Integer> checkStateIsValid(String stateVer) {
+  /** Returns null if the state ({@link CloudSolrClient#STATE_VERSION}) is good; otherwise returns state problems. */
+  private Map<String, Integer> checkStateVersionsAreValid(String stateVer) {
     Map<String, Integer> result = null;
     String[] pairs;
     if (stateVer != null && !stateVer.isEmpty() && cores.isZooKeeperAware()) {


[31/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10272: Adding user _default configset to test-files, fixing solr & solr.cmd script bugs

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/managed-schema
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/managed-schema b/solr/core/src/test-files/solr/configsets/_default/conf/managed-schema
new file mode 100644
index 0000000..a88300a
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/managed-schema
@@ -0,0 +1,1076 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--  
+ This is the Solr schema file. This file should be named "schema.xml" and
+ should be in the conf directory under the solr home
+ (i.e. ./solr/conf/schema.xml by default) 
+ or located where the classloader for the Solr webapp can find it.
+
+ This example schema is the recommended starting point for users.
+ It should be kept correct and concise, usable out-of-the-box.
+
+ For more information, on how to customize this file, please see
+ http://wiki.apache.org/solr/SchemaXml
+
+ PERFORMANCE NOTE: this schema includes many optional features and should not
+ be used for benchmarking.  To improve performance one could
+  - set stored="false" for all fields possible (esp large fields) when you
+    only need to search on the field but don't need to return the original
+    value.
+  - set indexed="false" if you don't need to search on the field, but only
+    return the field as a result of searching on other indexed fields.
+  - remove all unneeded copyField statements
+  - for best index size and searching performance, set "index" to false
+    for all general text fields, use copyField to copy them to the
+    catchall "text" field, and use that for searching.
+  - For maximum indexing performance, use the ConcurrentUpdateSolrServer
+    java client.
+  - Remember to run the JVM in server mode, and use a higher logging level
+    that avoids logging every request
+-->
+
+<schema name="default-config" version="1.6">
+    <!-- attribute "name" is the name of this schema and is only used for display purposes.
+       version="x.y" is Solr's version number for the schema syntax and 
+       semantics.  It should not normally be changed by applications.
+
+       1.0: multiValued attribute did not exist, all fields are multiValued 
+            by nature
+       1.1: multiValued attribute introduced, false by default 
+       1.2: omitTermFreqAndPositions attribute introduced, true by default 
+            except for text fields.
+       1.3: removed optional field compress feature
+       1.4: autoGeneratePhraseQueries attribute introduced to drive QueryParser
+            behavior when a single string produces multiple tokens.  Defaults 
+            to off for version >= 1.4
+       1.5: omitNorms defaults to true for primitive field types 
+            (int, float, boolean, string...)
+       1.6: useDocValuesAsStored defaults to true.
+    -->
+
+    <!-- Valid attributes for fields:
+     name: mandatory - the name for the field
+     type: mandatory - the name of a field type from the 
+       fieldTypes section
+     indexed: true if this field should be indexed (searchable or sortable)
+     stored: true if this field should be retrievable
+     docValues: true if this field should have doc values. Doc values are
+       useful (required, if you are using *Point fields) for faceting, 
+       grouping, sorting and function queries. Doc values will make the index 
+       faster to load, more NRT-friendly and more memory-efficient. 
+       They however come with some limitations: they are currently only 
+       supported by StrField, UUIDField, all Trie*Fields and *PointFields,
+       and depending on the field type, they might require the field to be
+       single-valued, be required or have a default value (check the
+       documentation of the field type you're interested in for more information)
+     multiValued: true if this field may contain multiple values per document
+     omitNorms: (expert) set to true to omit the norms associated with
+       this field (this disables length normalization and index-time
+       boosting for the field, and saves some memory).  Only full-text
+       fields or fields that need an index-time boost need norms.
+       Norms are omitted for primitive (non-analyzed) types by default.
+     termVectors: [false] set to true to store the term vector for a
+       given field.
+       When using MoreLikeThis, fields used for similarity should be
+       stored for best performance.
+     termPositions: Store position information with the term vector.  
+       This will increase storage costs.
+     termOffsets: Store offset information with the term vector. This 
+       will increase storage costs.
+     required: The field is required.  It will throw an error if the
+       value does not exist
+     default: a value that should be used if no value is specified
+       when adding a document.
+    -->
+
+    <!-- field names should consist of alphanumeric or underscore characters only and
+      not start with a digit.  This is not currently strictly enforced,
+      but other field names will not have first class support from all components
+      and back compatibility is not guaranteed.  Names with both leading and
+      trailing underscores (e.g. _version_) are reserved.
+    -->
+
+    <!-- In this _default configset, only three fields are pre-declared: 
+         id, _version_, and _text_.  All other fields will be type guessed and added via the
+         "add-unknown-fields-to-the-schema" update request processor chain declared 
+         in solrconfig.xml.
+         
+         Note that many dynamic fields are also defined - you can use them to specify a 
+         field's type via field naming conventions - see below.
+  
+         WARNING: The _text_ catch-all field will significantly increase your index size.
+         If you don't need it, consider removing it and the corresponding copyField directive.
+    -->
+    <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
+    <!-- doc values are enabled by default for primitive types such as long so we don't index the version field  -->
+    <field name="_version_" type="long" indexed="false" stored="false"/>
+    <field name="_root_" type="string" indexed="true" stored="false" docValues="false" />
+    <field name="_text_" type="text_general" indexed="true" stored="false" multiValued="true"/>
+
+    <!-- This can be enabled, in case the client does not know what fields may be searched. It isn't enabled by default
+         because it's very expensive to index everything twice. -->
+    <!-- <copyField source="*" dest="_text_"/> -->
+
+    <!-- Dynamic field definitions allow using convention over configuration
+       for fields via the specification of patterns to match field names. 
+       EXAMPLE:  name="*_i" will match any field ending in _i (like myid_i, z_i)
+       RESTRICTION: the glob-like pattern in the name attribute must have
+       a "*" only at the start or the end.  -->
+   
+    <dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>
+    <dynamicField name="*_is" type="ints"    indexed="true"  stored="true"/>
+    <dynamicField name="*_s"  type="string"  indexed="true"  stored="true" />
+    <dynamicField name="*_s_ns"  type="string"  indexed="true"  stored="false" />
+    <dynamicField name="*_ss" type="strings"  indexed="true"  stored="true"/>
+    <dynamicField name="*_l"  type="long"   indexed="true"  stored="true"/>
+    <dynamicField name="*_l_ns"  type="long"   indexed="true"  stored="false"/>
+    <dynamicField name="*_ls" type="longs"   indexed="true"  stored="true"/>
+    <dynamicField name="*_t"   type="text_general" indexed="true" stored="true"/>
+    <dynamicField name="*_txt" type="text_general" indexed="true" stored="true"/>
+    <dynamicField name="*_b"  type="boolean" indexed="true" stored="true"/>
+    <dynamicField name="*_bs" type="booleans" indexed="true" stored="true"/>
+    <dynamicField name="*_f"  type="float"  indexed="true"  stored="true"/>
+    <dynamicField name="*_fs" type="floats"  indexed="true"  stored="true"/>
+    <dynamicField name="*_d"  type="double" indexed="true"  stored="true"/>
+    <dynamicField name="*_ds" type="doubles" indexed="true"  stored="true"/>
+
+    <dynamicField name="*_dt"  type="date"    indexed="true"  stored="true"/>
+    <dynamicField name="*_dts" type="date"    indexed="true"  stored="true" multiValued="true"/>
+    <dynamicField name="*_p"  type="location" indexed="true" stored="true"/>
+    <dynamicField name="*_srpt"  type="location_rpt" indexed="true" stored="true"/>
+    
+    <!-- KD-tree (point) numerics -->
+    <dynamicField name="*_pi" type="pint"    indexed="true"  stored="true"/>
+    <dynamicField name="*_pis" type="pints"    indexed="true"  stored="true"/>
+    <dynamicField name="*_pl" type="plong"   indexed="true"  stored="true"/>
+    <dynamicField name="*_pls" type="plongs"   indexed="true"  stored="true"/>
+    <dynamicField name="*_pf" type="pfloat"  indexed="true"  stored="true"/>
+    <dynamicField name="*_pfs" type="pfloats"  indexed="true"  stored="true"/>
+    <dynamicField name="*_pd" type="pdouble" indexed="true"  stored="true"/>
+    <dynamicField name="*_pds" type="pdoubles" indexed="true"  stored="true"/>
+    <dynamicField name="*_pdt" type="pdate"  indexed="true"  stored="true"/>
+    <dynamicField name="*_pdts" type="pdates"  indexed="true"  stored="true"/>
+
+    <!-- some trie-coded dynamic fields -->
+    <dynamicField name="*_ti" type="tint"    indexed="true"  stored="true"/>
+    <dynamicField name="*_tis" type="tints"    indexed="true"  stored="true"/>
+    <dynamicField name="*_tl" type="tlong"   indexed="true"  stored="true"/>
+    <dynamicField name="*_tls" type="tlongs"   indexed="true"  stored="true"/>
+    <dynamicField name="*_tf" type="tfloat"  indexed="true"  stored="true"/>
+    <dynamicField name="*_tfs" type="tfloats"  indexed="true"  stored="true"/>
+    <dynamicField name="*_td" type="tdouble" indexed="true"  stored="true"/>
+    <dynamicField name="*_tds" type="tdoubles" indexed="true"  stored="true"/>
+    <dynamicField name="*_tdt" type="tdate"  indexed="true"  stored="true"/>
+    <dynamicField name="*_tdts" type="tdates"  indexed="true"  stored="true"/>
+
+    <!-- payloaded dynamic fields -->
+    <dynamicField name="*_dpf" type="delimited_payloads_float" indexed="true"  stored="true"/>
+    <dynamicField name="*_dpi" type="delimited_payloads_int" indexed="true"  stored="true"/>
+    <dynamicField name="*_dps" type="delimited_payloads_string" indexed="true"  stored="true"/>
+
+    <dynamicField name="*_c"   type="currency" indexed="true"  stored="true"/>
+
+    <dynamicField name="ignored_*" type="ignored" multiValued="true"/>
+    <dynamicField name="attr_*" type="text_general" indexed="true" stored="true" multiValued="true"/>
+
+    <dynamicField name="random_*" type="random" />
+
+    <!-- uncomment the following to ignore any fields that don't already match an existing 
+        field name or dynamic field, rather than reporting them as an error. 
+        alternately, change the type="ignored" to some other type e.g. "text" if you want 
+        unknown fields indexed and/or stored by default 
+        
+        NB: use of "*" dynamic fields will disable field type guessing and adding
+        unknown fields to the schema. --> 
+    <!--dynamicField name="*" type="ignored" multiValued="true" /-->
+
+    <!-- Field to use to determine and enforce document uniqueness.
+      Unless this field is marked with required="false", it will be a required field
+    -->
+    <uniqueKey>id</uniqueKey>
+
+    <!-- copyField commands copy one field to another at the time a document
+       is added to the index.  It's used either to index the same field differently,
+       or to add multiple fields to the same field for easier/faster searching.
+
+    <copyField source="sourceFieldName" dest="destinationFieldName"/>
+    -->
+
+    <!-- field type definitions. The "name" attribute is
+       just a label to be used by field definitions.  The "class"
+       attribute and any other attributes determine the real
+       behavior of the fieldType.
+         Class names starting with "solr" refer to java classes in a
+       standard package such as org.apache.solr.analysis
+    -->
+
+    <!-- The StrField type is not analyzed, but indexed/stored verbatim.
+       It supports doc values but in that case the field needs to be
+       single-valued and either required or have a default value.
+      -->
+    <fieldType name="string" class="solr.StrField" sortMissingLast="true" docValues="true" />
+    <fieldType name="strings" class="solr.StrField" sortMissingLast="true" multiValued="true" docValues="true" />
+
+    <!-- boolean type: "true" or "false" -->
+    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
+
+    <fieldType name="booleans" class="solr.BoolField" sortMissingLast="true" multiValued="true"/>
+
+    <!-- sortMissingLast and sortMissingFirst attributes are optional attributes are
+         currently supported on types that are sorted internally as strings
+         and on numeric types.
+	     This includes "string","boolean", "int", "float", "long", "date", "double",
+	     including the "Trie" and "Point" variants.
+       - If sortMissingLast="true", then a sort on this field will cause documents
+         without the field to come after documents with the field,
+         regardless of the requested sort order (asc or desc).
+       - If sortMissingFirst="true", then a sort on this field will cause documents
+         without the field to come before documents with the field,
+         regardless of the requested sort order.
+       - If sortMissingLast="false" and sortMissingFirst="false" (the default),
+         then default lucene sorting will be used which places docs without the
+         field first in an ascending sort and last in a descending sort.
+    -->    
+
+    <!--
+      Numeric field types that index values using KD-trees. *Point fields are faster and more efficient than Trie* fields both, at
+      search time and at index time, but some features are still not supported.
+      Point fields don't support FieldCache, so they must have docValues="true" if needed for sorting, faceting, functions, etc.
+    -->
+    <fieldType name="pint" class="solr.IntPointField" docValues="true"/>
+    <fieldType name="pfloat" class="solr.FloatPointField" docValues="true"/>
+    <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+    <fieldType name="pdouble" class="solr.DoublePointField" docValues="true"/>
+    
+    <fieldType name="pints" class="solr.IntPointField" docValues="true" multiValued="true"/>
+    <fieldType name="pfloats" class="solr.FloatPointField" docValues="true" multiValued="true"/>
+    <fieldType name="plongs" class="solr.LongPointField" docValues="true" multiValued="true"/>
+    <fieldType name="pdoubles" class="solr.DoublePointField" docValues="true" multiValued="true"/>
+
+    <!--
+      Default numeric field types. For faster range queries, consider *PointFields (pint/pfloat/plong/pdouble), or the 
+      tint/tfloat/tlong/tdouble types.
+    -->
+    <fieldType name="int" class="solr.TrieIntField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="float" class="solr.TrieFloatField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="long" class="solr.TrieLongField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="double" class="solr.TrieDoubleField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
+
+    <fieldType name="ints" class="solr.TrieIntField" docValues="true" precisionStep="0" positionIncrementGap="0" multiValued="true"/>
+    <fieldType name="floats" class="solr.TrieFloatField" docValues="true" precisionStep="0" positionIncrementGap="0" multiValued="true"/>
+    <fieldType name="longs" class="solr.TrieLongField" docValues="true" precisionStep="0" positionIncrementGap="0" multiValued="true"/>
+    <fieldType name="doubles" class="solr.TrieDoubleField" docValues="true" precisionStep="0" positionIncrementGap="0" multiValued="true"/>
+
+    <!--
+     Numeric field types that index each value at various levels of precision
+     to accelerate range queries when the number of values between the range
+     endpoints is large. See the javadoc for NumericRangeQuery for internal
+     implementation details.
+
+     Smaller precisionStep values (specified in bits) will lead to more tokens
+     indexed per value, slightly larger index size, and faster range queries.
+     A precisionStep of 0 disables indexing at different precision levels.
+     
+     Consider using pint/pfloat/plong/pdouble instead of Trie* fields if possible
+    -->
+    <fieldType name="tint" class="solr.TrieIntField" docValues="true" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tfloat" class="solr.TrieFloatField" docValues="true" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tlong" class="solr.TrieLongField" docValues="true" precisionStep="8" positionIncrementGap="0"/>
+    <fieldType name="tdouble" class="solr.TrieDoubleField" docValues="true" precisionStep="8" positionIncrementGap="0"/>
+    
+    <fieldType name="tints" class="solr.TrieIntField" docValues="true" precisionStep="8" positionIncrementGap="0" multiValued="true"/>
+    <fieldType name="tfloats" class="solr.TrieFloatField" docValues="true" precisionStep="8" positionIncrementGap="0" multiValued="true"/>
+    <fieldType name="tlongs" class="solr.TrieLongField" docValues="true" precisionStep="8" positionIncrementGap="0" multiValued="true"/>
+    <fieldType name="tdoubles" class="solr.TrieDoubleField" docValues="true" precisionStep="8" positionIncrementGap="0" multiValued="true"/>
+
+    <!-- The format for this date field is of the form 1995-12-31T23:59:59Z, and
+         is a more restricted form of the canonical representation of dateTime
+         http://www.w3.org/TR/xmlschema-2/#dateTime    
+         The trailing "Z" designates UTC time and is mandatory.
+         Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
+         All other components are mandatory.
+
+         Expressions can also be used to denote calculations that should be
+         performed relative to "NOW" to determine the value, ie...
+
+               NOW/HOUR
+                  ... Round to the start of the current hour
+               NOW-1DAY
+                  ... Exactly 1 day prior to now
+               NOW/DAY+6MONTHS+3DAYS
+                  ... 6 months and 3 days in the future from the start of
+                      the current day
+                      
+         Consult the TrieDateField javadocs for more information.
+      -->
+    <!-- KD-tree versions of date fields -->
+    <fieldType name="pdate" class="solr.DatePointField" docValues="true"/>
+    <fieldType name="pdates" class="solr.DatePointField" docValues="true" multiValued="true"/>
+    
+    <fieldType name="date" class="solr.TrieDateField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
+    <fieldType name="dates" class="solr.TrieDateField" docValues="true" precisionStep="0" positionIncrementGap="0" multiValued="true"/>
+    <fieldType name="tdate" class="solr.TrieDateField" docValues="true" precisionStep="6" positionIncrementGap="0"/>
+    <fieldType name="tdates" class="solr.TrieDateField" docValues="true" precisionStep="6" positionIncrementGap="0" multiValued="true"/>
+
+
+    <!--Binary data type. The data should be sent/retrieved in as Base64 encoded Strings -->
+    <fieldType name="binary" class="solr.BinaryField"/>
+
+    <!-- The "RandomSortField" is not used to store or search any
+         data.  You can declare fields of this type it in your schema
+         to generate pseudo-random orderings of your docs for sorting 
+         or function purposes.  The ordering is generated based on the field
+         name and the version of the index. As long as the index version
+         remains unchanged, and the same field name is reused,
+         the ordering of the docs will be consistent.  
+         If you want different psuedo-random orderings of documents,
+         for the same version of the index, use a dynamicField and
+         change the field name in the request.
+     -->
+    <fieldType name="random" class="solr.RandomSortField" indexed="true" />
+
+    <!-- solr.TextField allows the specification of custom text analyzers
+         specified as a tokenizer and a list of token filters. Different
+         analyzers may be specified for indexing and querying.
+
+         The optional positionIncrementGap puts space between multiple fields of
+         this type on the same document, with the purpose of preventing false phrase
+         matching across fields.
+
+         For more info on customizing your analyzer chain, please see
+         http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
+     -->
+
+    <!-- One can also specify an existing Analyzer class that has a
+         default constructor via the class attribute on the analyzer element.
+         Example:
+    <fieldType name="text_greek" class="solr.TextField">
+      <analyzer class="org.apache.lucene.analysis.el.GreekAnalyzer"/>
+    </fieldType>
+    -->
+
+    <!-- A text field that only splits on whitespace for exact matching of words -->
+    <dynamicField name="*_ws" type="text_ws"  indexed="true"  stored="true"/>
+    <fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A general text field that has reasonable, generic
+         cross-language defaults: it tokenizes with StandardTokenizer,
+	       removes stop words from case-insensitive "stopwords.txt"
+	       (empty by default), and down cases.  At query time only, it
+	       also applies synonyms.
+	  -->
+    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" multiValued="true">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymGraphFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        <filter class="solr.FlattenGraphFilterFactory"/>
+        -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
+        <filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A text field with defaults appropriate for English: it
+         tokenizes with StandardTokenizer, removes English stop words
+         (lang/stopwords_en.txt), down cases, protects words from protwords.txt, and
+         finally applies Porter's stemming.  The query time analyzer
+         also applies synonyms from synonyms.txt. -->
+    <dynamicField name="*_txt_en" type="text_en"  indexed="true"  stored="true"/>
+    <fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymGraphFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        <filter class="solr.FlattenGraphFilterFactory"/>
+        -->
+        <!-- Case insensitive stop word removal.
+        -->
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+            />
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.EnglishPossessiveFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+	      -->
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+        />
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.EnglishPossessiveFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+	      -->
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A text field with defaults appropriate for English, plus
+         aggressive word-splitting and autophrase features enabled.
+         This field is just like text_en, except it adds
+         WordDelimiterGraphFilter to enable splitting and matching of
+         words on case-change, alpha numeric boundaries, and
+         non-alphanumeric chars.  This means certain compound word
+         cases will work, for example query "wi fi" will match
+         document "WiFi" or "wi-fi".
+    -->
+    <dynamicField name="*_txt_en_split" type="text_en_splitting"  indexed="true"  stored="true"/>
+    <fieldType name="text_en_splitting" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
+      <analyzer type="index">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymGraphFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <!-- Case insensitive stop word removal.
+        -->
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+        />
+        <filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.PorterStemFilterFactory"/>
+        <filter class="solr.FlattenGraphFilterFactory" />
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="lang/stopwords_en.txt"
+        />
+        <filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Less flexible matching, but less false matches.  Probably not ideal for product names,
+         but may be good for SKUs.  Can insert dashes in the wrong place and still match. -->
+    <dynamicField name="*_txt_en_split_tight" type="text_en_splitting_tight"  indexed="true"  stored="true"/>
+    <fieldType name="text_en_splitting_tight" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
+      <analyzer type="index">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/>
+        <filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="0" generateNumberParts="0" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+        <!-- this filter can remove any duplicate tokens that appear at the same position - sometimes
+             possible with WordDelimiterGraphFilter in conjuncton with stemming. -->
+        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+        <filter class="solr.FlattenGraphFilterFactory" />
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt"/>
+        <filter class="solr.WordDelimiterGraphFilterFactory" generateWordParts="0" generateNumberParts="0" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+        <!-- this filter can remove any duplicate tokens that appear at the same position - sometimes
+             possible with WordDelimiterGraphFilter in conjuncton with stemming. -->
+        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Just like text_general except it reverses the characters of
+	       each token, to enable more efficient leading wildcard queries.
+    -->
+    <dynamicField name="*_txt_rev" type="text_general_rev"  indexed="true"  stored="true"/>
+    <fieldType name="text_general_rev" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.ReversedWildcardFilterFactory" withOriginal="true"
+                maxPosAsterisk="3" maxPosQuestion="2" maxFractionAsterisk="0.33"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" />
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <dynamicField name="*_phon_en" type="phonetic_en"  indexed="true"  stored="true"/>
+    <fieldType name="phonetic_en" stored="false" indexed="true" class="solr.TextField" >
+      <analyzer>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.DoubleMetaphoneFilterFactory" inject="false"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- lowercases the entire field value, keeping it as a single token.  -->
+    <dynamicField name="*_s_lower" type="lowercase"  indexed="true"  stored="true"/>
+    <fieldType name="lowercase" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory" />
+      </analyzer>
+    </fieldType>
+
+    <!-- 
+      Example of using PathHierarchyTokenizerFactory at index time, so
+      queries for paths match documents at that path, or in descendent paths
+    -->
+    <dynamicField name="*_descendent_path" type="descendent_path"  indexed="true"  stored="true"/>
+    <fieldType name="descendent_path" class="solr.TextField">
+      <analyzer type="index">
+        <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" />
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.KeywordTokenizerFactory" />
+      </analyzer>
+    </fieldType>
+
+    <!--
+      Example of using PathHierarchyTokenizerFactory at query time, so
+      queries for paths match documents at that path, or in ancestor paths
+    -->
+    <dynamicField name="*_ancestor_path" type="ancestor_path"  indexed="true"  stored="true"/>
+    <fieldType name="ancestor_path" class="solr.TextField">
+      <analyzer type="index">
+        <tokenizer class="solr.KeywordTokenizerFactory" />
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.PathHierarchyTokenizerFactory" delimiter="/" />
+      </analyzer>
+    </fieldType>
+
+    <!-- since fields of this type are by default not stored or indexed,
+         any data added to them will be ignored outright.  --> 
+    <fieldType name="ignored" stored="false" indexed="false" docValues="false" multiValued="true" class="solr.StrField" />
+
+    <!-- This point type indexes the coordinates as separate fields (subFields)
+      If subFieldType is defined, it references a type, and a dynamic field
+      definition is created matching *___<typename>.  Alternately, if 
+      subFieldSuffix is defined, that is used to create the subFields.
+      Example: if subFieldType="double", then the coordinates would be
+        indexed in fields myloc_0___double,myloc_1___double.
+      Example: if subFieldSuffix="_d" then the coordinates would be indexed
+        in fields myloc_0_d,myloc_1_d
+      The subFields are an implementation detail of the fieldType, and end
+      users normally should not need to know about them.
+     -->
+    <dynamicField name="*_point" type="point"  indexed="true"  stored="true"/>
+    <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
+
+    <!-- A specialized field for geospatial search filters and distance sorting. -->
+    <fieldType name="location" class="solr.LatLonPointSpatialField" docValues="true"/>
+
+    <!-- An alternative geospatial field type new to Solr 4.  It supports multiValued and polygon shapes.
+      For more information about this and other Spatial fields new to Solr 4, see:
+      http://wiki.apache.org/solr/SolrAdaptersForLuceneSpatial4
+    -->
+    <fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"
+               geo="true" distErrPct="0.025" maxDistErr="0.001" distanceUnits="kilometers" />
+
+    <!-- Payloaded field types -->
+    <fieldType name="delimited_payloads_float" stored="false" indexed="true" class="solr.TextField">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.DelimitedPayloadTokenFilterFactory" encoder="float"/>
+      </analyzer>
+    </fieldType>
+    <fieldType name="delimited_payloads_int" stored="false" indexed="true" class="solr.TextField">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.DelimitedPayloadTokenFilterFactory" encoder="integer"/>
+      </analyzer>
+    </fieldType>
+    <fieldType name="delimited_payloads_string" stored="false" indexed="true" class="solr.TextField">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.DelimitedPayloadTokenFilterFactory" encoder="identity"/>
+      </analyzer>
+    </fieldType>
+
+   <!-- Money/currency field type. See http://wiki.apache.org/solr/MoneyFieldType
+        Parameters:
+          amountLongSuffix: Required. Refers to a dynamic field for the raw amount sub-field. 
+                              The dynamic field must have a field type that extends LongValueFieldType.
+                              Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
+          codeStrSuffix:    Required. Refers to a dynamic field for the currency code sub-field.
+                              The dynamic field must have a field type that extends StrField.
+                              Note: If you expect to use Atomic Updates, this dynamic field may not be stored.
+          defaultCurrency:  Specifies the default currency if none specified. Defaults to "USD"
+          providerClass:    Lets you plug in other exchange provider backend:
+                            solr.FileExchangeRateProvider is the default and takes one parameter:
+                              currencyConfig: name of an xml file holding exchange rates
+                            solr.OpenExchangeRatesOrgProvider uses rates from openexchangerates.org:
+                              ratesFileLocation: URL or path to rates JSON file (default latest.json on the web)
+                              refreshInterval: Number of minutes between each rates fetch (default: 1440, min: 60)
+   -->
+    <fieldType name="currency" class="solr.CurrencyFieldType" amountLongSuffix="_l_ns" codeStrSuffix="_s_ns"
+               defaultCurrency="USD" currencyConfig="currency.xml" />
+
+
+    <!-- some examples for different languages (generally ordered by ISO code) -->
+
+    <!-- Arabic -->
+    <dynamicField name="*_txt_ar" type="text_ar"  indexed="true"  stored="true"/>
+    <fieldType name="text_ar" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- for any non-arabic -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ar.txt" />
+        <!-- normalizes ﻯ to ﻱ, etc -->
+        <filter class="solr.ArabicNormalizationFilterFactory"/>
+        <filter class="solr.ArabicStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Bulgarian -->
+    <dynamicField name="*_txt_bg" type="text_bg"  indexed="true"  stored="true"/>
+    <fieldType name="text_bg" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/> 
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_bg.txt" /> 
+        <filter class="solr.BulgarianStemFilterFactory"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- Catalan -->
+    <dynamicField name="*_txt_ca" type="text_ca"  indexed="true"  stored="true"/>
+    <fieldType name="text_ca" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes l', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_ca.txt"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ca.txt" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Catalan"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- CJK bigram (see text_ja for a Japanese configuration using morphological analysis) -->
+    <dynamicField name="*_txt_cjk" type="text_cjk"  indexed="true"  stored="true"/>
+    <fieldType name="text_cjk" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- normalize width before bigram, as e.g. half-width dakuten combine  -->
+        <filter class="solr.CJKWidthFilterFactory"/>
+        <!-- for any non-CJK -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.CJKBigramFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Czech -->
+    <dynamicField name="*_txt_cz" type="text_cz"  indexed="true"  stored="true"/>
+    <fieldType name="text_cz" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_cz.txt" />
+        <filter class="solr.CzechStemFilterFactory"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- Danish -->
+    <dynamicField name="*_txt_da" type="text_da"  indexed="true"  stored="true"/>
+    <fieldType name="text_da" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_da.txt" format="snowball" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Danish"/>       
+      </analyzer>
+    </fieldType>
+    
+    <!-- German -->
+    <dynamicField name="*_txt_de" type="text_de"  indexed="true"  stored="true"/>
+    <fieldType name="text_de" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_de.txt" format="snowball" />
+        <filter class="solr.GermanNormalizationFilterFactory"/>
+        <filter class="solr.GermanLightStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.GermanMinimalStemFilterFactory"/> -->
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="German2"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Greek -->
+    <dynamicField name="*_txt_el" type="text_el"  indexed="true"  stored="true"/>
+    <fieldType name="text_el" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- greek specific lowercase for sigma -->
+        <filter class="solr.GreekLowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="false" words="lang/stopwords_el.txt" />
+        <filter class="solr.GreekStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Spanish -->
+    <dynamicField name="*_txt_es" type="text_es"  indexed="true"  stored="true"/>
+    <fieldType name="text_es" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_es.txt" format="snowball" />
+        <filter class="solr.SpanishLightStemFilterFactory"/>
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Spanish"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Basque -->
+    <dynamicField name="*_txt_eu" type="text_eu"  indexed="true"  stored="true"/>
+    <fieldType name="text_eu" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_eu.txt" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Basque"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Persian -->
+    <dynamicField name="*_txt_fa" type="text_fa"  indexed="true"  stored="true"/>
+    <fieldType name="text_fa" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <!-- for ZWNJ -->
+        <charFilter class="solr.PersianCharFilterFactory"/>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.ArabicNormalizationFilterFactory"/>
+        <filter class="solr.PersianNormalizationFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fa.txt" />
+      </analyzer>
+    </fieldType>
+    
+    <!-- Finnish -->
+    <dynamicField name="*_txt_fi" type="text_fi"  indexed="true"  stored="true"/>
+    <fieldType name="text_fi" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fi.txt" format="snowball" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Finnish"/>
+        <!-- less aggressive: <filter class="solr.FinnishLightStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- French -->
+    <dynamicField name="*_txt_fr" type="text_fr"  indexed="true"  stored="true"/>
+    <fieldType name="text_fr" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes l', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_fr.txt"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_fr.txt" format="snowball" />
+        <filter class="solr.FrenchLightStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.FrenchMinimalStemFilterFactory"/> -->
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="French"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Irish -->
+    <dynamicField name="*_txt_ga" type="text_ga"  indexed="true"  stored="true"/>
+    <fieldType name="text_ga" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes d', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_ga.txt"/>
+        <!-- removes n-, etc. position increments is intentionally false! -->
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/hyphenations_ga.txt"/>
+        <filter class="solr.IrishLowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ga.txt"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Irish"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Galician -->
+    <dynamicField name="*_txt_gl" type="text_gl"  indexed="true"  stored="true"/>
+    <fieldType name="text_gl" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_gl.txt" />
+        <filter class="solr.GalicianStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.GalicianMinimalStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Hindi -->
+    <dynamicField name="*_txt_hi" type="text_hi"  indexed="true"  stored="true"/>
+    <fieldType name="text_hi" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <!-- normalizes unicode representation -->
+        <filter class="solr.IndicNormalizationFilterFactory"/>
+        <!-- normalizes variation in spelling -->
+        <filter class="solr.HindiNormalizationFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hi.txt" />
+        <filter class="solr.HindiStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Hungarian -->
+    <dynamicField name="*_txt_hu" type="text_hu"  indexed="true"  stored="true"/>
+    <fieldType name="text_hu" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hu.txt" format="snowball" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Hungarian"/>
+        <!-- less aggressive: <filter class="solr.HungarianLightStemFilterFactory"/> -->   
+      </analyzer>
+    </fieldType>
+    
+    <!-- Armenian -->
+    <dynamicField name="*_txt_hy" type="text_hy"  indexed="true"  stored="true"/>
+    <fieldType name="text_hy" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_hy.txt" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Armenian"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Indonesian -->
+    <dynamicField name="*_txt_id" type="text_id"  indexed="true"  stored="true"/>
+    <fieldType name="text_id" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_id.txt" />
+        <!-- for a less aggressive approach (only inflectional suffixes), set stemDerivational to false -->
+        <filter class="solr.IndonesianStemFilterFactory" stemDerivational="true"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Italian -->
+  <dynamicField name="*_txt_it" type="text_it"  indexed="true"  stored="true"/>
+  <fieldType name="text_it" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- removes l', etc -->
+        <filter class="solr.ElisionFilterFactory" ignoreCase="true" articles="lang/contractions_it.txt"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_it.txt" format="snowball" />
+        <filter class="solr.ItalianLightStemFilterFactory"/>
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Italian"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Japanese using morphological analysis (see text_cjk for a configuration using bigramming)
+
+         NOTE: If you want to optimize search for precision, use default operator AND in your request
+         handler config (q.op) Use OR if you would like to optimize for recall (default).
+    -->
+    <dynamicField name="*_txt_ja" type="text_ja"  indexed="true"  stored="true"/>
+    <fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false">
+      <analyzer>
+        <!-- Kuromoji Japanese morphological analyzer/tokenizer (JapaneseTokenizer)
+
+           Kuromoji has a search mode (default) that does segmentation useful for search.  A heuristic
+           is used to segment compounds into its parts and the compound itself is kept as synonym.
+
+           Valid values for attribute mode are:
+              normal: regular segmentation
+              search: segmentation useful for search with synonyms compounds (default)
+            extended: same as search mode, but unigrams unknown words (experimental)
+
+           For some applications it might be good to use search mode for indexing and normal mode for
+           queries to reduce recall and prevent parts of compounds from being matched and highlighted.
+           Use <analyzer type="index"> and <analyzer type="query"> for this and mode normal in query.
+
+           Kuromoji also has a convenient user dictionary feature that allows overriding the statistical
+           model with your own entries for segmentation, part-of-speech tags and readings without a need
+           to specify weights.  Notice that user dictionaries have not been subject to extensive testing.
+
+           User dictionary attributes are:
+                     userDictionary: user dictionary filename
+             userDictionaryEncoding: user dictionary encoding (default is UTF-8)
+
+           See lang/userdict_ja.txt for a sample user dictionary file.
+
+           Punctuation characters are discarded by default.  Use discardPunctuation="false" to keep them.
+
+           See http://wiki.apache.org/solr/JapaneseLanguageSupport for more on Japanese language support.
+        -->
+        <tokenizer class="solr.JapaneseTokenizerFactory" mode="search"/>
+        <!--<tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>-->
+        <!-- Reduces inflected verbs and adjectives to their base/dictionary forms (辞書形) -->
+        <filter class="solr.JapaneseBaseFormFilterFactory"/>
+        <!-- Removes tokens with certain part-of-speech tags -->
+        <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt" />
+        <!-- Normalizes full-width romaji to half-width and half-width kana to full-width (Unicode NFKC subset) -->
+        <filter class="solr.CJKWidthFilterFactory"/>
+        <!-- Removes common tokens typically not useful for search, but have a negative effect on ranking -->
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt" />
+        <!-- Normalizes common katakana spelling variations by removing any last long sound character (U+30FC) -->
+        <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
+        <!-- Lower-cases romaji characters -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Latvian -->
+    <dynamicField name="*_txt_lv" type="text_lv"  indexed="true"  stored="true"/>
+    <fieldType name="text_lv" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_lv.txt" />
+        <filter class="solr.LatvianStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Dutch -->
+    <dynamicField name="*_txt_nl" type="text_nl"  indexed="true"  stored="true"/>
+    <fieldType name="text_nl" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_nl.txt" format="snowball" />
+        <filter class="solr.StemmerOverrideFilterFactory" dictionary="lang/stemdict_nl.txt" ignoreCase="false"/>
+        <filter class="solr.SnowballPorterFilterFactory" language="Dutch"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Norwegian -->
+    <dynamicField name="*_txt_no" type="text_no"  indexed="true"  stored="true"/>
+    <fieldType name="text_no" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_no.txt" format="snowball" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Norwegian"/>
+        <!-- less aggressive: <filter class="solr.NorwegianLightStemFilterFactory"/> -->
+        <!-- singular/plural: <filter class="solr.NorwegianMinimalStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Portuguese -->
+  <dynamicField name="*_txt_pt" type="text_pt"  indexed="true"  stored="true"/>
+  <fieldType name="text_pt" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_pt.txt" format="snowball" />
+        <filter class="solr.PortugueseLightStemFilterFactory"/>
+        <!-- less aggressive: <filter class="solr.PortugueseMinimalStemFilterFactory"/> -->
+        <!-- more aggressive: <filter class="solr.SnowballPorterFilterFactory" language="Portuguese"/> -->
+        <!-- most aggressive: <filter class="solr.PortugueseStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Romanian -->
+    <dynamicField name="*_txt_ro" type="text_ro"  indexed="true"  stored="true"/>
+    <fieldType name="text_ro" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ro.txt" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Romanian"/>
+      </analyzer>
+    </fieldType>
+    
+    <!-- Russian -->
+    <dynamicField name="*_txt_ru" type="text_ru"  indexed="true"  stored="true"/>
+    <fieldType name="text_ru" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ru.txt" format="snowball" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Russian"/>
+        <!-- less aggressive: <filter class="solr.RussianLightStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Swedish -->
+    <dynamicField name="*_txt_sv" type="text_sv"  indexed="true"  stored="true"/>
+    <fieldType name="text_sv" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_sv.txt" format="snowball" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Swedish"/>
+        <!-- less aggressive: <filter class="solr.SwedishLightStemFilterFactory"/> -->
+      </analyzer>
+    </fieldType>
+    
+    <!-- Thai -->
+    <dynamicField name="*_txt_th" type="text_th"  indexed="true"  stored="true"/>
+    <fieldType name="text_th" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.ThaiTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_th.txt" />
+      </analyzer>
+    </fieldType>
+    
+    <!-- Turkish -->
+    <dynamicField name="*_txt_tr" type="text_tr"  indexed="true"  stored="true"/>
+    <fieldType name="text_tr" class="solr.TextField" positionIncrementGap="100">
+      <analyzer> 
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.TurkishLowerCaseFilterFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="false" words="lang/stopwords_tr.txt" />
+        <filter class="solr.SnowballPorterFilterFactory" language="Turkish"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Similarity is the scoring routine for each document vs. a query.
+       A custom Similarity or SimilarityFactory may be specified here, but 
+       the default is fine for most applications.  
+       For more info: http://wiki.apache.org/solr/SchemaXml#Similarity
+    -->
+    <!--
+     <similarity class="com.example.solr.CustomSimilarityFactory">
+       <str name="paramkey">param value</str>
+     </similarity>
+    -->
+
+</schema>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/params.json
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/params.json b/solr/core/src/test-files/solr/configsets/_default/conf/params.json
new file mode 100644
index 0000000..06114ef
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/params.json
@@ -0,0 +1,20 @@
+{"params":{
+  "query":{
+    "defType":"edismax",
+    "q.alt":"*:*",
+    "rows":"10",
+    "fl":"*,score",
+    "":{"v":0}
+  },
+  "facets":{
+    "facet":"on",
+    "facet.mincount": "1",
+    "":{"v":0}
+  },
+ "velocity":{
+   "wt": "velocity",
+   "v.template":"browse",
+   "v.layout": "layout",
+   "":{"v":0}
+ }
+}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/protwords.txt
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/protwords.txt b/solr/core/src/test-files/solr/configsets/_default/conf/protwords.txt
new file mode 100644
index 0000000..1dfc0ab
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/protwords.txt
@@ -0,0 +1,21 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+# Use a protected word file to protect against the stemmer reducing two
+# unrelated words to the same base word.
+
+# Some non-words that normally won't be encountered,
+# just to test that they won't be stemmed.
+dontstems
+zwhacky
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/85069cac/solr/core/src/test-files/solr/configsets/_default/conf/schema.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/schema.xml b/solr/core/src/test-files/solr/configsets/_default/conf/schema.xml
deleted file mode 100644
index e94229e..0000000
--- a/solr/core/src/test-files/solr/configsets/_default/conf/schema.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements.  See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License.  You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<schema name="default-config" version="1.6">
-    <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
-    <field name="_version_" type="long" indexed="false" stored="false"/>
-    <field name="_root_" type="string" indexed="true" stored="false" docValues="false" />
-    <field name="_text_" type="text_general" indexed="true" stored="false" multiValued="true"/>
-
-    <fieldType name="string" class="solr.StrField" sortMissingLast="true" docValues="true" />
-    <fieldType name="long" class="solr.TrieLongField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
-    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" multiValued="true">
-      <analyzer type="index">
-        <tokenizer class="solr.StandardTokenizerFactory"/>
-        <filter class="solr.LowerCaseFilterFactory"/>
-      </analyzer>
-      <analyzer type="query">
-        <tokenizer class="solr.StandardTokenizerFactory"/>
-        <filter class="solr.LowerCaseFilterFactory"/>
-      </analyzer>
-    </fieldType>
-</schema>


[38/58] [abbrv] lucene-solr:jira/solr-10879: Fix solrj test compilation error.

Posted by ab...@apache.org.
Fix solrj test compilation error.


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

Branch: refs/heads/jira/solr-10879
Commit: cabb1fa366c5fc74a3be25f9a2e92b023c04343f
Parents: b4fa0e7
Author: Karl Wright <Da...@gmail.com>
Authored: Thu Jun 29 05:13:51 2017 -0400
Committer: Karl Wright <Da...@gmail.com>
Committed: Thu Jun 29 05:13:51 2017 -0400

----------------------------------------------------------------------
 .../solr/client/solrj/embedded/SolrExampleStreamingTest.java       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cabb1fa3/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java
index 35ab898..6443ce9 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java
@@ -132,7 +132,7 @@ public class SolrExampleStreamingTest extends SolrExampleTests {
       lastError = ex;
     }
     
-    static class Builder extends ConcurrentUpdateSolrClient.Builder {
+    public static class Builder extends ConcurrentUpdateSolrClient.Builder {
 
       public Builder(String baseSolrUrl) {
         super(baseSolrUrl);


[58/58] [abbrv] lucene-solr:jira/solr-10879: Merge branch 'master' into jira/solr-10879

Posted by ab...@apache.org.
Merge branch 'master' into jira/solr-10879


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/97ebeced
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/97ebeced
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/97ebeced

Branch: refs/heads/jira/solr-10879
Commit: 97ebecedbfa4c2ae49074b4cc9cb3505b6ad3ab3
Parents: c488daf d070ca6
Author: Andrzej Bialecki <ab...@apache.org>
Authored: Mon Jul 3 12:41:02 2017 +0200
Committer: Andrzej Bialecki <ab...@apache.org>
Committed: Mon Jul 3 12:41:02 2017 +0200

----------------------------------------------------------------------
 README.md                                       |  103 +
 README.txt                                      |   13 -
 build.xml                                       |   37 +-
 .../lucene/classification/classification.iml    |    1 -
 .../lucene/spatial-extras/spatial-extras.iml    |    5 +-
 dev-tools/scripts/smokeTestRelease.py           |   12 +-
 lucene/CHANGES.txt                              |   28 +
 lucene/MIGRATE.txt                              |   17 +-
 .../lucene/analysis/custom/CustomAnalyzer.java  |   16 +-
 .../miscellaneous/ConcatenatingTokenStream.java |  121 +
 .../PrefixAndSuffixAwareTokenFilter.java        |   84 -
 .../miscellaneous/PrefixAwareTokenFilter.java   |  202 --
 .../payloads/NumericPayloadTokenFilter.java     |    7 +-
 .../payloads/TypeAsPayloadTokenFilter.java      |    6 +-
 .../analysis/util/ClasspathResourceLoader.java  |   12 +-
 .../analysis/util/FilesystemResourceLoader.java |   16 +
 .../TestConcatenatingTokenStream.java           |   82 +
 .../TestPrefixAndSuffixAwareTokenFilter.java    |   49 -
 .../TestPrefixAwareTokenFilter.java             |   60 -
 .../byTask/feeds/SpatialFileQueryMaker.java     |   15 +-
 lucene/classification/build.xml                 |    6 +-
 .../classification/KNearestFuzzyClassifier.java |   29 +-
 .../classification/utils/NearestFuzzyQuery.java |  333 ++
 .../KNearestFuzzyClassifierTest.java            |    2 +-
 lucene/common-build.xml                         |    2 +-
 .../org/apache/lucene/analysis/Analyzer.java    |    4 +-
 .../java/org/apache/lucene/analysis/Token.java  |  210 --
 .../org/apache/lucene/analysis/TokenStream.java |    7 +-
 .../tokenattributes/CharTermAttributeImpl.java  |    5 -
 .../index/BinaryDocValuesFieldUpdates.java      |  101 +-
 .../apache/lucene/index/BufferedUpdates.java    |   53 +-
 .../lucene/index/BufferedUpdatesStream.java     |  701 +---
 .../apache/lucene/index/CoalescedUpdates.java   |  109 -
 .../lucene/index/DocValuesFieldUpdates.java     |  190 +-
 .../apache/lucene/index/DocValuesUpdate.java    |    3 -
 .../apache/lucene/index/DocumentsWriter.java    |   82 +-
 .../index/DocumentsWriterDeleteQueue.java       |   29 +-
 .../index/DocumentsWriterFlushControl.java      |   21 +-
 .../lucene/index/DocumentsWriterFlushQueue.java |   37 +-
 .../lucene/index/DocumentsWriterPerThread.java  |   35 +-
 .../index/DocumentsWriterPerThreadPool.java     |   11 +-
 .../lucene/index/FlushByRamOrCountsPolicy.java  |   29 +-
 .../org/apache/lucene/index/FlushPolicy.java    |    3 -
 .../lucene/index/FreqProxTermsWriter.java       |    5 +-
 .../lucene/index/FrozenBufferedUpdates.java     |  848 ++++-
 .../apache/lucene/index/IndexFileDeleter.java   |    7 +-
 .../org/apache/lucene/index/IndexWriter.java    |  777 +++--
 .../apache/lucene/index/IndexWriterConfig.java  |   19 +-
 .../lucene/index/LiveIndexWriterConfig.java     |   48 +-
 .../index/MergedPrefixCodedTermsIterator.java   |  132 -
 .../index/NumericDocValuesFieldUpdates.java     |   97 +-
 .../apache/lucene/index/PrefixCodedTerms.java   |    2 +-
 .../apache/lucene/index/ReadersAndUpdates.java  |  415 ++-
 .../apache/lucene/index/SegmentCommitInfo.java  |   16 +-
 .../apache/lucene/index/SegmentCoreReaders.java |    2 -
 .../org/apache/lucene/index/SegmentInfo.java    |    2 +-
 .../org/apache/lucene/index/SegmentReader.java  |   19 +-
 .../lucene/index/SerialMergeScheduler.java      |    4 +-
 .../apache/lucene/index/TieredMergePolicy.java  |   73 +-
 .../org/apache/lucene/search/DoubleValues.java  |   21 +
 .../lucene/search/DoubleValuesSource.java       |  216 +-
 .../apache/lucene/search/LongValuesSource.java  |   82 +-
 .../util/packed/AbstractPagedMutable.java       |    2 +-
 .../index/TestBinaryDocValuesUpdates.java       |  146 +-
 .../index/TestDocumentsWriterDeleteQueue.java   |   39 +-
 .../index/TestFlushByRamOrCountsPolicy.java     |   12 +-
 .../lucene/index/TestForceMergeForever.java     |    7 +-
 .../lucene/index/TestIndexManyDocuments.java    |   71 +
 .../apache/lucene/index/TestIndexWriter.java    |   61 -
 .../lucene/index/TestIndexWriterConfig.java     |    7 +-
 .../lucene/index/TestIndexWriterDelete.java     |  153 +-
 .../lucene/index/TestIndexWriterExceptions.java |  253 --
 .../lucene/index/TestIndexWriterReader.java     |    1 +
 .../lucene/index/TestNRTReaderWithThreads.java  |    8 +-
 .../index/TestNumericDocValuesUpdates.java      |  314 +-
 .../lucene/index/TestPerSegmentDeletes.java     |    7 +-
 .../lucene/index/TestPrefixCodedTerms.java      |   76 -
 .../TestControlledRealTimeReopenThread.java     |    4 +-
 .../lucene/search/TestDoubleValuesSource.java   |   16 +-
 .../facet/range/TestRangeFacetCounts.java       |   75 +-
 .../lucene/search/highlight/TokenGroup.java     |   15 +-
 .../apache/lucene/search/join/TestJoinUtil.java |   16 +-
 .../apache/lucene/index/memory/MemoryIndex.java |    6 +-
 .../lucene/index/memory/TestMemoryIndex.java    |   40 +
 .../queries/function/FunctionScoreQuery.java    |    9 -
 .../lucene/queries/function/ValueSource.java    |  260 +-
 .../function/TestFunctionScoreExplanations.java |    8 +-
 .../function/TestFunctionScoreQuery.java        |   91 +-
 .../queryparser/classic/FastCharStream.java     |    2 +-
 .../standard/parser/FastCharStream.java         |    2 +-
 .../surround/parser/FastCharStream.java         |    2 +-
 .../idversion/IDVersionPostingsWriter.java      |    4 +-
 .../idversion/VersionBlockTreeTermsWriter.java  |    4 +-
 lucene/spatial-extras/build.xml                 |    8 +-
 .../org/apache/lucene/spatial/ShapeValues.java  |   41 +
 .../lucene/spatial/ShapeValuesSource.java       |   34 +
 .../apache/lucene/spatial/SpatialStrategy.java  |   19 +-
 .../bbox/BBoxOverlapRatioValueSource.java       |    7 +-
 .../spatial/bbox/BBoxSimilarityValueSource.java |   79 +-
 .../lucene/spatial/bbox/BBoxStrategy.java       |   13 +-
 .../lucene/spatial/bbox/BBoxValueSource.java    |   74 +-
 .../composite/CompositeSpatialStrategy.java     |   14 +-
 .../spatial/composite/CompositeVerifyQuery.java |   32 +-
 .../composite/IntersectsRPTVerifyQuery.java     |   21 +-
 .../prefix/NumberRangePrefixTreeStrategy.java   |    4 +-
 .../spatial/prefix/PrefixTreeStrategy.java      |    4 +-
 .../serialized/SerializedDVStrategy.java        |  110 +-
 .../spatial/util/CachingDoubleValueSource.java  |   61 +-
 .../util/DistanceToShapeValueSource.java        |   68 +-
 .../util/ReciprocalDoubleValuesSource.java      |   96 +
 .../spatial/util/ShapeAreaValueSource.java      |   67 +-
 .../ShapeFieldCacheDistanceValueSource.java     |   59 +-
 .../spatial/util/ShapePredicateValueSource.java |  113 -
 .../spatial/util/ShapeValuesPredicate.java      |   99 +
 .../spatial/vector/DistanceValueSource.java     |   72 +-
 .../spatial/vector/PointVectorStrategy.java     |   95 +-
 .../lucene/spatial/DistanceStrategyTest.java    |    6 -
 .../apache/lucene/spatial/SpatialExample.java   |   12 +-
 .../apache/lucene/spatial/StrategyTestCase.java |   39 +-
 .../lucene/spatial/spatial4j/Geo3dRptTest.java  |    2 +-
 .../Geo3dShapeRectRelationTestCase.java         |    2 +-
 .../DocumentValueSourceDictionaryTest.java      |   15 +
 .../java/org/apache/lucene/analysis/Token.java  |  195 ++
 .../index/BaseDocValuesFormatTestCase.java      |   24 +
 .../index/BaseIndexFileFormatTestCase.java      |    2 +-
 .../org/apache/lucene/util/LuceneTestCase.java  |   11 -
 lucene/tools/forbiddenApis/base.txt             |    4 +
 solr/CHANGES.txt                                |  109 +-
 solr/bin/solr                                   |   41 +-
 solr/bin/solr.cmd                               |   24 +-
 .../collection1/conf/solrconfig-icucollate.xml  |    2 +-
 .../apache/solr/analytics/AnalyticsDriver.java  |   82 +
 .../solr/analytics/AnalyticsExpression.java     |   64 +
 .../analytics/AnalyticsGroupingManager.java     |  239 ++
 .../solr/analytics/AnalyticsRequestManager.java |  279 ++
 .../solr/analytics/AnalyticsRequestParser.java  |  549 +++
 .../solr/analytics/ExpressionFactory.java       |  821 +++++
 .../analytics/accumulator/BasicAccumulator.java |  173 -
 .../accumulator/FacetingAccumulator.java        |  730 ----
 .../analytics/accumulator/ValueAccumulator.java |   40 -
 .../facet/FacetValueAccumulator.java            |   35 -
 .../facet/FieldFacetAccumulator.java            |  153 -
 .../facet/QueryFacetAccumulator.java            |   72 -
 .../facet/RangeFacetAccumulator.java            |   49 -
 .../accumulator/facet/package-info.java         |   24 -
 .../analytics/accumulator/package-info.java     |   23 -
 .../analytics/expression/BaseExpression.java    |   88 -
 .../expression/DualDelegateExpression.java      |   99 -
 .../solr/analytics/expression/Expression.java   |   39 -
 .../analytics/expression/ExpressionFactory.java |  175 -
 .../expression/MultiDelegateExpression.java     |  131 -
 .../expression/SingleDelegateExpression.java    |   88 -
 .../solr/analytics/expression/package-info.java |   23 -
 .../analytics/facet/AbstractSolrQueryFacet.java |  104 +
 .../solr/analytics/facet/AnalyticsFacet.java    |  166 +
 .../apache/solr/analytics/facet/PivotFacet.java |  114 +
 .../apache/solr/analytics/facet/PivotNode.java  |  263 ++
 .../apache/solr/analytics/facet/QueryFacet.java |   64 +
 .../apache/solr/analytics/facet/RangeFacet.java |  119 +
 .../solr/analytics/facet/SortableFacet.java     |  178 +
 .../solr/analytics/facet/StreamingFacet.java    |   32 +
 .../apache/solr/analytics/facet/ValueFacet.java |   60 +
 .../facet/compare/ConstantComparator.java       |   30 +
 .../facet/compare/DelegatingComparator.java     |   62 +
 .../facet/compare/ExpressionComparator.java     |   46 +
 .../facet/compare/FacetResultsComparator.java   |   52 +
 .../facet/compare/FacetValueComparator.java     |   37 +
 .../analytics/facet/compare/package-info.java   |   23 +
 .../solr/analytics/facet/package-info.java      |   23 +
 .../function/ExpressionCalculator.java          |   71 +
 .../MergingReductionCollectionManager.java      |   46 +
 .../function/ReductionCollectionManager.java    |  320 ++
 .../analytics/function/ReductionFunction.java   |   37 +
 .../function/field/AnalyticsField.java          |   69 +
 .../analytics/function/field/BooleanField.java  |  111 +
 .../function/field/BooleanMultiField.java       |  101 +
 .../analytics/function/field/DateField.java     |  108 +
 .../function/field/DateMultiField.java          |   47 +
 .../function/field/DateMultiPointField.java     |   47 +
 .../analytics/function/field/DoubleField.java   |   97 +
 .../function/field/DoubleMultiField.java        |   85 +
 .../function/field/DoubleMultiPointField.java   |   81 +
 .../analytics/function/field/FloatField.java    |  108 +
 .../function/field/FloatMultiField.java         |   91 +
 .../function/field/FloatMultiPointField.java    |   87 +
 .../solr/analytics/function/field/IntField.java |  129 +
 .../analytics/function/field/IntMultiField.java |  100 +
 .../function/field/IntMultiPointField.java      |   96 +
 .../analytics/function/field/LongField.java     |  107 +
 .../function/field/LongMultiField.java          |   89 +
 .../function/field/LongMultiPointField.java     |   86 +
 .../analytics/function/field/StringField.java   |   85 +
 .../function/field/StringMultiField.java        |   66 +
 .../analytics/function/field/package-info.java  |   23 +
 .../function/mapping/AbsoluteValueFunction.java |   54 +
 .../analytics/function/mapping/AddFunction.java |   68 +
 .../function/mapping/BottomFunction.java        |  163 +
 .../function/mapping/CompareFunction.java       |  614 ++++
 .../function/mapping/ConcatFunction.java        |   78 +
 .../function/mapping/DateMathFunction.java      |  156 +
 .../function/mapping/DateParseFunction.java     |  210 ++
 .../function/mapping/DivideFunction.java        |   51 +
 .../function/mapping/FillMissingFunction.java   |  842 +++++
 .../function/mapping/FilterFunction.java        |  722 ++++
 .../analytics/function/mapping/IfFunction.java  |  892 +++++
 .../function/mapping/JoinFunction.java          |   57 +
 .../function/mapping/LambdaFunction.java        | 3220 ++++++++++++++++++
 .../analytics/function/mapping/LogFunction.java |   51 +
 .../function/mapping/LogicFunction.java         |   90 +
 .../function/mapping/MultFunction.java          |   68 +
 .../function/mapping/NegateFunction.java        |   58 +
 .../mapping/NumericConvertFunction.java         |  256 ++
 .../function/mapping/PowerFunction.java         |   51 +
 .../function/mapping/RemoveFunction.java        |  796 +++++
 .../function/mapping/ReplaceFunction.java       |  914 +++++
 .../function/mapping/StringCastFunction.java    |   42 +
 .../function/mapping/SubtractFunction.java      |   51 +
 .../analytics/function/mapping/TopFunction.java |  163 +
 .../function/mapping/package-info.java          |   23 +
 .../solr/analytics/function/package-info.java   |   23 +
 .../function/reduction/CountFunction.java       |   87 +
 .../function/reduction/DocCountFunction.java    |   87 +
 .../function/reduction/MaxFunction.java         |  298 ++
 .../function/reduction/MedianFunction.java      |  200 ++
 .../function/reduction/MinFunction.java         |  298 ++
 .../function/reduction/MissingFunction.java     |   76 +
 .../function/reduction/OrdinalFunction.java     |  386 +++
 .../function/reduction/PercentileFunction.java  |  337 ++
 .../function/reduction/SumFunction.java         |   92 +
 .../function/reduction/UniqueFunction.java      |  101 +
 .../function/reduction/data/CountCollector.java |  188 +
 .../function/reduction/data/MaxCollector.java   |  476 +++
 .../function/reduction/data/MinCollector.java   |  476 +++
 .../function/reduction/data/ReductionData.java  |   24 +
 .../reduction/data/ReductionDataCollector.java  |  183 +
 .../reduction/data/SortedListCollector.java     |  363 ++
 .../function/reduction/data/SumCollector.java   |  124 +
 .../reduction/data/UniqueCollector.java         |  241 ++
 .../function/reduction/data/package-info.java   |   24 +
 .../function/reduction/package-info.java        |   23 +
 .../org/apache/solr/analytics/package-info.java |   23 +
 .../request/AbstractFieldFacetRequest.java      |   42 -
 .../request/AnalyticsContentHandler.java        |  314 --
 .../analytics/request/AnalyticsRequest.java     |  114 -
 .../request/AnalyticsRequestFactory.java        |  308 --
 .../solr/analytics/request/AnalyticsStats.java  |  138 -
 .../analytics/request/ExpressionRequest.java    |   72 -
 .../solr/analytics/request/FacetRequest.java    |   26 -
 .../analytics/request/FieldFacetRequest.java    |  172 -
 .../analytics/request/QueryFacetRequest.java    |   74 -
 .../analytics/request/RangeFacetRequest.java    |  129 -
 .../solr/analytics/request/package-info.java    |   24 -
 .../AbstractDelegatingStatsCollector.java       |   74 -
 .../statistics/MedianStatsCollector.java        |   76 -
 .../statistics/MinMaxStatsCollector.java        |  114 -
 .../statistics/NumericStatsCollector.java       |   68 -
 .../statistics/PercentileStatsCollector.java    |   80 -
 .../analytics/statistics/StatsCollector.java    |   69 -
 .../StatsCollectorSupplierFactory.java          |  646 ----
 .../statistics/UniqueStatsCollector.java        |   53 -
 .../solr/analytics/statistics/package-info.java |   24 -
 .../stream/AnalyticsShardRequestManager.java    |  245 ++
 .../stream/AnalyticsShardResponseParser.java    |   89 +
 .../solr/analytics/stream/package-info.java     |   23 +
 .../reservation/BooleanArrayReservation.java    |   44 +
 .../reservation/BooleanCheckedReservation.java  |   42 +
 .../stream/reservation/BooleanReservation.java  |   42 +
 .../reservation/DoubleArrayReservation.java     |   44 +
 .../reservation/DoubleCheckedReservation.java   |   43 +
 .../stream/reservation/DoubleReservation.java   |   42 +
 .../reservation/FloatArrayReservation.java      |   44 +
 .../reservation/FloatCheckedReservation.java    |   43 +
 .../stream/reservation/FloatReservation.java    |   42 +
 .../stream/reservation/IntArrayReservation.java |   42 +
 .../reservation/IntCheckedReservation.java      |   43 +
 .../stream/reservation/IntReservation.java      |   42 +
 .../reservation/LongArrayReservation.java       |   45 +
 .../reservation/LongCheckedReservation.java     |   43 +
 .../stream/reservation/LongReservation.java     |   42 +
 .../ReductionCheckedDataReservation.java        |   35 +
 .../ReductionDataArrayReservation.java          |   36 +
 .../reservation/ReductionDataReservation.java   |   53 +
 .../reservation/StringArrayReservation.java     |   45 +
 .../reservation/StringCheckedReservation.java   |   44 +
 .../stream/reservation/StringReservation.java   |   43 +
 .../stream/reservation/package-info.java        |   24 +
 .../read/BooleanCheckedDataReader.java          |   33 +
 .../read/BooleanDataArrayReader.java            |   36 +
 .../reservation/read/BooleanDataReader.java     |   33 +
 .../read/DoubleCheckedDataReader.java           |   32 +
 .../reservation/read/DoubleDataArrayReader.java |   35 +
 .../reservation/read/DoubleDataReader.java      |   32 +
 .../read/FloatCheckedDataReader.java            |   33 +
 .../reservation/read/FloatDataArrayReader.java  |   36 +
 .../reservation/read/FloatDataReader.java       |   33 +
 .../reservation/read/IntCheckedDataReader.java  |   32 +
 .../reservation/read/IntDataArrayReader.java    |   34 +
 .../stream/reservation/read/IntDataReader.java  |   32 +
 .../reservation/read/LongCheckedDataReader.java |   32 +
 .../reservation/read/LongDataArrayReader.java   |   35 +
 .../stream/reservation/read/LongDataReader.java |   32 +
 .../read/ReductionCheckedDataReader.java        |   54 +
 .../read/ReductionDataArrayReader.java          |   54 +
 .../reservation/read/ReductionDataReader.java   |   40 +
 .../read/StringCheckedDataReader.java           |   32 +
 .../reservation/read/StringDataArrayReader.java |   35 +
 .../reservation/read/StringDataReader.java      |   34 +
 .../stream/reservation/read/package-info.java   |   24 +
 .../write/BooleanCheckedDataWriter.java         |   33 +
 .../write/BooleanDataArrayWriter.java           |   36 +
 .../reservation/write/BooleanDataWriter.java    |   33 +
 .../write/DoubleCheckedDataWriter.java          |   34 +
 .../write/DoubleDataArrayWriter.java            |   36 +
 .../reservation/write/DoubleDataWriter.java     |   33 +
 .../write/FloatCheckedDataWriter.java           |   35 +
 .../reservation/write/FloatDataArrayWriter.java |   37 +
 .../reservation/write/FloatDataWriter.java      |   34 +
 .../reservation/write/IntCheckedDataWriter.java |   34 +
 .../reservation/write/IntDataArrayWriter.java   |   35 +
 .../stream/reservation/write/IntDataWriter.java |   33 +
 .../write/LongCheckedDataWriter.java            |   34 +
 .../reservation/write/LongDataArrayWriter.java  |   36 +
 .../reservation/write/LongDataWriter.java       |   33 +
 .../write/ReductionCheckedDataWriter.java       |   60 +
 .../write/ReductionDataArrayWriter.java         |   53 +
 .../reservation/write/ReductionDataWriter.java  |   40 +
 .../write/StringCheckedDataWriter.java          |   34 +
 .../write/StringDataArrayWriter.java            |   36 +
 .../reservation/write/StringDataWriter.java     |   37 +
 .../stream/reservation/write/package-info.java  |   24 +
 .../solr/analytics/util/AnalyticsParams.java    |  114 -
 .../solr/analytics/util/AnalyticsParsers.java   |  171 -
 .../util/AnalyticsResponseHeadings.java         |   36 +
 .../analytics/util/FacetRangeGenerator.java     |  356 ++
 .../solr/analytics/util/MedianCalculator.java   |    4 +
 .../solr/analytics/util/OldAnalyticsParams.java |  177 +
 .../util/OldAnalyticsRequestConverter.java      |  177 +
 .../solr/analytics/util/OrdinalCalculator.java  |  173 +
 .../analytics/util/PercentileCalculator.java    |  176 -
 .../analytics/util/RangeEndpointCalculator.java |  354 --
 .../util/function/BooleanConsumer.java          |   59 +
 .../analytics/util/function/FloatConsumer.java  |   59 +
 .../analytics/util/function/FloatSupplier.java  |   41 +
 .../analytics/util/function/package-info.java   |   23 +
 .../solr/analytics/util/package-info.java       |    3 +-
 .../AbsoluteValueDoubleFunction.java            |   60 -
 .../util/valuesource/AddDoubleFunction.java     |   49 -
 .../util/valuesource/ConstDateSource.java       |  112 -
 .../util/valuesource/ConstDoubleSource.java     |  104 -
 .../util/valuesource/ConstStringSource.java     |   50 -
 .../util/valuesource/DateFieldSource.java       |  131 -
 .../util/valuesource/DateMathFunction.java      |   71 -
 .../util/valuesource/DivDoubleFunction.java     |   48 -
 .../util/valuesource/DualDoubleFunction.java    |   94 -
 .../util/valuesource/FilterFieldSource.java     |  154 -
 .../util/valuesource/LogDoubleFunction.java     |   43 -
 .../util/valuesource/MultiDateFunction.java     |  133 -
 .../util/valuesource/MultiDoubleFunction.java   |  119 -
 .../valuesource/MultiplyDoubleFunction.java     |   49 -
 .../util/valuesource/NegateDoubleFunction.java  |   55 -
 .../util/valuesource/PowDoubleFunction.java     |   48 -
 .../util/valuesource/ReverseStringFunction.java |   45 -
 .../util/valuesource/SingleDoubleFunction.java  |   79 -
 .../util/valuesource/SingleStringFunction.java  |  117 -
 .../util/valuesource/package-info.java          |   24 -
 .../solr/analytics/value/AnalyticsValue.java    |   55 +
 .../analytics/value/AnalyticsValueStream.java   |  133 +
 .../solr/analytics/value/BooleanValue.java      |   85 +
 .../analytics/value/BooleanValueStream.java     |   55 +
 .../solr/analytics/value/ComparableValue.java   |   32 +
 .../apache/solr/analytics/value/DateValue.java  |  102 +
 .../solr/analytics/value/DateValueStream.java   |   62 +
 .../solr/analytics/value/DoubleValue.java       |   86 +
 .../solr/analytics/value/DoubleValueStream.java |   54 +
 .../apache/solr/analytics/value/FloatValue.java |   97 +
 .../solr/analytics/value/FloatValueStream.java  |   60 +
 .../apache/solr/analytics/value/IntValue.java   |  121 +
 .../solr/analytics/value/IntValueStream.java    |   71 +
 .../apache/solr/analytics/value/LongValue.java  |   97 +
 .../solr/analytics/value/LongValueStream.java   |   60 +
 .../solr/analytics/value/StringValue.java       |   71 +
 .../solr/analytics/value/StringValueStream.java |   49 +
 .../value/constant/ConstantBooleanValue.java    |   91 +
 .../value/constant/ConstantDateValue.java       |  103 +
 .../value/constant/ConstantDoubleValue.java     |   90 +
 .../value/constant/ConstantFloatValue.java      |   99 +
 .../value/constant/ConstantIntValue.java        |  118 +
 .../value/constant/ConstantLongValue.java       |  100 +
 .../value/constant/ConstantStringValue.java     |   79 +
 .../analytics/value/constant/ConstantValue.java |  128 +
 .../analytics/value/constant/package-info.java  |   23 +
 .../solr/analytics/value/package-info.java      |   23 +
 .../apache/solr/handler/AnalyticsHandler.java   |  147 +
 .../handler/component/AnalyticsComponent.java   |  119 +-
 .../java/org/apache/solr/handler/package.html   |   28 +
 .../response/AnalyticsShardResponseWriter.java  |   91 +
 .../java/org/apache/solr/response/package.html  |   28 +
 .../analytics/requestFiles/expressions.txt      |   70 -
 .../analytics/requestFiles/fieldFacetExtras.txt |   66 -
 .../analytics/requestFiles/fieldFacets.txt      |  132 -
 .../analytics/requestFiles/functions.txt        |   62 -
 .../analytics/requestFiles/noFacets.txt         |   74 -
 .../analytics/requestFiles/queryFacets.txt      |   45 -
 .../analytics/requestFiles/rangeFacets.txt      |  170 -
 .../analytics/requestXMLFiles/expressions.xml   |  285 --
 .../requestXMLFiles/fieldFacetExtras.xml        |  101 -
 .../analytics/requestXMLFiles/fieldFacets.xml   |  496 ---
 .../analytics/requestXMLFiles/functions.xml     |  246 --
 .../analytics/requestXMLFiles/noFacets.xml      |  310 --
 .../analytics/requestXMLFiles/queryFacets.xml   |   94 -
 .../analytics/requestXMLFiles/rangeFacets.xml   |  319 --
 .../test-files/solr/analytics/expressions.txt   |   65 +
 .../test-files/solr/analytics/facetSorting.txt  |    4 +
 .../solr/analytics/fieldFacetExtras.txt         |   66 +
 .../test-files/solr/analytics/fieldFacets.txt   |  132 +
 .../src/test-files/solr/analytics/functions.txt |   57 +
 .../src/test-files/solr/analytics/noFacets.txt  |   74 +
 .../test-files/solr/analytics/queryFacets.txt   |   27 +
 .../test-files/solr/analytics/rangeFacets.txt   |  161 +
 .../solr/collection1/conf/schema-analytics.xml  |   17 +-
 .../collection1/conf/solrconfig-analytics.xml   |   42 +
 .../solr/collection1/conf/solrconfig-basic.xml  |   40 -
 .../configsets/cloud-analytics/conf/schema.xml  |   63 +
 .../cloud-analytics/conf/solrconfig.xml         |   59 +
 .../AbstractAnalyticsStatsCloudTest.java        |  187 +
 .../analytics/AbstractAnalyticsStatsTest.java   |   15 +-
 .../apache/solr/analytics/NoFacetCloudTest.java |  557 +++
 .../org/apache/solr/analytics/NoFacetTest.java  |   47 +-
 .../analytics/expression/ExpressionTest.java    |   70 +-
 .../solr/analytics/expression/FunctionTest.java |  221 ++
 .../facet/AbstractAnalyticsFacetCloudTest.java  |  284 ++
 .../facet/AbstractAnalyticsFacetTest.java       |   38 +-
 .../solr/analytics/facet/FacetSortingTest.java  |   53 +
 .../analytics/facet/FieldFacetCloudTest.java    | 1214 +++++++
 .../facet/FieldFacetExtrasCloudTest.java        |  253 ++
 .../analytics/facet/FieldFacetExtrasTest.java   |    6 +-
 .../solr/analytics/facet/FieldFacetTest.java    |   63 +-
 .../analytics/facet/QueryFacetCloudTest.java    |  159 +
 .../solr/analytics/facet/QueryFacetTest.java    |   10 +-
 .../analytics/facet/RangeFacetCloudTest.java    |  588 ++++
 .../solr/analytics/facet/RangeFacetTest.java    |   43 +-
 .../util/valuesource/FunctionTest.java          |  233 --
 .../carrot2/CarrotClusteringEngine.java         |   62 +-
 .../clustering/solr/collection1/conf/schema.xml |   18 +-
 .../solr/collection1/conf/solrconfig.xml        |   20 +-
 .../clustering/ClusteringComponentTest.java     |    2 +-
 .../handler/dataimport/MailEntityProcessor.java |   31 +-
 .../conf/dataimport-schema-no-unique-key.xml    |   18 +-
 .../collection1/conf/dataimport-solrconfig.xml  |   40 +-
 .../conf/contentstream-solrconfig.xml           |   42 +-
 .../conf/dataimport-nodatasource-solrconfig.xml |   42 +-
 .../solr/collection1/conf/dataimport-schema.xml |   10 +-
 .../conf/dataimport-solr_id-schema.xml          |   18 +-
 .../collection1/conf/dataimport-solrconfig.xml  |   42 +-
 .../handler/extraction/SolrContentHandler.java  |    4 +-
 .../extraction/solr/collection1/conf/schema.xml |   18 +-
 .../solr/collection1/conf/solrconfig.xml        |   37 +-
 .../extraction/TestXLSXResponseWriter.java      |    2 +-
 .../conf/solrconfig-languageidentifier.xml      |    4 +-
 .../ltr/model/MultipleAdditiveTreesModel.java   |   16 +-
 .../test-files/solr/collection1/conf/schema.xml |   10 +-
 .../org/apache/solr/ltr/TestLTROnSolrCloud.java |   14 +-
 .../uima/solr/collection1/conf/schema.xml       |   20 +-
 .../uima/solr/collection1/conf/solrconfig.xml   |   25 +-
 .../test-files/uima/uima-tokenizers-schema.xml  |   20 +-
 .../uima/uima-tokenizers-solrconfig.xml         |   15 +-
 .../java/org/apache/solr/response/PageTool.java |    5 +-
 .../src/java/org/apache/solr/cloud/Assign.java  |  137 +-
 .../apache/solr/cloud/CreateCollectionCmd.java  |   96 +-
 .../org/apache/solr/cloud/CreateShardCmd.java   |   74 +-
 .../java/org/apache/solr/cloud/Overseer.java    |    4 +-
 .../cloud/OverseerCollectionMessageHandler.java |   92 +-
 .../java/org/apache/solr/cloud/RestoreCmd.java  |   30 +-
 .../org/apache/solr/cloud/SplitShardCmd.java    |   13 +-
 .../org/apache/solr/cloud/ZkController.java     |   56 +-
 .../cloud/autoscaling/AutoScalingHandler.java   |   13 +-
 .../apache/solr/cloud/rule/ReplicaAssigner.java |   68 +-
 .../org/apache/solr/core/CoreContainer.java     |   58 +-
 .../java/org/apache/solr/core/SolrConfig.java   |   14 +-
 .../src/java/org/apache/solr/core/SolrCore.java |   18 +-
 .../java/org/apache/solr/core/SolrCores.java    |   91 +-
 .../apache/solr/core/SolrResourceLoader.java    |   10 +-
 .../apache/solr/handler/AnalyzeEvaluator.java   |    3 +-
 .../apache/solr/handler/CdcrRequestHandler.java |    6 +-
 .../org/apache/solr/handler/ClassifyStream.java |    3 +-
 .../solr/handler/MoreLikeThisHandler.java       |    2 +-
 .../apache/solr/handler/RequestHandlerBase.java |    1 -
 .../solr/handler/StandardRequestHandler.java    |   19 +-
 .../solr/handler/admin/CollectionsHandler.java  |    6 +-
 .../handler/admin/ConfigSetsHandlerApi.java     |    2 +
 .../solr/handler/component/ExpandComponent.java |    2 +
 .../solr/handler/component/ResponseBuilder.java |    3 +
 .../handler/component/SpellCheckComponent.java  |    4 +-
 .../org/apache/solr/legacy/BBoxStrategy.java    |   13 +-
 .../org/apache/solr/legacy/BBoxValueSource.java |   82 +-
 .../apache/solr/legacy/DistanceValueSource.java |   81 +-
 .../apache/solr/legacy/PointVectorStrategy.java |   17 +-
 .../apache/solr/metrics/SolrMetricReporter.java |   15 +
 .../metrics/reporters/SolrGangliaReporter.java  |    5 -
 .../metrics/reporters/SolrGraphiteReporter.java |    5 -
 .../solr/metrics/reporters/SolrJmxReporter.java |    5 +-
 .../metrics/reporters/SolrSlf4jReporter.java    |    5 -
 .../reporters/solr/SolrClusterReporter.java     |   12 +-
 .../reporters/solr/SolrShardReporter.java       |   12 +-
 .../org/apache/solr/parser/FastCharStream.java  |    2 +-
 .../apache/solr/parser/SolrQueryParserBase.java |    5 +-
 .../transform/GeoTransformerFactory.java        |   33 +-
 .../solr/schema/AbstractSpatialFieldType.java   |   10 +-
 .../java/org/apache/solr/schema/BBoxField.java  |    8 +-
 .../org/apache/solr/schema/CurrencyField.java   |  999 +-----
 .../apache/solr/schema/CurrencyFieldType.java   |  829 +++++
 .../apache/solr/schema/ExternalFileField.java   |   14 -
 .../java/org/apache/solr/schema/FieldType.java  |    4 +-
 .../solr/schema/FileExchangeRateProvider.java   |  252 ++
 .../solr/schema/LatLonPointSpatialField.java    |   46 +-
 .../schema/OpenExchangeRatesOrgProvider.java    |    2 +-
 .../java/org/apache/solr/schema/PointField.java |   28 +
 .../schema/RptWithGeometrySpatialField.java     |   60 +-
 .../apache/solr/schema/ZkIndexSchemaReader.java |  105 +-
 .../org/apache/solr/search/DisMaxQParser.java   |    4 +-
 .../solr/search/ExtendedDismaxQParser.java      |   10 +-
 .../java/org/apache/solr/search/QueryUtils.java |   11 +
 .../apache/solr/search/ValueSourceParser.java   |    8 +-
 .../apache/solr/search/facet/FacetRange.java    |    2 +-
 .../distance/GeoDistValueSourceParser.java      |    8 +-
 .../apache/solr/search/mlt/CloudMLTQParser.java |    3 +-
 .../solr/search/mlt/SimpleMLTQParser.java       |    3 +-
 .../search/stats/ExactSharedStatsCache.java     |   12 +-
 .../solr/search/stats/ExactStatsCache.java      |   19 +-
 .../org/apache/solr/servlet/BaseSolrFilter.java |    3 +
 .../apache/solr/servlet/BaseSolrServlet.java    |    3 +
 .../org/apache/solr/servlet/HttpSolrCall.java   |   13 +-
 .../apache/solr/servlet/SolrDispatchFilter.java |    8 +-
 .../spelling/AbstractLuceneSpellChecker.java    |   12 +-
 .../spelling/ConjunctionSolrSpellChecker.java   |    1 -
 .../solr/spelling/DirectSolrSpellChecker.java   |    1 -
 .../solr/spelling/PossibilityIterator.java      |    2 -
 .../apache/solr/spelling/QueryConverter.java    |    7 +-
 .../org/apache/solr/spelling/ResultEntry.java   |    2 -
 .../apache/solr/spelling/SolrSpellChecker.java  |   13 +-
 .../solr/spelling/SpellCheckCollator.java       |    5 +-
 .../solr/spelling/SpellCheckCorrection.java     |    1 -
 .../apache/solr/spelling/SpellingOptions.java   |    5 +-
 .../solr/spelling/SpellingQueryConverter.java   |    1 -
 .../apache/solr/spelling/SpellingResult.java    |    5 +-
 .../solr/spelling/SuggestQueryConverter.java    |    2 -
 .../java/org/apache/solr/spelling/Token.java    |  175 +
 .../spelling/WordBreakSolrSpellChecker.java     |    1 -
 .../apache/solr/spelling/suggest/Suggester.java |    2 +-
 .../solr/update/StreamingSolrClients.java       |   65 +-
 .../org/apache/solr/util/Java9InitHack.java     |   78 +
 .../src/java/org/apache/solr/util/SolrCLI.java  |   34 +-
 .../org/apache/solr/util/SolrPluginUtils.java   |   12 +-
 .../resources/SystemCollectionSolrConfig.xml    |    2 +-
 .../collection1/conf/bad-error-solrconfig.xml   |    2 +-
 .../collection1/conf/bad-mpf-solrconfig.xml     |    2 +-
 .../bad-schema-currency-ft-amount-suffix.xml    |   34 +
 .../conf/bad-schema-currency-ft-code-suffix.xml |   33 +
 .../conf/bad-schema-currency-ft-oer-norates.xml |    2 +-
 ...ma-currencyfieldtype-bogus-amount-suffix.xml |   34 +
 ...hema-currencyfieldtype-bogus-code-suffix.xml |   35 +
 ...ma-currencyfieldtype-dynamic-multivalued.xml |   36 +
 ...a-currencyfieldtype-ft-bogus-code-in-xml.xml |   41 +
 ...-currencyfieldtype-ft-bogus-default-code.xml |   41 +
 ...-schema-currencyfieldtype-ft-multivalued.xml |   36 +
 ...-schema-currencyfieldtype-ft-oer-norates.xml |   40 +
 ...-currencyfieldtype-missing-amount-suffix.xml |   34 +
 ...ma-currencyfieldtype-missing-code-suffix.xml |   35 +
 ...bad-schema-currencyfieldtype-multivalued.xml |   36 +
 ...schema-currencyfieldtype-wrong-amount-ft.xml |   36 +
 ...d-schema-currencyfieldtype-wrong-code-ft.xml |   35 +
 .../conf/bad-schema-dup-fieldType.xml           |    4 +-
 .../conf/bad-schema-external-filefield.xml      |   25 -
 .../collection1/conf/schema-binaryfield.xml     |   36 -
 .../collection1/conf/schema-copyfield-test.xml  |   34 +-
 .../collection1/conf/schema-customfield.xml     |   29 +-
 .../conf/schema-distrib-interval-faceting.xml   |   32 +-
 .../conf/schema-distributed-missing-sort.xml    |   28 +-
 .../solr/collection1/conf/schema-docValues.xml  |   10 +-
 .../conf/schema-docValuesFaceting.xml           |   35 +-
 .../collection1/conf/schema-docValuesJoin.xml   |   10 +-
 .../conf/schema-docValuesMissing.xml            |   10 +-
 .../collection1/conf/schema-docValuesMulti.xml  |   10 +-
 .../conf/schema-field-sort-values.xml           |    4 +-
 .../collection1/conf/schema-inplace-updates.xml |    6 +-
 .../conf/schema-non-stored-docvalues.xml        |   47 +-
 .../conf/schema-not-required-unique-key.xml     |    1 -
 .../collection1/conf/schema-replication1.xml    |    1 -
 .../collection1/conf/schema-replication2.xml    |    1 -
 .../collection1/conf/schema-required-fields.xml |   34 +-
 .../solr/collection1/conf/schema-reversed.xml   |    5 +-
 .../collection1/conf/schema-sortingresponse.xml |   30 +-
 .../solr/collection1/conf/schema-sorts.xml      |  115 +-
 .../collection1/conf/schema-tokenizer-test.xml  |   21 +-
 .../solr/collection1/conf/schema-trie.xml       |    4 +-
 .../solr/collection1/conf/schema-version-dv.xml |    5 +-
 .../collection1/conf/schema-version-indexed.xml |    5 +-
 .../test-files/solr/collection1/conf/schema.xml |  130 +-
 .../solr/collection1/conf/schema11.xml          |   71 +-
 .../solr/collection1/conf/schema12.xml          |   72 +-
 .../solr/collection1/conf/schema15.xml          |   22 +-
 .../solr/collection1/conf/schema_latest.xml     |   96 +-
 ...dd-schema-fields-update-processor-chains.xml |    2 +-
 .../conf/solrconfig-altdirectory.xml            |    2 +-
 .../conf/solrconfig-analytics-query.xml         |  227 +-
 .../solr/collection1/conf/solrconfig-basic.xml  |    2 +-
 .../conf/solrconfig-blockjoinfacetcomponent.xml |   11 +-
 .../conf/solrconfig-cache-enable-disable.xml    |    4 +-
 .../solr/collection1/conf/solrconfig-cdcr.xml   |    2 +-
 .../conf/solrconfig-cdcrupdatelog.xml           |    2 +-
 .../conf/solrconfig-classification.xml          |    2 +-
 .../conf/solrconfig-collapseqparser.xml         |  125 +-
 .../conf/solrconfig-components-name.xml         |    4 +-
 .../solrconfig-configurerecoverystrategy.xml    |    2 +-
 .../conf/solrconfig-customrecoverystrategy.xml  |    2 +-
 .../conf/solrconfig-delaying-component.xml      |    2 +-
 .../collection1/conf/solrconfig-delpolicy1.xml  |    2 +-
 .../collection1/conf/solrconfig-delpolicy2.xml  |    2 +-
 ...lrconfig-distrib-update-processor-chains.xml |    3 +-
 .../conf/solrconfig-doctransformers.xml         |    4 +-
 .../collection1/conf/solrconfig-elevate.xml     |    2 +-
 .../solrconfig-externalversionconstraint.xml    |    2 +-
 .../conf/solrconfig-functionquery.xml           |    4 +-
 .../solr/collection1/conf/solrconfig-hash.xml   |    4 +-
 .../collection1/conf/solrconfig-headers.xml     |    2 +-
 .../collection1/conf/solrconfig-highlight.xml   |    2 +-
 .../conf/solrconfig-implicitproperties.xml      |    2 +-
 .../conf/solrconfig-infixsuggesters.xml         |    2 +-
 .../conf/solrconfig-logmergepolicyfactory.xml   |    2 +-
 .../conf/solrconfig-managed-schema-test.xml     |    2 +-
 .../conf/solrconfig-managed-schema.xml          |    4 +-
 .../conf/solrconfig-master-throttled.xml        |    8 +-
 .../solr/collection1/conf/solrconfig-master.xml |    8 +-
 .../conf/solrconfig-master1-keepOneBackup.xml   |    4 +-
 .../collection1/conf/solrconfig-master1.xml     |    8 +-
 .../collection1/conf/solrconfig-master2.xml     |    8 +-
 .../collection1/conf/solrconfig-master3.xml     |    8 +-
 .../conf/solrconfig-mergepolicy-defaults.xml    |    2 +-
 .../conf/solrconfig-mergepolicy-legacy.xml      |    2 +-
 .../solrconfig-mergepolicyfactory-nocfs.xml     |    2 +-
 .../collection1/conf/solrconfig-nocache.xml     |    8 +-
 .../conf/solrconfig-nomergepolicyfactory.xml    |    2 +-
 .../collection1/conf/solrconfig-noopregen.xml   |    2 +-
 .../collection1/conf/solrconfig-paramset.xml    |    2 +-
 ...lrconfig-parsing-update-processor-chains.xml |    2 +-
 .../conf/solrconfig-phrasesuggest.xml           |    2 +-
 .../conf/solrconfig-plugcollector.xml           |   28 +-
 .../conf/solrconfig-postingshighlight.xml       |    2 +-
 .../conf/solrconfig-query-parser-init.xml       |    2 +-
 .../conf/solrconfig-querysender-noquery.xml     |    2 +-
 .../collection1/conf/solrconfig-querysender.xml |    8 +-
 .../collection1/conf/solrconfig-repeater.xml    |    8 +-
 .../collection1/conf/solrconfig-reqHandler.incl |    2 +-
 .../conf/solrconfig-response-log-component.xml  |   16 +-
 .../collection1/conf/solrconfig-schemaless.xml  |    2 +-
 .../conf/solrconfig-script-updateprocessor.xml  |    2 +-
 .../conf/solrconfig-searcher-listeners1.xml     |    2 +-
 .../solr/collection1/conf/solrconfig-slave.xml  |    8 +-
 .../solr/collection1/conf/solrconfig-slave1.xml |    8 +-
 .../conf/solrconfig-solcoreproperties.xml       |    2 +-
 .../solrconfig-sortingmergepolicyfactory.xml    |    4 +-
 .../conf/solrconfig-sortingresponse.xml         |    2 +-
 .../collection1/conf/solrconfig-spatial.xml     |    2 +-
 .../conf/solrconfig-spellcheckcomponent.xml     |   12 +-
 .../conf/solrconfig-spellchecker.xml            |    2 +-
 .../solr/collection1/conf/solrconfig-sql.xml    |    4 +-
 ...-suggestercomponent-context-filter-query.xml |    2 +-
 .../conf/solrconfig-suggestercomponent.xml      |    2 +-
 .../collection1/conf/solrconfig-test-misc.xml   |    4 +-
 .../conf/solrconfig-testxmlparser.xml           |    2 +-
 .../solrconfig-tieredmergepolicyfactory.xml     |    2 +-
 .../solr/collection1/conf/solrconfig-tlog.xml   |    5 +-
 ...nfig-uninvertdocvaluesmergepolicyfactory.xml |    2 +-
 .../conf/solrconfig-update-processor-chains.xml |    2 +-
 ...lrconfig-warmer-randommergepolicyfactory.xml |    2 +-
 .../solr/collection1/conf/solrconfig.xml        |   37 +-
 .../conf/solrconfig_SimpleTextCodec.xml         |    2 +-
 .../solr/collection1/conf/solrconfig_codec.xml  |    2 +-
 .../solr/collection1/conf/solrconfig_codec2.xml |    2 +-
 .../solr/collection1/conf/solrconfig_perf.xml   |    5 +-
 .../solr/configsets/_default/conf/currency.xml  |   67 +
 .../solr/configsets/_default/conf/elevate.xml   |   42 +
 .../_default/conf/lang/contractions_ca.txt      |    8 +
 .../_default/conf/lang/contractions_fr.txt      |   15 +
 .../_default/conf/lang/contractions_ga.txt      |    5 +
 .../_default/conf/lang/contractions_it.txt      |   23 +
 .../_default/conf/lang/hyphenations_ga.txt      |    5 +
 .../_default/conf/lang/stemdict_nl.txt          |    6 +
 .../_default/conf/lang/stoptags_ja.txt          |  420 +++
 .../_default/conf/lang/stopwords_ar.txt         |  125 +
 .../_default/conf/lang/stopwords_bg.txt         |  193 ++
 .../_default/conf/lang/stopwords_ca.txt         |  220 ++
 .../_default/conf/lang/stopwords_cz.txt         |  172 +
 .../_default/conf/lang/stopwords_da.txt         |  110 +
 .../_default/conf/lang/stopwords_de.txt         |  294 ++
 .../_default/conf/lang/stopwords_el.txt         |   78 +
 .../_default/conf/lang/stopwords_en.txt         |   54 +
 .../_default/conf/lang/stopwords_es.txt         |  356 ++
 .../_default/conf/lang/stopwords_eu.txt         |   99 +
 .../_default/conf/lang/stopwords_fa.txt         |  313 ++
 .../_default/conf/lang/stopwords_fi.txt         |   97 +
 .../_default/conf/lang/stopwords_fr.txt         |  186 +
 .../_default/conf/lang/stopwords_ga.txt         |  110 +
 .../_default/conf/lang/stopwords_gl.txt         |  161 +
 .../_default/conf/lang/stopwords_hi.txt         |  235 ++
 .../_default/conf/lang/stopwords_hu.txt         |  211 ++
 .../_default/conf/lang/stopwords_hy.txt         |   46 +
 .../_default/conf/lang/stopwords_id.txt         |  359 ++
 .../_default/conf/lang/stopwords_it.txt         |  303 ++
 .../_default/conf/lang/stopwords_ja.txt         |  127 +
 .../_default/conf/lang/stopwords_lv.txt         |  172 +
 .../_default/conf/lang/stopwords_nl.txt         |  119 +
 .../_default/conf/lang/stopwords_no.txt         |  194 ++
 .../_default/conf/lang/stopwords_pt.txt         |  253 ++
 .../_default/conf/lang/stopwords_ro.txt         |  233 ++
 .../_default/conf/lang/stopwords_ru.txt         |  243 ++
 .../_default/conf/lang/stopwords_sv.txt         |  133 +
 .../_default/conf/lang/stopwords_th.txt         |  119 +
 .../_default/conf/lang/stopwords_tr.txt         |  212 ++
 .../_default/conf/lang/userdict_ja.txt          |   29 +
 .../configsets/_default/conf/managed-schema     | 1076 ++++++
 .../solr/configsets/_default/conf/params.json   |   20 +
 .../solr/configsets/_default/conf/protwords.txt |   21 +
 .../configsets/_default/conf/solrconfig.xml     | 1373 ++++++++
 .../solr/configsets/_default/conf/stopwords.txt |   14 +
 .../solr/configsets/_default/conf/synonyms.txt  |   29 +
 .../bad-mergepolicy/conf/solrconfig.xml         |    2 +-
 .../cdcr-source-disabled/conf/schema.xml        |    2 +-
 .../solr/configsets/cdcr-source/conf/schema.xml |    2 +-
 .../configsets/cdcr-source/conf/solrconfig.xml  |    3 +-
 .../solr/configsets/cdcr-target/conf/schema.xml |    2 +-
 .../configsets/cdcr-target/conf/solrconfig.xml  |    3 +-
 .../exitable-directory/conf/solrconfig.xml      |    2 +-
 .../test-files/solr/crazy-path-to-config.xml    |   10 +-
 .../org/apache/solr/BasicFunctionalityTest.java |    6 +-
 .../org/apache/solr/ConvertedLegacyTest.java    |   46 +-
 .../test/org/apache/solr/CursorPagingTest.java  |    2 +
 .../apache/solr/DisMaxRequestHandlerTest.java   |   12 +-
 .../test/org/apache/solr/EchoParamsTest.java    |    4 +-
 .../src/test/org/apache/solr/SampleTest.java    |    2 +-
 .../test/org/apache/solr/SolrInfoBeanTest.java  |    4 +-
 .../apache/solr/TestDistributedGrouping.java    |    7 +
 .../org/apache/solr/TestDistributedSearch.java  |   11 +-
 .../org/apache/solr/TestGroupingSearch.java     |    3 +
 .../core/src/test/org/apache/solr/TestJoin.java |    2 +-
 .../org/apache/solr/TestRandomDVFaceting.java   |   25 +
 .../org/apache/solr/TestRandomFaceting.java     |    3 +
 .../solr/cloud/BaseCdcrDistributedZkTest.java   |   26 +-
 .../solr/cloud/BasicDistributedZk2Test.java     |   29 +-
 .../solr/cloud/BasicDistributedZkTest.java      |  137 +-
 .../test/org/apache/solr/cloud/BasicZkTest.java |    2 +-
 .../solr/cloud/ClusterStateUpdateTest.java      |  175 +-
 .../cloud/CollectionsAPIDistributedZkTest.java  |  125 +-
 .../solr/cloud/CollectionsAPISolrJTest.java     |   40 +-
 .../org/apache/solr/cloud/ForceLeaderTest.java  |    4 +-
 .../FullThrottleStoppableIndexingThread.java    |   31 +-
 .../apache/solr/cloud/HttpPartitionTest.java    |   10 +-
 .../cloud/LeaderElectionIntegrationTest.java    |  294 +-
 .../cloud/LeaderFailoverAfterPartitionTest.java |    2 +-
 .../cloud/LeaderFailureAfterFreshStartTest.java |    4 +-
 .../LeaderInitiatedRecoveryOnCommitTest.java    |    4 +-
 ...aderInitiatedRecoveryOnShardRestartTest.java |    2 +-
 ...verseerCollectionConfigSetProcessorTest.java |   41 +-
 .../org/apache/solr/cloud/OverseerTest.java     |  339 +-
 .../org/apache/solr/cloud/ReplaceNodeTest.java  |    2 +-
 .../solr/cloud/ReplicationFactorTest.java       |    6 +-
 .../solr/cloud/ShardRoutingCustomTest.java      |   12 +
 .../org/apache/solr/cloud/ShardSplitTest.java   |    2 +-
 .../apache/solr/cloud/SolrCloudExampleTest.java |   11 +-
 .../solr/cloud/TestAuthenticationFramework.java |    2 +
 .../cloud/TestCloudJSONFacetJoinDomain.java     |    6 +-
 .../apache/solr/cloud/TestCloudPivotFacet.java  |    7 +-
 .../apache/solr/cloud/TestConfigSetsAPI.java    |   55 +-
 .../solr/cloud/TestMiniSolrCloudCluster.java    |   11 +
 .../cloud/TestOnReconnectListenerSupport.java   |    2 +-
 .../org/apache/solr/cloud/TestPullReplica.java  |    8 +-
 .../cloud/TestRandomRequestDistribution.java    |   10 +-
 .../cloud/TestSolrCloudWithKerberosAlt.java     |    4 +-
 .../solr/cloud/TestStressInPlaceUpdates.java    |   14 -
 .../org/apache/solr/cloud/TestTlogReplica.java  |    8 +-
 .../solr/cloud/UnloadDistributedZkTest.java     |  195 +-
 .../org/apache/solr/cloud/ZkControllerTest.java |   19 +-
 .../autoscaling/AutoScalingHandlerTest.java     |   22 +-
 .../solr/cloud/autoscaling/TestPolicyCloud.java |    6 +-
 .../solr/cloud/hdfs/HdfsNNFailoverTest.java     |    2 +-
 .../HdfsWriteToMultipleCollectionsTest.java     |    2 +-
 .../apache/solr/cloud/hdfs/StressHdfsTest.java  |    4 +-
 .../apache/solr/cloud/rule/RuleEngineTest.java  |    8 +-
 .../solr/core/AlternateDirectoryTest.java       |    2 +-
 .../apache/solr/core/DirectoryFactoryTest.java  |   15 +-
 .../apache/solr/core/RequestHandlersTest.java   |    8 +-
 .../test/org/apache/solr/core/SolrCoreTest.java |    2 +-
 .../test/org/apache/solr/core/TestConfig.java   |    4 +-
 .../org/apache/solr/core/TestCoreContainer.java |    4 +-
 .../org/apache/solr/core/TestCoreDiscovery.java |    3 +-
 .../org/apache/solr/core/TestLazyCores.java     |   44 +-
 .../solr/core/TestQuerySenderListener.java      |    2 +-
 .../solr/core/TestQuerySenderNoQuery.java       |    2 +-
 .../apache/solr/core/TestXIncludeConfig.java    |    2 +-
 .../solr/handler/MoreLikeThisHandlerTest.java   |    1 -
 .../apache/solr/handler/SearchHandlerTest.java  |   80 +
 .../handler/StandardRequestHandlerTest.java     |   88 -
 .../apache/solr/handler/TestConfigReload.java   |    2 +-
 .../handler/ThrowErrorOnInitRequestHandler.java |    4 +
 .../solr/handler/V2ApiIntegrationTest.java      |   19 +-
 .../DistributedFacetPivotLargeTest.java         |    5 +
 .../DistributedFacetPivotLongTailTest.java      |    5 +
 .../DistributedFacetPivotSmallAdvancedTest.java |    5 +
 .../DistributedFacetPivotSmallTest.java         |    5 +
 .../DistributedFacetPivotWhiteBoxTest.java      |    5 +
 .../DistributedSpellCheckComponentTest.java     |   10 +-
 .../DistributedTermsComponentTest.java          |    3 +
 .../component/DummyCustomParamSpellChecker.java |   14 +-
 .../handler/component/FacetPivotSmallTest.java  |    3 +-
 .../component/ResponseLogComponentTest.java     |   12 +-
 .../component/SpellCheckComponentTest.java      |   10 +-
 .../handler/component/StatsComponentTest.java   |    3 +-
 .../handler/component/SuggestComponentTest.java |    2 +-
 .../component/TermVectorComponentTest.java      |    2 +-
 .../handler/component/TermsComponentTest.java   |    2 +-
 ...estDistributedStatsComponentCardinality.java |   22 +-
 .../TestTrackingShardHandlerFactory.java        |    2 +-
 .../highlight/FastVectorHighlighterTest.java    |    2 +-
 .../solr/highlight/HighlighterConfigTest.java   |    2 +-
 .../apache/solr/highlight/HighlighterTest.java  |   84 +-
 .../solr/metrics/SolrMetricManagerTest.java     |    5 +
 .../metrics/SolrMetricsIntegrationTest.java     |    2 +-
 .../metrics/reporters/MockMetricReporter.java   |    3 +
 .../apache/solr/request/SimpleFacetsTest.java   |   12 +-
 .../org/apache/solr/request/TestFaceting.java   |   13 +-
 .../solr/request/TestIntervalFaceting.java      |    4 +-
 .../org/apache/solr/request/TestWriterPerf.java |    2 +
 .../apache/solr/response/TestExportWriter.java  |   24 +-
 .../solr/schema/AbstractCurrencyFieldTest.java  |  426 ---
 .../apache/solr/schema/BadIndexSchemaTest.java  |   46 +-
 .../schema/CurrencyFieldOpenExchangeTest.java   |   27 -
 .../solr/schema/CurrencyFieldTypeTest.java      |  494 +++
 .../solr/schema/CurrencyFieldXmlFileTest.java   |   42 -
 .../apache/solr/schema/DocValuesMultiTest.java  |   10 +-
 .../org/apache/solr/schema/IndexSchemaTest.java |   22 +-
 .../OpenExchangeRatesOrgProviderTest.java       |    2 +-
 .../org/apache/solr/schema/PolyFieldTest.java   |    8 -
 .../apache/solr/schema/SchemaWatcherTest.java   |   56 +
 .../solr/schema/TestCloudManagedSchema.java     |    2 +-
 .../solr/search/TestCollapseQParserPlugin.java  |    2 +
 .../search/TestComplexPhraseQParserPlugin.java  |    8 +-
 .../search/TestGraphTermsQParserPlugin.java     |    2 +
 .../solr/search/TestMaxScoreQueryParser.java    |   10 +-
 .../apache/solr/search/TestSolr4Spatial.java    |   10 +-
 .../apache/solr/search/TestSolrQueryParser.java |   34 +-
 .../org/apache/solr/search/TestTrieFacet.java   |   26 +-
 .../search/facet/TestJsonFacetRefinement.java   |  181 +-
 .../solr/search/facet/TestJsonFacets.java       |    4 +-
 .../solr/search/function/TestFunctionQuery.java |    3 +
 .../function/TestMinMaxOnMultiValuedField.java  |   25 +-
 .../search/join/BlockJoinFacetDistribTest.java  |    2 +-
 .../search/join/BlockJoinFacetRandomTest.java   |    2 +-
 .../search/join/BlockJoinFacetSimpleTest.java   |    2 +-
 .../search/stats/TestDefaultStatsCache.java     |   17 +-
 .../spelling/DirectSolrSpellCheckerTest.java    |    3 +-
 .../spelling/FileBasedSpellCheckerTest.java     |    1 -
 .../spelling/IndexBasedSpellCheckerTest.java    |    1 -
 .../solr/spelling/SimpleQueryConverter.java     |    8 +-
 .../solr/spelling/SpellCheckCollatorTest.java   |   43 +-
 .../SpellCheckCollatorWithCollapseTest.java     |    2 +-
 .../spelling/SpellPossibilityIteratorTest.java  |    2 -
 .../spelling/SpellingQueryConverterTest.java    |    9 +-
 .../spelling/TestSuggestSpellingConverter.java  |   10 +-
 .../spelling/WordBreakSolrSpellCheckerTest.java |   17 +-
 .../apache/solr/update/DocumentBuilderTest.java |    4 +-
 .../solr/update/TestInPlaceUpdatesDistrib.java  |   14 -
 .../update/TestInPlaceUpdatesStandalone.java    |   14 -
 .../org/apache/solr/update/UpdateLogTest.java   |    9 -
 .../apache/solr/util/TestSolrCLIRunExample.java |    2 +-
 .../test/org/apache/solr/util/TestUtils.java    |   23 +
 .../example-DIH/solr/db/conf/managed-schema     |   27 +-
 .../example-DIH/solr/db/conf/solrconfig.xml     |   24 +-
 .../example-DIH/solr/mail/conf/managed-schema   |   27 +-
 .../example-DIH/solr/mail/conf/solrconfig.xml   |   24 +-
 .../example-DIH/solr/solr/conf/currency.xml     |    2 +-
 .../example-DIH/solr/solr/conf/managed-schema   |   27 +-
 .../example-DIH/solr/solr/conf/solrconfig.xml   |   24 +-
 solr/example/files/conf/managed-schema          |    4 +-
 solr/example/files/conf/solrconfig.xml          |   24 +-
 solr/server/README.txt                          |   11 +-
 .../solr/configsets/_default/conf/currency.xml  |   67 +
 .../solr/configsets/_default/conf/elevate.xml   |   42 +
 .../_default/conf/lang/contractions_ca.txt      |    8 +
 .../_default/conf/lang/contractions_fr.txt      |   15 +
 .../_default/conf/lang/contractions_ga.txt      |    5 +
 .../_default/conf/lang/contractions_it.txt      |   23 +
 .../_default/conf/lang/hyphenations_ga.txt      |    5 +
 .../_default/conf/lang/stemdict_nl.txt          |    6 +
 .../_default/conf/lang/stoptags_ja.txt          |  420 +++
 .../_default/conf/lang/stopwords_ar.txt         |  125 +
 .../_default/conf/lang/stopwords_bg.txt         |  193 ++
 .../_default/conf/lang/stopwords_ca.txt         |  220 ++
 .../_default/conf/lang/stopwords_cz.txt         |  172 +
 .../_default/conf/lang/stopwords_da.txt         |  110 +
 .../_default/conf/lang/stopwords_de.txt         |  294 ++
 .../_default/conf/lang/stopwords_el.txt         |   78 +
 .../_default/conf/lang/stopwords_en.txt         |   54 +
 .../_default/conf/lang/stopwords_es.txt         |  356 ++
 .../_default/conf/lang/stopwords_eu.txt         |   99 +
 .../_default/conf/lang/stopwords_fa.txt         |  313 ++
 .../_default/conf/lang/stopwords_fi.txt         |   97 +
 .../_default/conf/lang/stopwords_fr.txt         |  186 +
 .../_default/conf/lang/stopwords_ga.txt         |  110 +
 .../_default/conf/lang/stopwords_gl.txt         |  161 +
 .../_default/conf/lang/stopwords_hi.txt         |  235 ++
 .../_default/conf/lang/stopwords_hu.txt         |  211 ++
 .../_default/conf/lang/stopwords_hy.txt         |   46 +
 .../_default/conf/lang/stopwords_id.txt         |  359 ++
 .../_default/conf/lang/stopwords_it.txt         |  303 ++
 .../_default/conf/lang/stopwords_ja.txt         |  127 +
 .../_default/conf/lang/stopwords_lv.txt         |  172 +
 .../_default/conf/lang/stopwords_nl.txt         |  119 +
 .../_default/conf/lang/stopwords_no.txt         |  194 ++
 .../_default/conf/lang/stopwords_pt.txt         |  253 ++
 .../_default/conf/lang/stopwords_ro.txt         |  233 ++
 .../_default/conf/lang/stopwords_ru.txt         |  243 ++
 .../_default/conf/lang/stopwords_sv.txt         |  133 +
 .../_default/conf/lang/stopwords_th.txt         |  119 +
 .../_default/conf/lang/stopwords_tr.txt         |  212 ++
 .../_default/conf/lang/userdict_ja.txt          |   29 +
 .../configsets/_default/conf/managed-schema     | 1076 ++++++
 .../solr/configsets/_default/conf/params.json   |   20 +
 .../solr/configsets/_default/conf/protwords.txt |   21 +
 .../configsets/_default/conf/solrconfig.xml     | 1373 ++++++++
 .../solr/configsets/_default/conf/stopwords.txt |   14 +
 .../solr/configsets/_default/conf/synonyms.txt  |   29 +
 .../configsets/basic_configs/conf/currency.xml  |   67 -
 .../configsets/basic_configs/conf/elevate.xml   |   42 -
 .../basic_configs/conf/lang/contractions_ca.txt |    8 -
 .../basic_configs/conf/lang/contractions_fr.txt |   15 -
 .../basic_configs/conf/lang/contractions_ga.txt |    5 -
 .../basic_configs/conf/lang/contractions_it.txt |   23 -
 .../basic_configs/conf/lang/hyphenations_ga.txt |    5 -
 .../basic_configs/conf/lang/stemdict_nl.txt     |    6 -
 .../basic_configs/conf/lang/stoptags_ja.txt     |  420 ---
 .../basic_configs/conf/lang/stopwords_ar.txt    |  125 -
 .../basic_configs/conf/lang/stopwords_bg.txt    |  193 --
 .../basic_configs/conf/lang/stopwords_ca.txt    |  220 --
 .../basic_configs/conf/lang/stopwords_cz.txt    |  172 -
 .../basic_configs/conf/lang/stopwords_da.txt    |  110 -
 .../basic_configs/conf/lang/stopwords_de.txt    |  294 --
 .../basic_configs/conf/lang/stopwords_el.txt    |   78 -
 .../basic_configs/conf/lang/stopwords_en.txt    |   54 -
 .../basic_configs/conf/lang/stopwords_es.txt    |  356 --
 .../basic_configs/conf/lang/stopwords_eu.txt    |   99 -
 .../basic_configs/conf/lang/stopwords_fa.txt    |  313 --
 .../basic_configs/conf/lang/stopwords_fi.txt    |   97 -
 .../basic_configs/conf/lang/stopwords_fr.txt    |  186 -
 .../basic_configs/conf/lang/stopwords_ga.txt    |  110 -
 .../basic_configs/conf/lang/stopwords_gl.txt    |  161 -
 .../basic_configs/conf/lang/stopwords_hi.txt    |  235 --
 .../basic_configs/conf/lang/stopwords_hu.txt    |  211 --
 .../basic_configs/conf/lang/stopwords_hy.txt    |   46 -
 .../basic_configs/conf/lang/stopwords_id.txt    |  359 --
 .../basic_configs/conf/lang/stopwords_it.txt    |  303 --
 .../basic_configs/conf/lang/stopwords_ja.txt    |  127 -
 .../basic_configs/conf/lang/stopwords_lv.txt    |  172 -
 .../basic_configs/conf/lang/stopwords_nl.txt    |  119 -
 .../basic_configs/conf/lang/stopwords_no.txt    |  194 --
 .../basic_configs/conf/lang/stopwords_pt.txt    |  253 --
 .../basic_configs/conf/lang/stopwords_ro.txt    |  233 --
 .../basic_configs/conf/lang/stopwords_ru.txt    |  243 --
 .../basic_configs/conf/lang/stopwords_sv.txt    |  133 -
 .../basic_configs/conf/lang/stopwords_th.txt    |  119 -
 .../basic_configs/conf/lang/stopwords_tr.txt    |  212 --
 .../basic_configs/conf/lang/userdict_ja.txt     |   29 -
 .../basic_configs/conf/managed-schema           | 1045 ------
 .../configsets/basic_configs/conf/params.json   |   20 -
 .../configsets/basic_configs/conf/protwords.txt |   21 -
 .../basic_configs/conf/solrconfig.xml           | 1408 --------
 .../configsets/basic_configs/conf/stopwords.txt |   14 -
 .../configsets/basic_configs/conf/synonyms.txt  |   29 -
 .../conf/currency.xml                           |   67 -
 .../data_driven_schema_configs/conf/elevate.xml |   42 -
 .../conf/lang/contractions_ca.txt               |    8 -
 .../conf/lang/contractions_fr.txt               |   15 -
 .../conf/lang/contractions_ga.txt               |    5 -
 .../conf/lang/contractions_it.txt               |   23 -
 .../conf/lang/hyphenations_ga.txt               |    5 -
 .../conf/lang/stemdict_nl.txt                   |    6 -
 .../conf/lang/stoptags_ja.txt                   |  420 ---
 .../conf/lang/stopwords_ar.txt                  |  125 -
 .../conf/lang/stopwords_bg.txt                  |  193 --
 .../conf/lang/stopwords_ca.txt                  |  220 --
 .../conf/lang/stopwords_cz.txt                  |  172 -
 .../conf/lang/stopwords_da.txt                  |  110 -
 .../conf/lang/stopwords_de.txt                  |  294 --
 .../conf/lang/stopwords_el.txt                  |   78 -
 .../conf/lang/stopwords_en.txt                  |   54 -
 .../conf/lang/stopwords_es.txt                  |  356 --
 .../conf/lang/stopwords_eu.txt                  |   99 -
 .../conf/lang/stopwords_fa.txt                  |  313 --
 .../conf/lang/stopwords_fi.txt                  |   97 -
 .../conf/lang/stopwords_fr.txt                  |  186 -
 .../conf/lang/stopwords_ga.txt                  |  110 -
 .../conf/lang/stopwords_gl.txt                  |  161 -
 .../conf/lang/stopwords_hi.txt                  |  235 --
 .../conf/lang/stopwords_hu.txt                  |  211 --
 .../conf/lang/stopwords_hy.txt                  |   46 -
 .../conf/lang/stopwords_id.txt                  |  359 --
 .../conf/lang/stopwords_it.txt                  |  303 --
 .../conf/lang/stopwords_ja.txt                  |  127 -
 .../conf/lang/stopwords_lv.txt                  |  172 -
 .../conf/lang/stopwords_nl.txt                  |  119 -
 .../conf/lang/stopwords_no.txt                  |  194 --
 .../conf/lang/stopwords_pt.txt                  |  253 --
 .../conf/lang/stopwords_ro.txt                  |  233 --
 .../conf/lang/stopwords_ru.txt                  |  243 --
 .../conf/lang/stopwords_sv.txt                  |  133 -
 .../conf/lang/stopwords_th.txt                  |  119 -
 .../conf/lang/stopwords_tr.txt                  |  212 --
 .../conf/lang/userdict_ja.txt                   |   29 -
 .../conf/managed-schema                         | 1069 ------
 .../data_driven_schema_configs/conf/params.json |   20 -
 .../conf/protwords.txt                          |   21 -
 .../conf/solrconfig.xml                         | 1406 --------
 .../conf/stopwords.txt                          |   14 -
 .../conf/synonyms.txt                           |   29 -
 .../conf/managed-schema                         |   27 +-
 .../conf/solrconfig.xml                         |   38 +-
 .../solr-ref-guide/src/charfilterfactories.adoc |   24 +-
 solr/solr-ref-guide/src/collections-api.adoc    | 1044 +++---
 .../src/command-line-utilities.adoc             |    2 +-
 solr/solr-ref-guide/src/content-streams.adoc    |    2 +-
 solr/solr-ref-guide/src/coreadmin-api.adoc      |  276 +-
 .../src/cross-data-center-replication-cdcr.adoc |    6 +-
 solr/solr-ref-guide/src/css/ref-guide.css       |    3 +-
 .../src/distributed-requests.adoc               |    4 +-
 solr/solr-ref-guide/src/faceting.adoc           |    6 +-
 .../src/field-types-included-with-solr.adoc     |    3 +-
 .../solr-ref-guide/src/filter-descriptions.adoc |   32 +-
 solr/solr-ref-guide/src/format-of-solr-xml.adoc |  174 +-
 solr/solr-ref-guide/src/function-queries.adoc   |  410 ++-
 solr/solr-ref-guide/src/graph-traversal.adoc    |  296 +-
 solr/solr-ref-guide/src/highlighting.adoc       |  299 +-
 solr/solr-ref-guide/src/language-analysis.adoc  |    4 +-
 solr/solr-ref-guide/src/other-parsers.adoc      |  169 +-
 solr/solr-ref-guide/src/query-re-ranking.adoc   |   15 +-
 solr/solr-ref-guide/src/response-writers.adoc   |    2 +-
 .../src/rule-based-authorization-plugin.adoc    |   23 +-
 solr/solr-ref-guide/src/schema-api.adoc         |  361 +-
 .../src/solr-control-script-reference.adoc      |  522 +--
 .../src/solr-jdbc-apache-zeppelin.adoc          |    2 +-
 solr/solr-ref-guide/src/stream-sources.adoc     |    4 +-
 .../src/the-dismax-query-parser.adoc            |   16 +-
 .../solr-ref-guide/src/the-terms-component.adoc |    2 +-
 .../src/updating-parts-of-documents.adoc        |    2 +-
 ...store-data-with-the-data-import-handler.adoc |    4 +-
 ...king-with-currencies-and-exchange-rates.adoc |   34 +-
 .../cloud/autoscaling/AddReplicaSuggester.java  |   69 +
 .../client/solrj/cloud/autoscaling/Cell.java    |   69 +
 .../client/solrj/cloud/autoscaling/Clause.java  |  472 +++
 .../cloud/autoscaling/ClusterDataProvider.java  |   52 +
 .../cloud/autoscaling/MoveReplicaSuggester.java |   83 +
 .../client/solrj/cloud/autoscaling/Operand.java |  123 +
 .../client/solrj/cloud/autoscaling/Policy.java  |  521 +++
 .../solrj/cloud/autoscaling/PolicyHelper.java   |   96 +
 .../solrj/cloud/autoscaling/Preference.java     |   89 +
 .../client/solrj/cloud/autoscaling/Row.java     |  120 +
 .../solrj/cloud/autoscaling/package-info.java   |   23 +
 .../solr/client/solrj/impl/CloudSolrClient.java |   94 +-
 .../solrj/impl/ConcurrentUpdateSolrClient.java  |   63 +-
 .../impl/DelegationTokenHttpSolrClient.java     |   13 +
 .../solr/client/solrj/impl/HttpSolrClient.java  |  120 +-
 .../client/solrj/impl/LBHttpSolrClient.java     |   63 +-
 .../solrj/impl/SolrClientDataProvider.java      |    4 +-
 .../solr/client/solrj/io/stream/LetStream.java  |    4 +-
 .../solrj/request/CollectionAdminRequest.java   |   11 +-
 .../cloud/autoscaling/AddReplicaSuggester.java  |   69 -
 .../org/apache/solr/cloud/autoscaling/Cell.java |   57 -
 .../apache/solr/cloud/autoscaling/Clause.java   |  460 ---
 .../cloud/autoscaling/ClusterDataProvider.java  |   52 -
 .../cloud/autoscaling/MoveReplicaSuggester.java |   83 -
 .../apache/solr/cloud/autoscaling/Operand.java  |  123 -
 .../apache/solr/cloud/autoscaling/Policy.java   |  519 ---
 .../solr/cloud/autoscaling/PolicyHelper.java    |   96 -
 .../solr/cloud/autoscaling/Preference.java      |   85 -
 .../org/apache/solr/cloud/autoscaling/Row.java  |  116 -
 .../solr/cloud/autoscaling/package-info.java    |   22 -
 .../apache/solr/common/cloud/DocCollection.java |    2 +-
 .../solr/common/cloud/ReplicaPosition.java      |   55 +
 .../solr/common/cloud/ZkConfigManager.java      |    2 +-
 .../solr/common/params/MoreLikeThisParams.java  |    3 +-
 .../java/org/apache/solr/common/util/Utils.java |   97 +-
 .../solr/common/util/ValidatingJsonMap.java     |    2 +-
 .../collection1/conf/schema-replication1.xml    |    2 +-
 .../solrj/solr/collection1/conf/schema-sql.xml  |   20 +-
 .../solrj/solr/collection1/conf/schema.xml      |   20 +-
 .../solr/collection1/conf/solrconfig-slave1.xml |    8 +-
 .../solr/collection1/conf/solrconfig-sql.xml    |    4 +-
 .../solrj/solr/collection1/conf/solrconfig.xml  |    4 +-
 .../solrj/solr/configsets/ml/conf/schema.xml    |   20 +-
 .../solr/configsets/ml/conf/solrconfig.xml      |    4 +-
 .../solr/configsets/shared/conf/schema.xml      |    2 +-
 .../solr/configsets/shared/conf/solrconfig.xml  |    8 +-
 .../solr/configsets/streaming/conf/schema.xml   |   20 +-
 .../configsets/streaming/conf/solrconfig.xml    |    6 +-
 .../solrj/solr/multicore/core0/conf/schema.xml  |    2 +-
 .../solr/multicore/core0/conf/solrconfig.xml    |    8 +-
 .../solrj/solr/multicore/core1/conf/schema.xml  |    2 +-
 .../solr/multicore/core1/conf/solrconfig.xml    |    8 +-
 .../client/solrj/SolrSchemalessExampleTest.java |    2 +-
 .../solrj/cloud/autoscaling/TestPolicy.java     |  654 ++++
 .../embedded/SolrExampleStreamingTest.java      |   64 +-
 .../client/solrj/impl/CloudSolrClientTest.java  |    2 +-
 .../impl/ConcurrentUpdateSolrClientTest.java    |   36 +-
 .../client/solrj/impl/LBHttpSolrClientTest.java |    2 +-
 .../client/solrj/io/stream/JDBCStreamTest.java  |    2 +
 .../solrj/io/stream/StreamExpressionTest.java   |    2 +-
 .../solr/client/solrj/request/SchemaTest.java   |   23 +-
 .../solr/cloud/autoscaling/TestPolicy.java      |  654 ----
 .../solr/BaseDistributedSearchTestCase.java     |   15 +-
 .../java/org/apache/solr/SolrTestCaseJ4.java    |  171 +-
 .../solr/cloud/AbstractDistribZkTestBase.java   |   18 +-
 .../cloud/AbstractFullDistribZkTestBase.java    |  169 +-
 .../apache/solr/cloud/AbstractZkTestCase.java   |    6 +-
 .../org/apache/solr/util/ExternalPaths.java     |    6 +-
 .../web/js/angular/controllers/replication.js   |    6 +-
 1123 files changed, 63481 insertions(+), 41220 deletions(-)
----------------------------------------------------------------------



[40/58] [abbrv] lucene-solr:jira/solr-10879: LUCENE-7890: The `SortedSetDocValues` and `SortedNumericDocValues` instances returned by the MemoryIndex should support subsequent `advanceExact(0)` invocations.

Posted by ab...@apache.org.
LUCENE-7890: The `SortedSetDocValues` and `SortedNumericDocValues` instances returned by the MemoryIndex should support subsequent `advanceExact(0)` invocations.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/9f096200
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/9f096200
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/9f096200

Branch: refs/heads/jira/solr-10879
Commit: 9f096200b23ca1ff7b9d3c864c27a5b2b707f62a
Parents: c9c0121
Author: Martijn van Groningen <mv...@apache.org>
Authored: Thu Jun 29 15:03:44 2017 +0200
Committer: Martijn van Groningen <mv...@apache.org>
Committed: Thu Jun 29 15:03:44 2017 +0200

----------------------------------------------------------------------
 .../apache/lucene/index/memory/MemoryIndex.java |  6 ++-
 .../lucene/index/memory/TestMemoryIndex.java    | 40 ++++++++++++++++++++
 2 files changed, 44 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9f096200/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
----------------------------------------------------------------------
diff --git a/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java b/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
index 9812a39..fa6b564 100644
--- a/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
+++ b/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
@@ -938,11 +938,11 @@ public class MemoryIndex {
     MemoryDocValuesIterator it = new MemoryDocValuesIterator();
     return new SortedNumericDocValues() {
 
-      int value = 0;
+      int ord = 0;
 
       @Override
       public long nextValue() throws IOException {
-        return values[value++];
+        return values[ord++];
       }
 
       @Override
@@ -952,6 +952,7 @@ public class MemoryIndex {
 
       @Override
       public boolean advanceExact(int target) throws IOException {
+        ord = 0;
         return it.advance(target) == target;
       }
 
@@ -1082,6 +1083,7 @@ public class MemoryIndex {
 
       @Override
       public boolean advanceExact(int target) throws IOException {
+        ord = 0;
         return it.advance(target) == target;
       }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/9f096200/lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndex.java
----------------------------------------------------------------------
diff --git a/lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndex.java b/lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndex.java
index d4ce8f1..a737aad 100644
--- a/lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndex.java
+++ b/lucene/memory/src/test/org/apache/lucene/index/memory/TestMemoryIndex.java
@@ -302,6 +302,46 @@ public class TestMemoryIndex extends LuceneTestCase {
     assertEquals("f", sortedSetDocValues.lookupOrd(2L).utf8ToString());
   }
 
+  public void testDocValues_resetIterator() throws Exception {
+    Document doc = new Document();
+
+    doc.add(new SortedSetDocValuesField("sorted_set", new BytesRef("f")));
+    doc.add(new SortedSetDocValuesField("sorted_set", new BytesRef("d")));
+    doc.add(new SortedSetDocValuesField("sorted_set", new BytesRef("d")));
+    doc.add(new SortedSetDocValuesField("sorted_set", new BytesRef("c")));
+
+    doc.add(new SortedNumericDocValuesField("sorted_numeric", 33L));
+    doc.add(new SortedNumericDocValuesField("sorted_numeric", 32L));
+    doc.add(new SortedNumericDocValuesField("sorted_numeric", 32L));
+    doc.add(new SortedNumericDocValuesField("sorted_numeric", 31L));
+    doc.add(new SortedNumericDocValuesField("sorted_numeric", 30L));
+
+    MemoryIndex mi = MemoryIndex.fromDocument(doc, analyzer);
+    LeafReader leafReader = mi.createSearcher().getIndexReader().leaves().get(0).reader();
+
+    SortedSetDocValues sortedSetDocValues = leafReader.getSortedSetDocValues("sorted_set");
+    assertEquals(3, sortedSetDocValues.getValueCount());
+    for (int times = 0; times < 3; times++) {
+      assertTrue(sortedSetDocValues.advanceExact(0));
+      assertEquals(0L, sortedSetDocValues.nextOrd());
+      assertEquals(1L, sortedSetDocValues.nextOrd());
+      assertEquals(2L, sortedSetDocValues.nextOrd());
+      assertEquals(SortedSetDocValues.NO_MORE_ORDS, sortedSetDocValues.nextOrd());
+    }
+
+    SortedNumericDocValues sortedNumericDocValues = leafReader.getSortedNumericDocValues("sorted_numeric");
+    for (int times = 0; times < 3; times++) {
+      assertTrue(sortedNumericDocValues.advanceExact(0));
+      assertEquals(5, sortedNumericDocValues.docValueCount());
+      assertEquals(30L, sortedNumericDocValues.nextValue());
+      assertEquals(31L, sortedNumericDocValues.nextValue());
+      assertEquals(32L, sortedNumericDocValues.nextValue());
+      assertEquals(32L, sortedNumericDocValues.nextValue());
+      assertEquals(33L, sortedNumericDocValues.nextValue());
+    }
+
+  }
+
   public void testInvalidDocValuesUsage() throws Exception {
     Document doc = new Document();
     doc.add(new NumericDocValuesField("field", 29L));


[25/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10970: Randomize PointFields in all tests using schema-*sort* files

Posted by ab...@apache.org.
SOLR-10970: Randomize PointFields in all tests using schema-*sort* files


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/89abc989
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/89abc989
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/89abc989

Branch: refs/heads/jira/solr-10879
Commit: 89abc989075f3b213ffd84139b0798ced02a32cc
Parents: 82a44be
Author: Chris Hostetter <ho...@apache.org>
Authored: Wed Jun 28 14:52:40 2017 -0700
Committer: Chris Hostetter <ho...@apache.org>
Committed: Wed Jun 28 14:52:40 2017 -0700

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  1 +
 .../conf/schema-distributed-missing-sort.xml    | 28 ++++++++++----------
 .../conf/schema-field-sort-values.xml           |  4 +--
 .../collection1/conf/schema-sortingresponse.xml | 22 +++++++--------
 4 files changed, 28 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89abc989/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index be23b3a..bbda1a3 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -357,6 +357,7 @@ Other Changes
 * SOLR-10807: Randomize Points based numeric field types in (more) test schemas
   - SOLR-10946: Randomize the usage of Points based numerics in solrj test schemas (hossman)
   - SOLR-10947: Randomize the usage of Points based numerics in contrib test schemas (hossman)
+  - SOLR-10970: Randomize PointFields in all tests using schema-*sort* files (hossman)
 
 * SOLR-6807: Changed requestDispatcher's handleSelect to default to false, thus ignoring "qt".
   Simplified configs to not refer to handleSelect or "qt".  Switch all tests that assumed true to assume false

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89abc989/solr/core/src/test-files/solr/collection1/conf/schema-distributed-missing-sort.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-distributed-missing-sort.xml b/solr/core/src/test-files/solr/collection1/conf/schema-distributed-missing-sort.xml
index 13daf46..2187449 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-distributed-missing-sort.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-distributed-missing-sort.xml
@@ -17,29 +17,29 @@
 -->
 
 <schema name="test-distributed-missing-sort" version="1.6">
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="tint" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
 
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="tlong" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
 
-  <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="float" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="tfloat" class="${solr.tests.FloatFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
 
-  <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="double" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="tdouble" class="${solr.tests.DoubleFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
 
-  <fieldType name="date" class="solr.TrieDateField" precisionStep="0"/>
-  <fieldType name="tdate" class="solr.TrieDateField" precisionStep="6"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0"/>
+  <fieldType name="tdate" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="6"/>
 
   <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
 
-  <fieldType name="int_ml" class="solr.TrieIntField" precisionStep="0" sortMissingLast="true"/>
-  <fieldType name="int_mf" class="solr.TrieIntField" precisionStep="0" sortMissingFirst="true"/>
+  <fieldType name="int_ml" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" sortMissingLast="true"/>
+  <fieldType name="int_mf" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" sortMissingFirst="true"/>
 
-  <fieldType name="long_ml" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"
+  <fieldType name="long_ml" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"
              sortMissingLast="true"/>
-  <fieldType name="long_mf" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"
+  <fieldType name="long_mf" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"
              sortMissingFirst="true"/>
 
   <fieldType name="string_ml" class="solr.StrField" sortMissingLast="true"/>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89abc989/solr/core/src/test-files/solr/collection1/conf/schema-field-sort-values.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-field-sort-values.xml b/solr/core/src/test-files/solr/collection1/conf/schema-field-sort-values.xml
index 94485f6..3a9cd3b 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-field-sort-values.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-field-sort-values.xml
@@ -17,8 +17,8 @@
 -->
 
 <schema name="test-custom-comparator" version="1.6">
-  <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
-  <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="int" class="${solr.tests.IntegerFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="long" class="${solr.tests.LongFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
   <fieldType name="string" class="solr.StrField" sortMissingLast="true"/>
   <fieldType name="text" class="solr.TextField">
     <analyzer>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89abc989/solr/core/src/test-files/solr/collection1/conf/schema-sortingresponse.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/schema-sortingresponse.xml b/solr/core/src/test-files/solr/collection1/conf/schema-sortingresponse.xml
index 680a5d3..c45f178 100644
--- a/solr/core/src/test-files/solr/collection1/conf/schema-sortingresponse.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/schema-sortingresponse.xml
@@ -25,7 +25,7 @@
   <!-- format for date is 1995-12-31T23:59:59.999Z and only the fractional
        seconds part (.999) is optional.
     -->
-  <fieldType name="date" class="${solr.tests.DateFieldType}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+  <fieldType name="date" class="${solr.tests.DateFieldType}" docValues="${solr.tests.numeric.dv}" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
   
   <!-- Point Fields -->
   <fieldType name="pint" class="solr.IntPointField" docValues="true"/>
@@ -41,18 +41,18 @@
   <fieldType name="uuid" class="solr.UUIDField"/>
 
   <field name="id" type="string" required="true" indexed="true"/>
-  <field name="floatdv_m" type="${solr.tests.floatClass:pfloat}" indexed="false" stored="false" docValues="true" multiValued="true"/>
-  <field name="intdv_m" type="${solr.tests.intClass:pint}" indexed="false" stored="false" docValues="true" multiValued="true"/>
-  <field name="doubledv_m" type="${solr.tests.doubleClass:pdouble}" indexed="false" stored="false" docValues="true" multiValued="true"/>
-  <field name="longdv_m" type="${solr.tests.longClass:plong}" indexed="false" stored="false" docValues="true" multiValued="true"/>
-  <field name="datedv_m" type="${solr.tests.dateClass:pdate}" indexed="false" stored="false" docValues="true" multiValued="true"/>
+  <field name="floatdv_m" type="float" indexed="false" stored="false" docValues="true" multiValued="true"/>
+  <field name="intdv_m" type="int" indexed="false" stored="false" docValues="true" multiValued="true"/>
+  <field name="doubledv_m" type="double" indexed="false" stored="false" docValues="true" multiValued="true"/>
+  <field name="longdv_m" type="long" indexed="false" stored="false" docValues="true" multiValued="true"/>
+  <field name="datedv_m" type="date" indexed="false" stored="false" docValues="true" multiValued="true"/>
   <field name="stringdv_m" type="string" indexed="false" stored="false" docValues="true" multiValued="true"/>
 
-  <field name="floatdv" type="${solr.tests.floatClass:pfloat}" indexed="false" stored="false" docValues="true"/>
-  <field name="intdv" type="${solr.tests.intClass:pint}" indexed="false" stored="false" docValues="true"/>
-  <field name="doubledv" type="${solr.tests.doubleClass:pdouble}" indexed="false" stored="false" docValues="true"/>
-  <field name="longdv" type="${solr.tests.longClass:plong}" indexed="false" stored="false" docValues="true"/>
-  <field name="datedv" type="${solr.tests.dateClass:pdate}" indexed="false" stored="false" docValues="true"/>
+  <field name="floatdv" type="float" indexed="false" stored="false" docValues="true"/>
+  <field name="intdv" type="int" indexed="false" stored="false" docValues="true"/>
+  <field name="doubledv" type="double" indexed="false" stored="false" docValues="true"/>
+  <field name="longdv" type="long" indexed="false" stored="false" docValues="true"/>
+  <field name="datedv" type="date" indexed="false" stored="false" docValues="true"/>
   <field name="stringdv" type="string" indexed="false" stored="false" docValues="true"/>
 
    <!-- Point fields explicitly -->


[09/58] [abbrv] lucene-solr:jira/solr-10879: SOLR-10123: Upgraded the Analytics Component to version 2.0

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollectorSupplierFactory.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollectorSupplierFactory.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollectorSupplierFactory.java
deleted file mode 100644
index e22362d..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/StatsCollectorSupplierFactory.java
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.statistics;
-
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.function.Supplier;
-
-import org.apache.lucene.queries.function.ValueSource;
-import org.apache.lucene.queries.function.valuesource.BytesRefFieldSource;
-import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
-import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
-import org.apache.lucene.queries.function.valuesource.IntFieldSource;
-import org.apache.lucene.queries.function.valuesource.LongFieldSource;
-import org.apache.solr.analytics.expression.ExpressionFactory;
-import org.apache.solr.analytics.request.ExpressionRequest;
-import org.apache.solr.analytics.util.AnalyticsParams;
-import org.apache.solr.analytics.util.valuesource.AbsoluteValueDoubleFunction;
-import org.apache.solr.analytics.util.valuesource.AddDoubleFunction;
-import org.apache.solr.analytics.util.valuesource.ConstDateSource;
-import org.apache.solr.analytics.util.valuesource.ConstDoubleSource;
-import org.apache.solr.analytics.util.valuesource.ConstStringSource;
-import org.apache.solr.analytics.util.valuesource.DateFieldSource;
-import org.apache.solr.analytics.util.valuesource.DateMathFunction;
-import org.apache.solr.analytics.util.valuesource.DivDoubleFunction;
-import org.apache.solr.analytics.util.valuesource.DualDoubleFunction;
-import org.apache.solr.analytics.util.valuesource.FilterFieldSource;
-import org.apache.solr.analytics.util.valuesource.LogDoubleFunction;
-import org.apache.solr.analytics.util.valuesource.MultiDateFunction;
-import org.apache.solr.analytics.util.valuesource.MultiDoubleFunction;
-import org.apache.solr.analytics.util.valuesource.MultiplyDoubleFunction;
-import org.apache.solr.analytics.util.valuesource.NegateDoubleFunction;
-import org.apache.solr.analytics.util.valuesource.PowDoubleFunction;
-import org.apache.solr.analytics.util.valuesource.ReverseStringFunction;
-import org.apache.solr.analytics.util.valuesource.SingleDoubleFunction;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.solr.schema.FieldType;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.SchemaField;
-import org.apache.solr.schema.StrField;
-import org.apache.solr.schema.TrieDateField;
-import org.apache.solr.schema.TrieDoubleField;
-import org.apache.solr.schema.TrieFloatField;
-import org.apache.solr.schema.TrieIntField;
-import org.apache.solr.schema.TrieLongField;
-import org.apache.solr.search.function.ConcatStringFunction;
-import org.apache.solr.util.DateMathParser;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class StatsCollectorSupplierFactory {
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-  
-  // FunctionTypes
-  final static int NUMBER_TYPE = 0;
-  final static int DATE_TYPE = 1;
-  final static int STRING_TYPE = 2;
-  final static int FIELD_TYPE = 3;
-  final static int FILTER_TYPE = 4;
-  
-  /**
-   * Builds a Supplier that will generate identical arrays of new StatsCollectors.
-   * 
-   * @param schema The Schema being used.
-   * @param exRequests The expression requests to generate a StatsCollector[] from.
-   * @return A Supplier that will return an array of new StatsCollector.
-   */
-  @SuppressWarnings("unchecked")
-  public static Supplier<StatsCollector[]> create(IndexSchema schema, List<ExpressionRequest> exRequests ) {
-    final Map<String, Set<String>> collectorStats =  new TreeMap<>();
-    final Map<String, Set<Integer>> collectorPercs =  new TreeMap<>();
-    final Map<String, ValueSource> collectorSources =  new TreeMap<>();
-    
-    // Iterate through all expression request to make a list of ValueSource strings
-    // and statistics that need to be calculated on those ValueSources.
-    for (ExpressionRequest expRequest : exRequests) {
-      String statExpression = expRequest.getExpressionString();
-      Set<String> statistics = getStatistics(statExpression);
-      if (statistics == null) {
-        continue;
-      }
-      for (String statExp : statistics) {
-        String stat;
-        String operands;
-        try {
-          stat = statExp.substring(0, statExp.indexOf('(')).trim();
-          operands = statExp.substring(statExp.indexOf('(')+1, statExp.lastIndexOf(')')).trim();
-        } catch (Exception e) {
-          throw new SolrException(ErrorCode.BAD_REQUEST,"Unable to parse statistic: ["+statExpression+"]",e);
-        }
-        String[] arguments = ExpressionFactory.getArguments(operands);
-        String source = arguments[0];
-        if (stat.equals(AnalyticsParams.STAT_PERCENTILE)) {
-          // The statistic is a percentile, extra parsing is required
-          if (arguments.length<2) {
-            throw new SolrException(ErrorCode.BAD_REQUEST,"Too few arguments given for "+stat+"() in ["+statExp+"].");
-          } else if (arguments.length>2) {
-            throw new SolrException(ErrorCode.BAD_REQUEST,"Too many arguments given for "+stat+"() in ["+statExp+"].");
-          }
-          source = arguments[1];
-          Set<Integer> percs = collectorPercs.get(source);
-          if (percs == null) {
-            percs = new HashSet<>();
-            collectorPercs.put(source, percs);
-          }
-          try {
-            int perc = Integer.parseInt(arguments[0]);
-            if (perc>0 && perc<100) {
-              percs.add(perc);
-            } else {
-              throw new SolrException(ErrorCode.BAD_REQUEST,"The percentile in ["+statExp+"] is not between 0 and 100, exculsive.");
-            }
-          } catch (NumberFormatException e) {
-            throw new SolrException(ErrorCode.BAD_REQUEST,"\""+arguments[0]+"\" cannot be converted into a percentile.",e);
-          }
-        } else if (arguments.length>1) {
-          throw new SolrException(ErrorCode.BAD_REQUEST,"Too many arguments given for "+stat+"() in ["+statExp+"].");
-        } else if (arguments.length==0) {
-          throw new SolrException(ErrorCode.BAD_REQUEST,"No arguments given for "+stat+"() in ["+statExp+"].");
-        } 
-        // Only unique ValueSources will be made; therefore statistics must be accumulated for
-        // each ValueSource, even across different expression requests
-        Set<String> stats = collectorStats.get(source);
-        if (stats == null) {
-          stats = new HashSet<>();
-          collectorStats.put(source, stats);
-        }
-        if(AnalyticsParams.STAT_PERCENTILE.equals(stat)) {
-          stats.add(stat + "_"+ arguments[0]);
-        } else {
-          stats.add(stat);
-        }
-      }
-    }
-    String[] keys = collectorStats.keySet().toArray(new String[0]);
-    for (String sourceStr : keys) {
-      // Build one ValueSource for each unique value source string
-      ValueSource source = buildSourceTree(schema, sourceStr);
-      if (source == null) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The statistic ["+sourceStr+"] could not be parsed.");
-      }
-      String builtString = source.toString();
-      collectorSources.put(builtString,source);
-      // Replace the user given string with the correctly built string
-      if (!builtString.equals(sourceStr)) {
-        Set<String> stats = collectorStats.remove(sourceStr);
-        if (stats!=null) {
-          collectorStats.put(builtString, stats);
-        }
-        Set<Integer> percs = collectorPercs.remove(sourceStr);
-        if (percs!=null) {
-          collectorPercs.put(builtString, percs);
-        }
-        for (ExpressionRequest er : exRequests) {
-          er.setExpressionString(er.getExpressionString().replace(sourceStr, builtString));
-        }
-      }
-    }
-    if (collectorSources.size()==0) {
-      return new Supplier<StatsCollector[]>() {
-        @Override
-        public StatsCollector[] get() {
-          return new StatsCollector[0];
-        }
-      };
-    }
-    
-    log.info("Stats objects: "+collectorStats.size()+" sr="+collectorSources.size()+" pr="+collectorPercs.size() );
-    
-    // All information is stored in final arrays so that nothing 
-    // has to be computed when the Supplier's get() method is called.
-    final Set<String>[] statsArr = collectorStats.values().toArray(new Set[0]);
-    final ValueSource[] sourceArr = collectorSources.values().toArray(new ValueSource[0]);
-    final boolean[] uniqueBools = new boolean[statsArr.length];
-    final boolean[] medianBools = new boolean[statsArr.length];
-    final boolean[] numericBools = new boolean[statsArr.length];
-    final boolean[] dateBools = new boolean[statsArr.length];
-    final double[][] percsArr = new double[statsArr.length][];
-    final String[][] percsNames = new String[statsArr.length][];
-    for (int count = 0; count < sourceArr.length; count++) {
-      uniqueBools[count] = statsArr[count].contains(AnalyticsParams.STAT_UNIQUE);
-      medianBools[count] = statsArr[count].contains(AnalyticsParams.STAT_MEDIAN);
-      numericBools[count] = statsArr[count].contains(AnalyticsParams.STAT_SUM)||statsArr[count].contains(AnalyticsParams.STAT_SUM_OF_SQUARES)||statsArr[count].contains(AnalyticsParams.STAT_MEAN)||statsArr[count].contains(AnalyticsParams.STAT_STANDARD_DEVIATION);
-      dateBools[count] = (sourceArr[count] instanceof DateFieldSource) | (sourceArr[count] instanceof MultiDateFunction) | (sourceArr[count] instanceof ConstDateSource);
-      Set<Integer> ps = collectorPercs.get(sourceArr[count].toString());
-      if (ps!=null) {
-        percsArr[count] = new double[ps.size()];
-        percsNames[count] = new String[ps.size()];
-        int percCount = 0;
-        for (int p : ps) {
-          percsArr[count][percCount] = p/100.0;
-          percsNames[count][percCount++] = AnalyticsParams.STAT_PERCENTILE+"_"+p;
-        }
-      }
-    }
-    // Making the Supplier
-    return new Supplier<StatsCollector[]>() {
-      public StatsCollector[] get() {
-        StatsCollector[] collectors = new StatsCollector[statsArr.length];
-        for (int count = 0; count < statsArr.length; count++) {
-          if(numericBools[count]){
-            StatsCollector sc = new NumericStatsCollector(sourceArr[count], statsArr[count]);
-            if(uniqueBools[count]) sc = new UniqueStatsCollector(sc);
-            if(medianBools[count]) sc = new MedianStatsCollector(sc);
-            if(percsArr[count]!=null) sc = new PercentileStatsCollector(sc,percsArr[count],percsNames[count]);
-            collectors[count]=sc;
-          } else if (dateBools[count]) {
-            StatsCollector sc = new MinMaxStatsCollector(sourceArr[count], statsArr[count]);
-            if(uniqueBools[count]) sc = new UniqueStatsCollector(sc);
-            if(medianBools[count]) sc = new DateMedianStatsCollector(sc);
-            if(percsArr[count]!=null) sc = new PercentileStatsCollector(sc,percsArr[count],percsNames[count]);
-           collectors[count]=sc;
-          } else {
-            StatsCollector sc = new MinMaxStatsCollector(sourceArr[count], statsArr[count]);
-            if(uniqueBools[count]) sc = new UniqueStatsCollector(sc);
-            if(medianBools[count]) sc = new MedianStatsCollector(sc);
-            if(percsArr[count]!=null) sc = new PercentileStatsCollector(sc,percsArr[count],percsNames[count]);
-            collectors[count]=sc;
-          }
-        }
-        return collectors;
-      }
-    };
-  }
-  
-  /**
-   * Finds the set of statistics that must be computed for the expression.
-   * @param expression The string representation of an expression
-   * @return The set of statistics (sum, mean, median, etc.) found in the expression
-   */
-  public static Set<String> getStatistics(String expression) {
-    HashSet<String> set = new HashSet<>();
-    int firstParen = expression.indexOf('(');
-    if (firstParen>0) {
-      String topOperation = expression.substring(0,firstParen).trim();
-      if (AnalyticsParams.ALL_STAT_SET.contains(topOperation)) {
-        set.add(expression);
-      } else if (!(topOperation.equals(AnalyticsParams.CONSTANT_NUMBER)||topOperation.equals(AnalyticsParams.CONSTANT_DATE)||topOperation.equals(AnalyticsParams.CONSTANT_STRING))) {
-        String operands = expression.substring(firstParen+1, expression.lastIndexOf(')')).trim();
-        String[] arguments = ExpressionFactory.getArguments(operands);
-        for (String argument : arguments) {
-          Set<String> more = getStatistics(argument);
-          if (more!=null) {
-            set.addAll(more);
-          }
-        }
-      }
-    }
-    if (set.size()==0) {
-      return null;
-    }
-    return set;
-  }
-  
-  /**
-   * Builds a Value Source from a given string
-   * 
-   * @param schema The schema being used.
-   * @param expression The string to be turned into an expression.
-   * @return The completed ValueSource
-   */
-  private static ValueSource buildSourceTree(IndexSchema schema, String expression) {
-    return buildSourceTree(schema,expression,FIELD_TYPE);
-  }
-  
-  /**
-   * Builds a Value Source from a given string and a given source type
-   * 
-   * @param schema The schema being used.
-   * @param expression The string to be turned into an expression.
-   * @param sourceType The type of source that must be returned.
-   * @return The completed ValueSource
-   */
-  private static ValueSource buildSourceTree(IndexSchema schema, String expression, int sourceType) {
-    int expressionType = getSourceType(expression);
-    if (sourceType != FIELD_TYPE && expressionType != FIELD_TYPE && 
-        expressionType != FILTER_TYPE && expressionType != sourceType) {
-      return null;
-    }
-    switch (expressionType) {
-    case NUMBER_TYPE : return buildNumericSource(schema, expression);
-    case DATE_TYPE : return buildDateSource(schema, expression);
-    case STRING_TYPE : return buildStringSource(schema, expression);
-    case FIELD_TYPE : return buildFieldSource(schema, expression, sourceType);
-    case FILTER_TYPE : return buildFilterSource(schema, expression.substring(expression.indexOf('(')+1,expression.lastIndexOf(')')), sourceType);
-    default : throw new SolrException(ErrorCode.BAD_REQUEST,expression+" is not a valid operation.");
-    }
-  }
-
-  /**
-   * Determines what type of value source the expression represents.
-   * 
-   * @param expression The expression representing the desired ValueSource
-   * @return NUMBER_TYPE, DATE_TYPE, STRING_TYPE or -1
-   */
-  private static int getSourceType(String expression) {
-    int paren = expression.indexOf('(');
-    if (paren<0) {
-      return FIELD_TYPE;
-    }
-    String operation = expression.substring(0,paren).trim();
-
-    if (AnalyticsParams.NUMERIC_OPERATION_SET.contains(operation)) {
-      return NUMBER_TYPE;
-    } else if (AnalyticsParams.DATE_OPERATION_SET.contains(operation)) {
-      return DATE_TYPE;
-    } else if (AnalyticsParams.STRING_OPERATION_SET.contains(operation)) {
-      return STRING_TYPE;
-    } else if (operation.equals(AnalyticsParams.FILTER)) {
-      return FILTER_TYPE;
-    }
-    throw new SolrException(ErrorCode.BAD_REQUEST,"The operation \""+operation+"\" in ["+expression+"] is not supported.");
-  }
-  
-  /**
-   *  Builds a value source for a given field, making sure that the field fits a given source type.
-   * @param schema the schema
-   * @param expressionString The name of the field to build a Field Source from.
-   * @param sourceType FIELD_TYPE for any type of field, NUMBER_TYPE for numeric fields, 
-   * DATE_TYPE for date fields and STRING_TYPE for string fields.
-   * @return a value source
-   */
-  private static ValueSource buildFieldSource(IndexSchema schema, String expressionString, int sourceType) {
-    SchemaField sf;
-    try {
-      sf = schema.getField(expressionString);
-    } catch (SolrException e) {
-      throw new SolrException(ErrorCode.BAD_REQUEST,"The field "+expressionString+" does not exist.",e);
-    }
-    FieldType type = sf.getType();
-    if ( type instanceof TrieIntField) {
-      if (sourceType!=NUMBER_TYPE&&sourceType!=FIELD_TYPE) {
-        return null;
-      }
-      return new IntFieldSource(expressionString) {
-        public String description() {
-          return field;
-        }
-      };
-    } else if (type instanceof TrieLongField) {
-      if (sourceType!=NUMBER_TYPE&&sourceType!=FIELD_TYPE) {
-        return null;
-      }
-      return new LongFieldSource(expressionString) {
-        public String description() {
-          return field;
-        }
-      };
-    } else if (type instanceof TrieFloatField) {
-      if (sourceType!=NUMBER_TYPE&&sourceType!=FIELD_TYPE) {
-        return null;
-      }
-      return new FloatFieldSource(expressionString) {
-        public String description() {
-          return field;
-        }
-      };
-    } else if (type instanceof TrieDoubleField) {
-      if (sourceType!=NUMBER_TYPE&&sourceType!=FIELD_TYPE) {
-        return null;
-      }
-      return new DoubleFieldSource(expressionString) {
-        public String description() {
-          return field;
-        }
-      };
-    } else if (type instanceof TrieDateField) {
-      if (sourceType!=DATE_TYPE&&sourceType!=FIELD_TYPE) {
-        return null;
-      }
-      return new DateFieldSource(expressionString) {
-        public String description() {
-          return field;
-        }
-      };
-    } else if (type instanceof StrField) {
-      if (sourceType!=STRING_TYPE&&sourceType!=FIELD_TYPE) {
-        return null;
-      }
-      return new BytesRefFieldSource(expressionString) {
-        public String description() {
-          return field;
-        }
-      };
-    }
-    throw new SolrException(ErrorCode.BAD_REQUEST, type.toString()+" is not a supported field type in Solr Analytics.");
-  }
-  
-  /**
-   * Builds a default is missing source that wraps a given source. A missing value is required for all 
-   * non-field value sources.
-   * @param schema the schema
-   * @param expressionString The name of the field to build a Field Source from.
-   * @param sourceType FIELD_TYPE for any type of field, NUMBER_TYPE for numeric fields, 
-   * DATE_TYPE for date fields and STRING_TYPE for string fields.
-   * @return a value source
-   */
-  @SuppressWarnings("deprecation")
-  private static ValueSource buildFilterSource(IndexSchema schema, String expressionString, int sourceType) {
-    String[] arguments = ExpressionFactory.getArguments(expressionString);
-    if (arguments.length!=2) {
-      throw new SolrException(ErrorCode.BAD_REQUEST,"Invalid arguments were given for \""+AnalyticsParams.FILTER+"\".");
-    }
-    ValueSource delegateSource = buildSourceTree(schema, arguments[0], sourceType);
-    if (delegateSource==null) {
-      return null;
-    }
-    Object defaultObject;
-
-    ValueSource src = delegateSource;
-    if (delegateSource instanceof FilterFieldSource) {
-      src = ((FilterFieldSource)delegateSource).getRootSource();
-    }
-    if ( src instanceof IntFieldSource) {
-      try {
-        defaultObject = new Integer(arguments[1]);
-      } catch (NumberFormatException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The filter value "+arguments[1]+" cannot be converted into an integer.",e);
-      }
-    } else if ( src instanceof DateFieldSource || src instanceof MultiDateFunction) {
-      defaultObject = DateMathParser.parseMath(null, arguments[1]);
-    } else if ( src instanceof LongFieldSource ) {
-      try {
-        defaultObject = new Long(arguments[1]);
-      } catch (NumberFormatException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The filter value "+arguments[1]+" cannot be converted into a long.",e);
-      }
-    } else if ( src instanceof FloatFieldSource ) {
-      try {
-        defaultObject = new Float(arguments[1]);
-      } catch (NumberFormatException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The filter value "+arguments[1]+" cannot be converted into a float.",e);
-      }
-    } else if ( src instanceof DoubleFieldSource || src instanceof SingleDoubleFunction ||
-                src instanceof DualDoubleFunction|| src instanceof MultiDoubleFunction) {
-      try {
-        defaultObject = new Double(arguments[1]);
-      } catch (NumberFormatException e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The filter value "+arguments[1]+" cannot be converted into a double.",e);
-      }
-    } else {
-      defaultObject = arguments[1];
-    }
-    return new FilterFieldSource(delegateSource,defaultObject);
-  } 
-  
-  /**
-   * Recursively parses and breaks down the expression string to build a numeric ValueSource.
-   * 
-   * @param schema The schema to pull fields from.
-   * @param expressionString The expression string to build a ValueSource from.
-   * @return The value source represented by the given expressionString
-   */
-  private static ValueSource buildNumericSource(IndexSchema schema, String expressionString) {
-    int paren = expressionString.indexOf('(');
-    String[] arguments;
-    String operands;
-    if (paren<0) {
-      return buildFieldSource(schema,expressionString,NUMBER_TYPE);
-    } else {
-      try {
-        operands = expressionString.substring(paren+1, expressionString.lastIndexOf(')')).trim();
-      } catch (Exception e) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"Missing closing parenthesis in ["+expressionString+"]");
-      }
-      arguments = ExpressionFactory.getArguments(operands);
-    }
-    String operation = expressionString.substring(0, paren).trim();
-    if (operation.equals(AnalyticsParams.CONSTANT_NUMBER)) {
-      if (arguments.length!=1) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The constant number declaration ["+expressionString+"] does not have exactly 1 argument.");
-      }
-      return new ConstDoubleSource(Double.parseDouble(arguments[0]));
-    } else if (operation.equals(AnalyticsParams.NEGATE)) {
-      if (arguments.length!=1) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The negate operation ["+expressionString+"] does not have exactly 1 argument.");
-      }
-      ValueSource argSource = buildNumericSource(schema, arguments[0]);
-      if (argSource==null) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The operation \""+AnalyticsParams.NEGATE+"\" requires a numeric field or operation as argument. \""+arguments[0]+"\" is not a numeric field or operation.");
-      }
-      return new NegateDoubleFunction(argSource);
-    }  else if (operation.equals(AnalyticsParams.ABSOLUTE_VALUE)) {
-      if (arguments.length!=1) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The absolute value operation ["+expressionString+"] does not have exactly 1 argument.");
-      }
-      ValueSource argSource = buildNumericSource(schema, arguments[0]);
-      if (argSource==null) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The operation \""+AnalyticsParams.NEGATE+"\" requires a numeric field or operation as argument. \""+arguments[0]+"\" is not a numeric field or operation.");
-      }
-      return new AbsoluteValueDoubleFunction(argSource);
-    } else if (operation.equals(AnalyticsParams.FILTER)) {
-      return buildFilterSource(schema, operands, NUMBER_TYPE);
-    }
-    List<ValueSource> subExpressions = new ArrayList<>();
-    for (String argument : arguments) {
-      ValueSource argSource = buildNumericSource(schema, argument);
-      if (argSource == null) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The operation \""+operation+"\" requires numeric fields or operations as arguments. \""+argument+"\" is not a numeric field or operation.");
-      }
-      subExpressions.add(argSource);
-    }
-    if (operation.equals(AnalyticsParams.ADD)) {
-      return new AddDoubleFunction(subExpressions.toArray(new ValueSource[0]));
-    } else if (operation.equals(AnalyticsParams.MULTIPLY)) {
-      return new MultiplyDoubleFunction(subExpressions.toArray(new ValueSource[0]));
-    } else if (operation.equals(AnalyticsParams.DIVIDE)) {
-      if (subExpressions.size()!=2) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The divide operation ["+expressionString+"] does not have exactly 2 arguments.");
-      }
-      return new DivDoubleFunction(subExpressions.get(0),subExpressions.get(1));
-    } else if (operation.equals(AnalyticsParams.POWER)) {
-      if (subExpressions.size()!=2) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The power operation ["+expressionString+"] does not have exactly 2 arguments.");
-      }
-      return new PowDoubleFunction(subExpressions.get(0),subExpressions.get(1));
-    } else if (operation.equals(AnalyticsParams.LOG)) {
-      if (subExpressions.size()!=2) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The log operation ["+expressionString+"] does not have exactly 2 arguments.");
-      }
-      return new LogDoubleFunction(subExpressions.get(0), subExpressions.get(1));
-    } 
-    if (AnalyticsParams.DATE_OPERATION_SET.contains(operation)||AnalyticsParams.STRING_OPERATION_SET.contains(operation)) {
-      return null;
-    }
-    throw new SolrException(ErrorCode.BAD_REQUEST,"The operation ["+expressionString+"] is not supported.");
-  }
-
-  
-  /**
-   * Recursively parses and breaks down the expression string to build a date ValueSource.
-   * 
-   * @param schema The schema to pull fields from.
-   * @param expressionString The expression string to build a ValueSource from.
-   * @return The value source represented by the given expressionString
-   */
-  @SuppressWarnings("deprecation")
-  private static ValueSource buildDateSource(IndexSchema schema, String expressionString) {
-    int paren = expressionString.indexOf('(');
-    String[] arguments;
-    if (paren<0) {
-      return buildFieldSource(schema, expressionString, DATE_TYPE);
-    } else {
-      arguments = ExpressionFactory.getArguments(expressionString.substring(paren+1, expressionString.lastIndexOf(')')).trim());
-    }
-    String operands = arguments[0];
-    String operation = expressionString.substring(0, paren).trim();
-    if (operation.equals(AnalyticsParams.CONSTANT_DATE)) {
-      if (arguments.length!=1) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"The constant date declaration ["+expressionString+"] does not have exactly 1 argument.");
-      }
-      return new ConstDateSource(DateMathParser.parseMath(null, operands));
-    } else if (operation.equals(AnalyticsParams.FILTER)) {
-      return buildFilterSource(schema, operands, DATE_TYPE);
-    }
-    if (operation.equals(AnalyticsParams.DATE_MATH)) {
-      List<ValueSource> subExpressions = new ArrayList<>();
-      boolean first = true;
-      for (String argument : arguments) {
-        ValueSource argSource;
-        if (first) {
-          first = false;
-          argSource = buildDateSource(schema, argument);
-          if (argSource == null) {
-            throw new SolrException(ErrorCode.BAD_REQUEST,"\""+AnalyticsParams.DATE_MATH+"\" requires the first argument be a date operation or field. ["+argument+"] is not a date operation or field.");
-          }
-        } else {
-          argSource = buildStringSource(schema, argument);
-          if (argSource == null) {
-            throw new SolrException(ErrorCode.BAD_REQUEST,"\""+AnalyticsParams.DATE_MATH+"\" requires that all arguments except the first be string operations. ["+argument+"] is not a string operation.");
-          }
-        }
-        subExpressions.add(argSource);
-      }
-      return new DateMathFunction(subExpressions.toArray(new ValueSource[0]));
-    }
-    if (AnalyticsParams.NUMERIC_OPERATION_SET.contains(operation)||AnalyticsParams.STRING_OPERATION_SET.contains(operation)) {
-      return null;
-    }
-    throw new SolrException(ErrorCode.BAD_REQUEST,"The operation ["+expressionString+"] is not supported.");
-  }
-
-  
-  /**
-   * Recursively parses and breaks down the expression string to build a string ValueSource.
-   * 
-   * @param schema The schema to pull fields from.
-   * @param expressionString The expression string to build a ValueSource from.
-   * @return The value source represented by the given expressionString
-   */
-  private static ValueSource buildStringSource(IndexSchema schema, String expressionString) {
-    int paren = expressionString.indexOf('(');
-    String[] arguments;
-    if (paren<0) {
-      return buildFieldSource(schema, expressionString, FIELD_TYPE);
-    } else {
-      arguments = ExpressionFactory.getArguments(expressionString.substring(paren+1, expressionString.lastIndexOf(')')).trim());
-    }
-    String operands = arguments[0];
-    String operation = expressionString.substring(0, paren).trim();
-    if (operation.equals(AnalyticsParams.CONSTANT_STRING)) {
-      operands = expressionString.substring(paren+1, expressionString.lastIndexOf(')'));
-      return new ConstStringSource(operands);
-    } else if (operation.equals(AnalyticsParams.FILTER)) {
-      return buildFilterSource(schema,operands,FIELD_TYPE);
-    } else if (operation.equals(AnalyticsParams.REVERSE)) {
-      if (arguments.length!=1) {
-        throw new SolrException(ErrorCode.BAD_REQUEST,"\""+AnalyticsParams.REVERSE+"\" requires exactly one argument. The number of arguments in "+expressionString+" is not 1.");
-      }
-      return new ReverseStringFunction(buildStringSource(schema, operands));
-    }
-    List<ValueSource> subExpressions = new ArrayList<>();
-    for (String argument : arguments) {
-      subExpressions.add(buildSourceTree(schema, argument));
-    }
-    if (operation.equals(AnalyticsParams.CONCATENATE)) {
-      return new ConcatStringFunction(subExpressions.toArray(new ValueSource[0]));
-    } 
-    if (AnalyticsParams.NUMERIC_OPERATION_SET.contains(operation)) {
-      return buildNumericSource(schema, expressionString);
-    } else if (AnalyticsParams.DATE_OPERATION_SET.contains(operation)) {
-      return buildDateSource(schema, expressionString);
-    }
-    throw new SolrException(ErrorCode.BAD_REQUEST,"The operation ["+expressionString+"] is not supported.");
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/UniqueStatsCollector.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/UniqueStatsCollector.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/UniqueStatsCollector.java
deleted file mode 100644
index 461b0f4..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/UniqueStatsCollector.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.analytics.statistics;
-
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * <code>UniqueValueCounter</code> computes the number of unique values.
- */
-public class UniqueStatsCollector extends AbstractDelegatingStatsCollector{
-  private final Set<Object> uniqueValues = new HashSet<>();
-  
-  public UniqueStatsCollector(StatsCollector delegate) {
-    super(delegate);
-  }
-  
-  @Override
-  public void collect(int doc) throws IOException {
-    super.collect(doc);
-    if (value.exists) {
-      uniqueValues.add(value.toObject());
-    }
-  }
-
-  @Override
-  public Comparable getStat(String stat) {
-    if (stat.equals("unique")) {
-      return new Long(uniqueValues.size());
-    }
-    return delegate.getStat(stat);
-  }
-
-  @Override
-  public void compute() {
-    delegate.compute();
-  }
-}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/package-info.java
deleted file mode 100644
index 90fa12d..0000000
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/statistics/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-/** 
- * Statistics collectors reduce a list of Objects to a single value. Most implementations reduce a list to a statistic on that list.
- */
-package org.apache.solr.analytics.statistics;
-
-
-

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardRequestManager.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardRequestManager.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardRequestManager.java
new file mode 100644
index 0000000..f65e58f
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardRequestManager.java
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import org.apache.solr.analytics.AnalyticsRequestManager;
+import org.apache.solr.analytics.AnalyticsRequestParser;
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
+import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.cloud.ClusterState;
+import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.common.cloud.ZkCoreNodeProps;
+import org.apache.solr.common.cloud.ZkStateReader;
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.ExecutorUtil;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SolrjNamedThreadFactory;
+import org.apache.solr.handler.AnalyticsHandler;
+import org.apache.solr.handler.component.AnalyticsComponent;
+import org.apache.solr.response.AnalyticsShardResponseWriter;
+
+/**
+ * This class manages the requesting of shard responses from all shards in the queried collection.
+ * 
+ * <p>
+ * Shard Requests are sent to the {@link AnalyticsHandler} instead of the {@link AnalyticsComponent},
+ * which is the entrance to the analytics component for all client requests.
+ */
+public class AnalyticsShardRequestManager {
+  private final SolrParams params;
+  protected transient CloudSolrClient cloudSolrClient;
+  protected transient List<String> replicaUrls;
+  
+  /**
+   * All shards responses, which are received in parallel, are funneled into the manager.
+   * So the manager must be transient.
+   */
+  private transient final AnalyticsRequestManager manager;
+
+  public AnalyticsShardRequestManager(SolrParams params, AnalyticsRequestManager manager) {
+    this.manager = manager;
+    this.params = loadParams(params, manager.analyticsRequest);
+  }
+
+  /**
+   * Send out shard requests to each shard in the given collection.
+   * 
+   * @param collection that is being queried
+   * @param zkHost of the solr cloud hosting the collection
+   * @throws IOException if an exception occurs while picking shards or sending requests
+   */
+  public void sendRequests(String collection, String zkHost) throws IOException {
+    this.replicaUrls = new ArrayList<>();
+    this.cloudSolrClient = new Builder()
+        .withZkHost(zkHost)
+        .build();
+    try {
+      this.cloudSolrClient.connect();
+      pickShards(collection);
+      streamFromShards();
+    } finally {
+      cloudSolrClient.close();
+    }
+  }
+  
+  /**
+   * Pick one replica from each shard to send the shard requests to.
+   * 
+   * @param collection that is being queried
+   * @throws IOException if an exception occurs while finding replicas
+   */
+  protected void pickShards(String collection) throws IOException {
+    try {
+
+      ZkStateReader zkStateReader = cloudSolrClient.getZkStateReader();
+      ClusterState clusterState = zkStateReader.getClusterState();
+      Set<String> liveNodes = clusterState.getLiveNodes();
+
+      Collection<Slice> slices = clusterState.getCollection(collection).getActiveSlices();
+
+      for(Slice slice : slices) {
+        Collection<Replica> replicas = slice.getReplicas();
+        List<Replica> shuffler = new ArrayList<>();
+        for(Replica replica : replicas) {
+          if(replica.getState() == Replica.State.ACTIVE && liveNodes.contains(replica.getNodeName()))
+          shuffler.add(replica);
+        }
+
+        Collections.shuffle(shuffler, new Random());
+        Replica rep = shuffler.get(0);
+        ZkCoreNodeProps zkProps = new ZkCoreNodeProps(rep);
+        String url = zkProps.getCoreUrl();
+        replicaUrls.add(url);
+      }
+    } catch (Exception e) {
+      throw new IOException(e);
+    }
+  }
+
+  /**
+   * Send a shard request to each chosen replica, streaming 
+   * the responses back to the {@link AnalyticsRequestManager}
+   * through the {@link AnalyticsShardResponseParser}.
+   * <p>
+   * A thread pool is used to send the requests simultaneously, 
+   * and therefore importing the results is also done in parallel.
+   * However the manager can only import one shard response at a time,
+   * so the {@link AnalyticsShardResponseParser} is blocked until each import is finished.
+   * 
+   * @throws IOException if an exception occurs while sending requests.
+   */
+  private void streamFromShards() throws IOException {
+    ExecutorService service = ExecutorUtil.newMDCAwareCachedThreadPool(new SolrjNamedThreadFactory("SolrAnalyticsStream"));
+    List<Future<SolrException>> futures = new ArrayList<>();
+    List<AnalyticsShardRequester> openers = new ArrayList<>();
+    for (String replicaUrl : replicaUrls) {
+      AnalyticsShardRequester opener = new AnalyticsShardRequester(replicaUrl);
+      openers.add(opener);
+      Future<SolrException> future = service.submit(opener);
+      futures.add(future);
+    }
+    try {
+      for (Future<SolrException> f : futures) {
+        SolrException e = f.get();
+        if (e != null) {
+          throw e;
+        }
+      }
+    } catch (InterruptedException e1) {
+      throw new RuntimeException(e1);
+    } catch (ExecutionException e1) {
+      throw new RuntimeException(e1);
+    } finally {
+      service.shutdown();
+      for (AnalyticsShardRequester opener : openers) {
+        opener.close();
+      }
+    }
+  }
+
+  /**
+   * Create a {@link SolrParams} for shard requests. The only parameters that are copied over from
+   * the original search request are "q" and "fq".
+   * 
+   * <p>
+   * The request is sent to the {@link AnalyticsHandler} and the output will be encoded in the analytics bit-stream
+   * format generated by the {@link AnalyticsShardResponseWriter}.
+   * 
+   * @param paramsIn of the original solr request
+   * @param analyticsRequest string representation
+   * @return shard request SolrParams
+   */
+  private static SolrParams loadParams(SolrParams paramsIn, String analyticsRequest) {
+    ModifiableSolrParams solrParams = new ModifiableSolrParams();
+
+    solrParams.add(CommonParams.QT, AnalyticsHandler.NAME);
+    solrParams.add(CommonParams.WT, AnalyticsShardResponseWriter.NAME);
+    solrParams.add(CommonParams.Q, paramsIn.get(CommonParams.Q));
+    solrParams.add(CommonParams.FQ, paramsIn.getParams(CommonParams.FQ));
+    solrParams.add(AnalyticsRequestParser.analyticsParamName, analyticsRequest);
+
+    return solrParams;
+  }
+
+  /**
+   * A class that opens a connection to a given solr instance, a selected replica of the queried collection,
+   * and sends a analytics request to the {@link AnalyticsHandler}. The results are processed by an
+   * {@link AnalyticsShardResponseParser} constructed with the {@link AnalyticsRequestManager} passed
+   * to the parent {@link AnalyticsShardRequestManager}.
+   */
+  protected class AnalyticsShardRequester implements Callable<SolrException> {
+    private String baseUrl;
+    HttpSolrClient client;
+
+    /**
+     * Create a requester for analytics shard data.
+     * 
+     * @param baseUrl of the replica to send the request to
+     */
+    public AnalyticsShardRequester(String baseUrl) {
+      this.baseUrl = baseUrl;
+      this.client = null;
+    }
+    
+    /**
+     * Send the analytics request to the shard.
+     */
+    @Override
+    public SolrException call() throws Exception {
+      client = new HttpSolrClient.Builder(baseUrl).build();
+      QueryRequest query = new QueryRequest( params );
+      query.setPath(AnalyticsHandler.NAME);
+      query.setResponseParser(new AnalyticsShardResponseParser(manager));
+      query.setMethod(SolrRequest.METHOD.POST);
+      NamedList<Object> exception = client.request(query);
+      if (exception.size() > 0) {
+        return (SolrException)exception.getVal(0);
+      }
+      return null;
+    }
+    
+    /**
+     * Close the connection to the solr instance.
+     * 
+     * @throws IOException if an error occurs while closing the connection
+     */
+    public void close() throws IOException {
+      if (client != null) {
+        client.close();
+      }
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardResponseParser.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardResponseParser.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardResponseParser.java
new file mode 100644
index 0000000..c7f4094
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardResponseParser.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream;
+
+import org.apache.solr.analytics.AnalyticsRequestManager;
+import org.apache.solr.client.solrj.ResponseParser;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.handler.AnalyticsHandler;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.Reader;
+
+/**
+ * This parser initiates a merge of an Analytics Shard Response, sent from the {@link AnalyticsHandler}.
+ * 
+ * The input stream is immediately sent to the given {@link AnalyticsRequestManager} to merge.
+ */
+public class AnalyticsShardResponseParser extends ResponseParser {
+  public static final String BINARY_CONTENT_TYPE = "application/octet-stream";
+  public static final String STREAM = "application/octet-stream";
+  
+  private final AnalyticsRequestManager manager;
+
+  /**
+   * 
+   * @param manager the manager of the current Analytics Request, will manage the merging of shard data
+   */
+  public AnalyticsShardResponseParser(AnalyticsRequestManager manager) {
+    this.manager = manager;
+  }
+
+  @Override
+  public String getWriterType() {
+    return "analytics_shard_stream";
+  }
+
+  @Override
+  public NamedList<Object> processResponse(InputStream body, String encoding) {
+    DataInputStream input = new DataInputStream(body);
+    //check to see if the response is an exception
+    NamedList<Object> exception = new NamedList<>();
+    try {
+      if (input.readBoolean()) {
+        manager.importShardData(input);
+      } else {
+        exception.add("Exception", new ObjectInputStream(input).readObject());
+      }
+    } catch (IOException e) {
+      exception.add("Exception", new SolrException(ErrorCode.SERVER_ERROR, "Couldn't process analytics shard response", e));
+    } catch (ClassNotFoundException e1) {
+      throw new RuntimeException(e1);
+    }
+    return exception;
+  }
+
+  @Override
+  public String getContentType() {
+    return BINARY_CONTENT_TYPE;
+  }
+
+  @Override
+  public String getVersion() {
+    return "1";
+  }
+
+  @Override
+  public NamedList<Object> processResponse(Reader reader) {
+    throw new RuntimeException("Cannot handle character stream");
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/package-info.java
new file mode 100644
index 0000000..31563cd
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Classes to manage the I/O between shards.
+ */
+package org.apache.solr.analytics.stream;
+
+

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanArrayReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanArrayReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanArrayReservation.java
new file mode 100644
index 0000000..b0ca38d
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanArrayReservation.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.BooleanSupplier;
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.BooleanDataArrayReader;
+import org.apache.solr.analytics.stream.reservation.write.BooleanDataArrayWriter;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+
+public class BooleanArrayReservation extends ReductionDataArrayReservation<BooleanConsumer, BooleanSupplier> {
+  
+  public BooleanArrayReservation(BooleanConsumer applier, IntConsumer sizeApplier, BooleanSupplier extractor, IntSupplier sizeExtractor) {
+    super(applier, sizeApplier, extractor, sizeExtractor);
+  }
+
+  @Override
+  public BooleanDataArrayReader createReadStream(DataInput input) {
+    return new BooleanDataArrayReader(input, applier, sizeApplier);
+  }
+
+  @Override
+  public BooleanDataArrayWriter createWriteStream(DataOutput output) {
+    return new BooleanDataArrayWriter(output, extractor, sizeExtractor);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanCheckedReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanCheckedReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanCheckedReservation.java
new file mode 100644
index 0000000..1c3d9ec
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanCheckedReservation.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.BooleanSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.BooleanCheckedDataReader;
+import org.apache.solr.analytics.stream.reservation.write.BooleanCheckedDataWriter;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+
+public class BooleanCheckedReservation extends ReductionCheckedDataReservation<BooleanConsumer, BooleanSupplier> {
+  
+  public BooleanCheckedReservation(BooleanConsumer applier, BooleanSupplier extractor, BooleanSupplier exists) {
+    super(applier, extractor, exists);
+  }
+
+  @Override
+  public BooleanCheckedDataReader createReadStream(DataInput input) {
+    return new BooleanCheckedDataReader(input, applier);
+  }
+
+  @Override
+  public BooleanCheckedDataWriter createWriteStream(DataOutput output) {
+    return new BooleanCheckedDataWriter(output, extractor, exists);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanReservation.java
new file mode 100644
index 0000000..2e6b718
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/BooleanReservation.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.BooleanSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.BooleanDataReader;
+import org.apache.solr.analytics.stream.reservation.write.BooleanDataWriter;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+
+public class BooleanReservation extends ReductionDataReservation<BooleanConsumer, BooleanSupplier> {
+  
+  public BooleanReservation(BooleanConsumer applier, BooleanSupplier extractor) {
+    super(applier, extractor);
+  }
+
+  @Override
+  public BooleanDataReader createReadStream(DataInput input) {
+    return new BooleanDataReader(input, applier);
+  }
+
+  @Override
+  public BooleanDataWriter createWriteStream(DataOutput output) {
+    return new BooleanDataWriter(output, extractor);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleArrayReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleArrayReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleArrayReservation.java
new file mode 100644
index 0000000..6acf657
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleArrayReservation.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.DoubleConsumer;
+import java.util.function.DoubleSupplier;
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.DoubleDataArrayReader;
+import org.apache.solr.analytics.stream.reservation.write.DoubleDataArrayWriter;
+
+public class DoubleArrayReservation extends ReductionDataArrayReservation<DoubleConsumer, DoubleSupplier> {
+  
+  public DoubleArrayReservation(DoubleConsumer applier, IntConsumer sizeApplier, DoubleSupplier extractor, IntSupplier sizeExtractor) {
+    super(applier, sizeApplier, extractor, sizeExtractor);
+  }
+
+  @Override
+  public DoubleDataArrayReader createReadStream(DataInput input) {
+    return new DoubleDataArrayReader(input, applier, sizeApplier);
+  }
+
+  @Override
+  public DoubleDataArrayWriter createWriteStream(DataOutput output) {
+    return new DoubleDataArrayWriter(output, extractor, sizeExtractor);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleCheckedReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleCheckedReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleCheckedReservation.java
new file mode 100644
index 0000000..a1dd461
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleCheckedReservation.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.BooleanSupplier;
+import java.util.function.DoubleConsumer;
+import java.util.function.DoubleSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.DoubleCheckedDataReader;
+import org.apache.solr.analytics.stream.reservation.write.DoubleCheckedDataWriter;
+
+public class DoubleCheckedReservation extends ReductionCheckedDataReservation<DoubleConsumer, DoubleSupplier> {
+  
+  public DoubleCheckedReservation(DoubleConsumer applier, DoubleSupplier extractor, BooleanSupplier exists) {
+    super(applier, extractor, exists);
+  }
+
+  @Override
+  public DoubleCheckedDataReader createReadStream(DataInput input) {
+    return new DoubleCheckedDataReader(input, applier);
+  }
+
+  @Override
+  public DoubleCheckedDataWriter createWriteStream(DataOutput output) {
+    return new DoubleCheckedDataWriter(output, extractor, exists);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleReservation.java
new file mode 100644
index 0000000..8ef3bef
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/DoubleReservation.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.DoubleConsumer;
+import java.util.function.DoubleSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.DoubleDataReader;
+import org.apache.solr.analytics.stream.reservation.write.DoubleDataWriter;
+
+public class DoubleReservation extends ReductionDataReservation<DoubleConsumer, DoubleSupplier> {
+  
+  public DoubleReservation(DoubleConsumer applier, DoubleSupplier extractor) {
+    super(applier, extractor);
+  }
+
+  @Override
+  public DoubleDataReader createReadStream(DataInput input) {
+    return new DoubleDataReader(input, applier);
+  }
+
+  @Override
+  public DoubleDataWriter createWriteStream(DataOutput output) {
+    return new DoubleDataWriter(output, extractor);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatArrayReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatArrayReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatArrayReservation.java
new file mode 100644
index 0000000..702106d
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatArrayReservation.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.FloatDataArrayReader;
+import org.apache.solr.analytics.stream.reservation.write.FloatDataArrayWriter;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.util.function.FloatSupplier;
+
+public class FloatArrayReservation extends ReductionDataArrayReservation<FloatConsumer, FloatSupplier> {
+  
+  public FloatArrayReservation(FloatConsumer applier, IntConsumer sizeApplier, FloatSupplier extractor, IntSupplier sizeExtractor) {
+    super(applier, sizeApplier, extractor, sizeExtractor);
+  }
+
+  @Override
+  public FloatDataArrayReader createReadStream(DataInput input) {
+    return new FloatDataArrayReader(input, applier, sizeApplier);
+  }
+
+  @Override
+  public FloatDataArrayWriter createWriteStream(DataOutput output) {
+    return new FloatDataArrayWriter(output, extractor, sizeExtractor);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatCheckedReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatCheckedReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatCheckedReservation.java
new file mode 100644
index 0000000..581772c
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatCheckedReservation.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.BooleanSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.FloatCheckedDataReader;
+import org.apache.solr.analytics.stream.reservation.write.FloatCheckedDataWriter;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.util.function.FloatSupplier;
+
+public class FloatCheckedReservation extends ReductionCheckedDataReservation<FloatConsumer, FloatSupplier> {
+  
+  public FloatCheckedReservation(FloatConsumer applier, FloatSupplier extractor, BooleanSupplier exists) {
+    super(applier, extractor, exists);
+  }
+
+  @Override
+  public FloatCheckedDataReader createReadStream(DataInput input) {
+    return new FloatCheckedDataReader(input, applier);
+  }
+
+  @Override
+  public FloatCheckedDataWriter createWriteStream(DataOutput output) {
+    return new FloatCheckedDataWriter(output, extractor, exists);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatReservation.java
new file mode 100644
index 0000000..c0ea5f0
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/FloatReservation.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+
+import org.apache.solr.analytics.stream.reservation.read.FloatDataReader;
+import org.apache.solr.analytics.stream.reservation.write.FloatDataWriter;
+import org.apache.solr.analytics.util.function.FloatConsumer;
+import org.apache.solr.analytics.util.function.FloatSupplier;
+
+public class FloatReservation extends ReductionDataReservation<FloatConsumer, FloatSupplier> {
+  
+  public FloatReservation(FloatConsumer applier, FloatSupplier extractor) {
+    super(applier, extractor);
+  }
+
+  @Override
+  public FloatDataReader createReadStream(DataInput input) {
+    return new FloatDataReader(input, applier);
+  }
+
+  @Override
+  public FloatDataWriter createWriteStream(DataOutput output) {
+    return new FloatDataWriter(output, extractor);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntArrayReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntArrayReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntArrayReservation.java
new file mode 100644
index 0000000..e3639a1
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntArrayReservation.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.IntDataArrayReader;
+import org.apache.solr.analytics.stream.reservation.write.IntDataArrayWriter;
+
+public class IntArrayReservation extends ReductionDataArrayReservation<IntConsumer, IntSupplier> {
+  
+  public IntArrayReservation(IntConsumer applier, IntConsumer sizeApplier, IntSupplier extractor, IntSupplier sizeExtractor) {
+    super(applier, sizeApplier, extractor, sizeExtractor);
+  }
+
+  @Override
+  public IntDataArrayReader createReadStream(DataInput input) {
+    return new IntDataArrayReader(input, applier, sizeApplier);
+  }
+
+  @Override
+  public IntDataArrayWriter createWriteStream(DataOutput output) {
+    return new IntDataArrayWriter(output, extractor, sizeExtractor);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntCheckedReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntCheckedReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntCheckedReservation.java
new file mode 100644
index 0000000..c0a7cf2
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntCheckedReservation.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.BooleanSupplier;
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.IntCheckedDataReader;
+import org.apache.solr.analytics.stream.reservation.write.IntCheckedDataWriter;
+
+public class IntCheckedReservation extends ReductionCheckedDataReservation<IntConsumer, IntSupplier> {
+  
+  public IntCheckedReservation(IntConsumer applier, IntSupplier extractor, BooleanSupplier exists) {
+    super(applier, extractor, exists);
+  }
+
+  @Override
+  public IntCheckedDataReader createReadStream(DataInput input) {
+    return new IntCheckedDataReader(input, applier);
+  }
+
+  @Override
+  public IntCheckedDataWriter createWriteStream(DataOutput output) {
+    return new IntCheckedDataWriter(output, extractor, exists);
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntReservation.java
new file mode 100644
index 0000000..cb66b58
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/IntReservation.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.IntDataReader;
+import org.apache.solr.analytics.stream.reservation.write.IntDataWriter;
+
+public class IntReservation extends ReductionDataReservation<IntConsumer, IntSupplier> {
+  
+  public IntReservation(IntConsumer applier, IntSupplier extractor) {
+    super(applier, extractor);
+  }
+
+  @Override
+  public IntDataReader createReadStream(DataInput input) {
+    return new IntDataReader(input, applier);
+  }
+
+  @Override
+  public IntDataWriter createWriteStream(DataOutput output) {
+    return new IntDataWriter(output, extractor);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongArrayReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongArrayReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongArrayReservation.java
new file mode 100644
index 0000000..980bc2b
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongArrayReservation.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.LongConsumer;
+import java.util.function.LongSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.LongDataArrayReader;
+import org.apache.solr.analytics.stream.reservation.write.LongDataArrayWriter;
+
+import java.util.function.IntConsumer;
+import java.util.function.IntSupplier;
+
+public class LongArrayReservation extends ReductionDataArrayReservation<LongConsumer, LongSupplier> {
+  
+  public LongArrayReservation(LongConsumer applier, IntConsumer sizeApplier, LongSupplier extractor, IntSupplier sizeExtractor) {
+    super(applier, sizeApplier, extractor, sizeExtractor);
+  }
+
+  @Override
+  public LongDataArrayReader createReadStream(DataInput input) {
+    return new LongDataArrayReader(input, applier, sizeApplier);
+  }
+
+  @Override
+  public LongDataArrayWriter createWriteStream(DataOutput output) {
+    return new LongDataArrayWriter(output, extractor, sizeExtractor);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongCheckedReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongCheckedReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongCheckedReservation.java
new file mode 100644
index 0000000..e1626e5
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongCheckedReservation.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.BooleanSupplier;
+import java.util.function.LongConsumer;
+import java.util.function.LongSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.LongCheckedDataReader;
+import org.apache.solr.analytics.stream.reservation.write.LongCheckedDataWriter;
+
+public class LongCheckedReservation extends ReductionCheckedDataReservation<LongConsumer, LongSupplier> {
+  
+  public LongCheckedReservation(LongConsumer applier, LongSupplier extractor, BooleanSupplier exists) {
+    super(applier, extractor, exists);
+  }
+
+  @Override
+  public LongCheckedDataReader createReadStream(DataInput input) {
+    return new LongCheckedDataReader(input, applier);
+  }
+
+  @Override
+  public LongCheckedDataWriter createWriteStream(DataOutput output) {
+    return new LongCheckedDataWriter(output, extractor, exists);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongReservation.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongReservation.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongReservation.java
new file mode 100644
index 0000000..daf8ec3
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/reservation/LongReservation.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.analytics.stream.reservation;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.function.LongConsumer;
+import java.util.function.LongSupplier;
+
+import org.apache.solr.analytics.stream.reservation.read.LongDataReader;
+import org.apache.solr.analytics.stream.reservation.write.LongDataWriter;
+
+public class LongReservation extends ReductionDataReservation<LongConsumer, LongSupplier> {
+  
+  public LongReservation(LongConsumer applier, LongSupplier extractor) {
+    super(applier, extractor);
+  }
+
+  @Override
+  public LongDataReader createReadStream(DataInput input) {
+    return new LongDataReader(input, applier);
+  }
+
+  @Override
+  public LongDataWriter createWriteStream(DataOutput output) {
+    return new LongDataWriter(output, extractor);
+  }
+}
\ No newline at end of file