You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dp...@apache.org on 2017/06/18 15:54:47 UTC

[1/8] lucene-solr:master: Adds documentation for the cartesianProduct

Repository: lucene-solr
Updated Branches:
  refs/heads/master 42fdb5492 -> 943bf5ab5


Adds documentation for the cartesianProduct


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

Branch: refs/heads/master
Commit: fffbe67b3b0f919f828df294916c071341f473f0
Parents: 42fdb54
Author: Dennis Gove <dp...@gmail.com>
Authored: Tue Jun 13 08:12:32 2017 -0400
Committer: Dennis Gove <dp...@gmail.com>
Committed: Sun Jun 18 11:50:46 2017 -0400

----------------------------------------------------------------------
 solr/solr-ref-guide/src/stream-decorators.adoc | 364 ++++++++++++++++++++
 1 file changed, 364 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/fffbe67b/solr/solr-ref-guide/src/stream-decorators.adoc
----------------------------------------------------------------------
diff --git a/solr/solr-ref-guide/src/stream-decorators.adoc b/solr/solr-ref-guide/src/stream-decorators.adoc
index c4ab4f4..e65f18a 100644
--- a/solr/solr-ref-guide/src/stream-decorators.adoc
+++ b/solr/solr-ref-guide/src/stream-decorators.adoc
@@ -20,6 +20,370 @@
 // specific language governing permissions and limitations
 // under the License.
 
+== cartesianProduct
+
+The `cartesianProduct` function turns a single tuple with a multi-valued field (ie. an array) into multiple tuples, one for each value in the array field. That is, given a single tuple containing an array of N values for fieldA, the `cartesianProduct` function will output N tuples, each with one value from the original tuple's array. In essence, you can flatten arrays for further processing.
+
+For example, using `cartesianProduct` you can turn this tuple
+[source,text]
+----
+{
+  "fieldA": "foo",
+  "fieldB": ["bar","baz","bat"]
+}
+----
+
+into the following 3 tuples
+[source,text]
+----
+{
+  "fieldA": "foo",
+  "fieldB": "bar"
+}
+{
+  "fieldA": "foo",
+  "fieldB": "baz"
+}
+{
+  "fieldA": "foo",
+  "fieldB": "bat"
+}
+----
+
+=== cartesianProduct Parameters
+
+* `incoming stream`: (Mandatory) A single incoming stream.
+* `fieldName or evaluator`: (Mandatory) Name of field to flatten values for, or evaluator whose result should be flattened.
+* `productSort='fieldName ASC|DESC'`: (Optional) Sort order of the newly generated tuples.
+
+=== cartesianProduct Syntax
+
+[source,text]
+----
+cartesianProduct(
+  <stream>,
+  <fieldName | evaluator> [as newFieldName],
+  productSort='fieldName ASC|DESC'
+)
+----
+
+=== cartesianProduct Examples
+
+The following examples show different outputs for this source tuple
+
+[source,text]
+----
+{
+  "fieldA": "valueA",
+  "fieldB": ["valueB1","valueB2"],
+  "fieldC": [1,2,3]
+}
+----
+
+==== Single Field, No Sorting
+
+[source,text]
+----
+cartesianProduct(
+  search(collection1, q='*:*', fl='fieldA, fieldB, fieldC', sort='fieldA ASC'),
+  fieldB
+)
+
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": [1,2,3]
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": [1,2,3]
+}
+----
+
+==== Single Evaluator, No Sorting
+
+[source,text]
+----
+cartesianProduct(
+  search(collection1, q='*:*', fl='fieldA, fieldB, fieldC', sort='fieldA ASC'),
+  sequence(3,4,5) as fieldE
+)
+
+{
+  "fieldA": "valueA",
+  "fieldB": ["valueB1","valueB2"],
+  "fieldC": [1,2,3],
+  "fieldE": 4
+}
+{
+  "fieldA": "valueA",
+  "fieldB": ["valueB1","valueB2"],
+  "fieldC": [1,2,3],
+  "fieldE": 9
+}
+{
+  "fieldA": "valueA",
+  "fieldB": ["valueB1","valueB2"],
+  "fieldC": [1,2,3],
+  "fieldE": 14
+}
+----
+
+==== Single Field, Sorted by Value
+
+[source,text]
+----
+cartesianProduct(
+  search(collection1, q='*:*', fl='fieldA, fieldB, fieldC', sort='fieldA ASC'),
+  fieldB,
+  productSort="fieldB DESC"
+)
+
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": [1,2,3]
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": [1,2,3]
+}
+----
+
+==== Single Evaluator, Sorted by Evaluator Values
+
+[source,text]
+----
+cartesianProduct(
+  search(collection1, q='*:*', fl='fieldA, fieldB, fieldC', sort='fieldA ASC'),
+  sequence(3,4,5) as fieldE,
+  productSort='newFieldE DESC'
+)
+
+{
+  "fieldA": "valueA",
+  "fieldB": ["valueB1","valueB2"],
+  "fieldC": [1,2,3],
+  "fieldE": 14
+}
+{
+  "fieldA": "valueA",
+  "fieldB": ["valueB1","valueB2"],
+  "fieldC": [1,2,3],
+  "fieldE": 9
+}
+{
+  "fieldA": "valueA",
+  "fieldB": ["valueB1","valueB2"],
+  "fieldC": [1,2,3],
+  "fieldE": 4
+}
+----
+
+==== Renamed Single Field, Sorted by Value
+
+[source,text]
+----
+cartesianProduct(
+  search(collection1, q='*:*', fl='fieldA, fieldB, fieldC', sort='fieldA ASC'),
+  fieldB as newFieldB,
+  productSort="fieldB DESC"
+)
+
+{
+  "fieldA": "valueA",
+  "fieldB": ["valueB1","valueB2"],
+  "fieldC": [1,2,3]
+  "newFieldB": "valueB2",
+}
+{
+  "fieldA": "valueA",
+  "fieldB": ["valueB1","valueB2"],
+  "fieldC": [1,2,3]
+  "newFieldB": "valueB1",
+}
+----
+
+==== Multiple Fields, No Sorting
+
+[source,text]
+----
+cartesianProduct(
+  search(collection1, q='*:*', fl='fieldA, fieldB, fieldC', sort='fieldA ASC'),
+  fieldB,
+  fieldC
+)
+
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": 1
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": 2
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": 3
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": 1
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": 2
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": 3
+}
+----
+
+==== Multiple Fields, Sorted by Single Field
+
+[source,text]
+----
+cartesianProduct(
+  search(collection1, q='*:*', fl='fieldA, fieldB, fieldC', sort='fieldA ASC'),
+  fieldB,
+  fieldC,
+  productSort="fieldC ASC"
+)
+
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": 1
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": 1
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": 2
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": 2
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": 3
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": 3
+}
+----
+
+==== Multiple Fields, Sorted by Multiple Fields
+
+[source,text]
+----
+cartesianProduct(
+  search(collection1, q='*:*', fl='fieldA, fieldB, fieldC', sort='fieldA ASC'),
+  fieldB,
+  fieldC,
+  productSort="fieldC ASC, fieldB DESC"
+)
+
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": 1
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": 1
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": 2
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": 2
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB2",
+  "fieldC": 3
+}
+{
+  "fieldA": "valueA",
+  "fieldB": "valueB1",
+  "fieldC": 3
+}
+----
+
+==== Field and Evaluator, No Sorting
+
+[source,text]
+----
+cartesianProduct(
+  search(collection1, q='*:*', fl='fieldA, fieldB, fieldC', sort='fieldA ASC'),
+  sequence(3,4,5) as fieldE,
+  fieldB
+)
+
+{
+  "fieldA": "valueA",
+  "fieldB": valueB1,
+  "fieldC": [1,2,3],
+  "fieldE": 4
+}
+{
+  "fieldA": "valueA",
+  "fieldB": valueB2,
+  "fieldC": [1,2,3],
+  "fieldE": 4
+}
+{
+  "fieldA": "valueA",
+  "fieldB": valueB1,
+  "fieldC": [1,2,3],
+  "fieldE": 9
+}
+{
+  "fieldA": "valueA",
+  "fieldB": valueB2,
+  "fieldC": [1,2,3],
+  "fieldE": 9
+}
+{
+  "fieldA": "valueA",
+  "fieldB": valueB1,
+  "fieldC": [1,2,3],
+  "fieldE": 14
+}
+{
+  "fieldA": "valueA",
+  "fieldB": valueB2,
+  "fieldC": [1,2,3],
+  "fieldE": 14
+}
+----
+
+As you can see in the examples above, the `cartesianProduct` function does support flattening tuples across multiple fields and/or evaluators. 
+
 == classify
 
 The `classify` function classifies tuples using a logistic regression text classification model. It was designed specifically to work with models trained using the <<stream-sources.adoc#train,train function>>. The `classify` function uses the <<stream-sources.adoc#model,model function>> to retrieve a stored model and then scores a stream of tuples using the model. The tuples read by the classifier must contain a text field that can be used for classification. The classify function uses a Lucene analyzer to extract the features from the text so the model can be applied. By default the `classify` function looks for the analyzer using the name of text field in the tuple. If the Solr schema on the worker node does not contain this field, the analyzer can be looked up in another field by specifying the `analyzerField` parameter.


[5/8] lucene-solr:master: SOLR-10882: ArrayEvaluator now supports values of any type

Posted by dp...@apache.org.
SOLR-10882: ArrayEvaluator now supports values of any type


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

Branch: refs/heads/master
Commit: 606824acaf6e0479cc1b29f57266ade18aed3d08
Parents: 8988862
Author: Dennis Gove <dp...@gmail.com>
Authored: Tue Jun 13 09:19:45 2017 -0400
Committer: Dennis Gove <dp...@gmail.com>
Committed: Sun Jun 18 11:50:57 2017 -0400

----------------------------------------------------------------------
 .../org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/606824ac/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
index 31d89a2..ed45ee9 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
@@ -36,11 +36,11 @@ public class ArrayEvaluator extends ComplexEvaluator implements Expressible {
     super(expression, factory);
   }
 
-  public List<Number> evaluate(Tuple tuple) throws IOException {
-    List<Number> list = new ArrayList();
+  public List<Object> evaluate(Tuple tuple) throws IOException {
+    List<Object> list = new ArrayList<>();
     for(StreamEvaluator subEvaluator : subEvaluators) {
-      Number num = (Number)subEvaluator.evaluate(tuple);
-      list.add(num);
+      Object value = (Number)subEvaluator.evaluate(tuple);
+      list.add(value);
     }
 
     return list;


[3/8] lucene-solr:master: SOLR-10882: LengthEvaluator now supports collections of any type

Posted by dp...@apache.org.
SOLR-10882: LengthEvaluator now supports collections of any type


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

Branch: refs/heads/master
Commit: f1695104fa8df6d9b484ef94d13eac16bcb3cf36
Parents: fffbe67
Author: Dennis Gove <dp...@gmail.com>
Authored: Tue Jun 13 09:06:00 2017 -0400
Committer: Dennis Gove <dp...@gmail.com>
Committed: Sun Jun 18 11:50:57 2017 -0400

----------------------------------------------------------------------
 .../client/solrj/io/eval/LengthEvaluator.java   |  23 +++-
 .../io/stream/eval/LengthEvaluatorTest.java     | 119 +++++++++++++++++++
 2 files changed, 138 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f1695104/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/LengthEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/LengthEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/LengthEvaluator.java
index da55ee4..b070fe8 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/LengthEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/LengthEvaluator.java
@@ -17,7 +17,8 @@
 package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
-import java.util.List;
+import java.util.Collection;
+import java.util.Locale;
 
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.Explanation;
@@ -33,12 +34,26 @@ public class LengthEvaluator extends ComplexEvaluator implements Expressible {
 
   public LengthEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(1 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting one value but found %d",expression,subEvaluators.size()));
+    }
   }
 
   public Number evaluate(Tuple tuple) throws IOException {
-    StreamEvaluator colEval1 = subEvaluators.get(0);
-    List<Number> numbers = (List<Number>)colEval1.evaluate(tuple);
-    return numbers.size();
+    
+    Object result = subEvaluators.get(0).evaluate(tuple);
+    
+    if(null == result){
+      throw new IOException(String.format(Locale.ROOT, "Unable to find %s(...) because the value is null", constructingFactory.getFunctionName(getClass())));
+    }
+    
+    if(result instanceof Collection<?>){
+      // Cause other evaluators expect Long instead of Integer
+      return new Long(((Collection<?>)result).size());
+    }
+    
+    throw new IOException(String.format(Locale.ROOT, "Unable to find %s(...) because the value is not a collection, instead a %s was found", constructingFactory.getFunctionName(getClass()), result.getClass().getSimpleName()));
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/f1695104/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/LengthEvaluatorTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/LengthEvaluatorTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/LengthEvaluatorTest.java
new file mode 100644
index 0000000..4b137b5
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/LengthEvaluatorTest.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.client.solrj.io.stream.eval;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.solr.client.solrj.io.Tuple;
+import org.apache.solr.client.solrj.io.eval.LengthEvaluator;
+import org.apache.solr.client.solrj.io.eval.SequenceEvaluator;
+import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
+import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
+import org.junit.Test;
+
+import junit.framework.Assert;
+
+public class LengthEvaluatorTest extends LuceneTestCase {
+
+  StreamFactory factory;
+  Map<String, Object> values;
+  
+  public LengthEvaluatorTest() {
+    super();
+    
+    factory = new StreamFactory()
+      .withFunctionName("length", LengthEvaluator.class)
+      .withFunctionName("sequence", SequenceEvaluator.class);
+    values = new HashMap<String,Object>();
+  }
+    
+  @Test
+  public void lengthField() throws Exception{
+    StreamEvaluator evaluator = factory.constructEvaluator("length(a)");
+    Object result;
+    
+    values.clear();
+    values.put("a", new ArrayList<Integer>(){{ add(1); add(2); add(4); }});
+    result = evaluator.evaluate(new Tuple(values));
+    Assert.assertTrue(result instanceof Long);
+    Assert.assertEquals(3L, result);
+    
+    values.clear();
+    values.put("a", new ArrayList<String>(){{ add("a"); add("b"); }});
+    result = evaluator.evaluate(new Tuple(values));
+    Assert.assertTrue(result instanceof Long);
+    Assert.assertEquals(2L, result);
+    
+    values.clear();
+    values.put("a", new ArrayList<String>(){{ }});
+    result = evaluator.evaluate(new Tuple(values));
+    Assert.assertTrue(result instanceof Long);
+    Assert.assertEquals(0L, result);    
+  }
+
+  @Test
+  public void lengthEvaluator() throws Exception{
+    StreamEvaluator evaluator = factory.constructEvaluator("length(sequence(3,4,10))");
+    Object result;
+    
+    values.clear();
+    result = evaluator.evaluate(new Tuple(values));
+    Assert.assertTrue(result instanceof Long);
+    Assert.assertEquals(3L, result);    
+  }
+  
+  @Test(expected = IOException.class)
+  public void lengthValueNotCollection() throws Exception{
+    StreamEvaluator evaluator = factory.constructEvaluator("length(a)");
+    
+    values.clear();
+    values.put("a", "foo");
+    evaluator.evaluate(new Tuple(values));    
+  }
+  
+  @Test(expected = IOException.class)
+  public void lengthNoField() throws Exception{
+    factory.constructEvaluator("length()");
+  }
+  
+  @Test(expected = IOException.class)
+  public void lengthTwoFields() throws Exception{
+    factory.constructEvaluator("length(a,b)");
+  }
+  
+  @Test(expected = IOException.class)
+  public void lengthNoValue() throws Exception{
+    StreamEvaluator evaluator = factory.constructEvaluator("length(a)");
+    
+    values.clear();
+    Object result = evaluator.evaluate(new Tuple(values));
+    assertNull(result);
+  }
+  @Test(expected = IOException.class)
+  public void lengthNullValue() throws Exception{
+    StreamEvaluator evaluator = factory.constructEvaluator("length(a)");
+    
+    values.clear();
+    values.put("a", null);
+    Object result = evaluator.evaluate(new Tuple(values));
+    assertNull(result);
+  }
+}


[7/8] lucene-solr:master: SOLR-10882: Moves sub evaluator check to the constructors to catch errors earlier

Posted by dp...@apache.org.
SOLR-10882: Moves sub evaluator check to the constructors to catch errors earlier


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

Branch: refs/heads/master
Commit: aeec043ed1cdf6ffd2b92811adde162eab06debd
Parents: 113459a
Author: Dennis Gove <dp...@gmail.com>
Authored: Fri Jun 16 20:10:28 2017 -0400
Committer: Dennis Gove <dp...@gmail.com>
Committed: Sun Jun 18 11:50:58 2017 -0400

----------------------------------------------------------------------
 .../solr/client/solrj/io/eval/ConvolutionEvaluator.java   | 10 +++++-----
 .../solr/client/solrj/io/eval/CorrelationEvaluator.java   |  9 +++++----
 .../solr/client/solrj/io/eval/CovarianceEvaluator.java    |  9 +++++----
 .../solrj/io/eval/CumulativeProbabilityEvaluator.java     |  9 +++++----
 .../solr/client/solrj/io/eval/DescribeEvaluator.java      | 10 ++++++----
 .../solr/client/solrj/io/eval/DistanceEvaluator.java      | 10 ++++++----
 .../solrj/io/eval/EmpiricalDistributionEvaluator.java     |  9 +++++----
 .../solr/client/solrj/io/eval/FindDelayEvaluator.java     |  9 +++++----
 .../solr/client/solrj/io/eval/HistogramEvaluator.java     |  9 +++++----
 .../solr/client/solrj/io/eval/MovingAverageEvaluator.java |  9 +++++----
 .../solr/client/solrj/io/eval/PercentileEvaluator.java    |  9 +++++----
 .../solr/client/solrj/io/eval/PredictEvaluator.java       | 10 ++++++----
 .../apache/solr/client/solrj/io/eval/RankEvaluator.java   | 10 ++++++----
 .../solr/client/solrj/io/eval/RegressionEvaluator.java    | 10 ++++++----
 .../solr/client/solrj/io/eval/ReverseEvaluator.java       | 10 ++++++----
 .../apache/solr/client/solrj/io/eval/ScaleEvaluator.java  | 10 ++++++----
 .../solr/client/solrj/io/eval/SequenceEvaluator.java      | 10 ++++++----
 17 files changed, 93 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ConvolutionEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ConvolutionEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ConvolutionEvaluator.java
index 000fa0d..e91620e 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ConvolutionEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ConvolutionEvaluator.java
@@ -18,6 +18,7 @@ package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Locale;
 import java.util.ArrayList;
 
 import org.apache.commons.math3.util.MathArrays;
@@ -35,15 +36,14 @@ public class ConvolutionEvaluator extends ComplexEvaluator implements Expressibl
 
   public ConvolutionEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values but found %d",expression,subEvaluators.size()));
+    }
   }
 
   public List<Number> evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Convolution evaluator expects 2 parameters found: "+subEvaluators.size());
-    }
-
-
     StreamEvaluator colEval1 = subEvaluators.get(0);
     StreamEvaluator colEval2 = subEvaluators.get(1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CorrelationEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CorrelationEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CorrelationEvaluator.java
index 05db16f..73c9f39 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CorrelationEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CorrelationEvaluator.java
@@ -18,6 +18,7 @@ package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Locale;
 
 import org.apache.commons.math3.stat.correlation.PearsonsCorrelation;
 import org.apache.solr.client.solrj.io.Tuple;
@@ -34,14 +35,14 @@ public class CorrelationEvaluator extends ComplexEvaluator implements Expressibl
 
   public CorrelationEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values but found %d",expression,subEvaluators.size()));
+    }
   }
 
   public Number evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Correlation evaluator expects 2 parameters found: "+subEvaluators.size());
-    }
-
     StreamEvaluator colEval1 = subEvaluators.get(0);
     StreamEvaluator colEval2 = subEvaluators.get(1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CovarianceEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CovarianceEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CovarianceEvaluator.java
index 5778289..9371d78 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CovarianceEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CovarianceEvaluator.java
@@ -18,6 +18,7 @@ package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Locale;
 
 import org.apache.commons.math3.stat.correlation.Covariance;
 import org.apache.solr.client.solrj.io.Tuple;
@@ -34,14 +35,14 @@ public class CovarianceEvaluator extends ComplexEvaluator implements Expressible
 
   public CovarianceEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values but found %d",expression,subEvaluators.size()));
+    }
   }
 
   public Number evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Covariance evaluator expects 2 parameters found: "+subEvaluators.size());
-    }
-
     StreamEvaluator colEval1 = subEvaluators.get(0);
     StreamEvaluator colEval2 = subEvaluators.get(1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CumulativeProbabilityEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CumulativeProbabilityEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CumulativeProbabilityEvaluator.java
index 469e983..9e2bbaf 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CumulativeProbabilityEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/CumulativeProbabilityEvaluator.java
@@ -18,6 +18,7 @@
 package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
+import java.util.Locale;
 
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.Explanation;
@@ -33,14 +34,14 @@ public class CumulativeProbabilityEvaluator extends ComplexEvaluator implements
 
   public CumulativeProbabilityEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values (emperical distribution and a number) but found %d",expression,subEvaluators.size()));
+    }
   }
 
   public Number evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Cumulative probability expects 2 parameters: an emperical distribution and a number");
-    }
-
     StreamEvaluator r = subEvaluators.get(0);
     StreamEvaluator d = subEvaluators.get(1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DescribeEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DescribeEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DescribeEvaluator.java
index 196afe5..e4c7523 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DescribeEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DescribeEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
@@ -36,14 +37,15 @@ public class DescribeEvaluator extends ComplexEvaluator implements Expressible {
 
   public DescribeEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(1 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting one column but found %d",expression,subEvaluators.size()));
+    }
+
   }
 
   public Tuple evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 1) {
-      throw new IOException("describe expects 1 column as a parameters");
-    }
-
     StreamEvaluator colEval = subEvaluators.get(0);
 
     List<Number> numbers = (List<Number>)colEval.evaluate(tuple);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DistanceEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DistanceEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DistanceEvaluator.java
index f4ac319..12591ad 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DistanceEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DistanceEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Locale;
 
 import org.apache.commons.math3.ml.distance.EuclideanDistance;
 import org.apache.solr.client.solrj.io.Tuple;
@@ -35,14 +36,15 @@ public class DistanceEvaluator extends ComplexEvaluator implements Expressible {
 
   public DistanceEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values but found %d",expression,subEvaluators.size()));
+    }
+
   }
 
   public Number evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Distance evaluator expects 2 parameters found: "+subEvaluators.size());
-    }
-
     StreamEvaluator colEval1 = subEvaluators.get(0);
     StreamEvaluator colEval2 = subEvaluators.get(1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/EmpiricalDistributionEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/EmpiricalDistributionEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/EmpiricalDistributionEvaluator.java
index 6885352..8456b4d 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/EmpiricalDistributionEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/EmpiricalDistributionEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Arrays;
 
@@ -38,14 +39,14 @@ public class EmpiricalDistributionEvaluator extends ComplexEvaluator implements
 
   public EmpiricalDistributionEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(1 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting one column but found %d",expression,subEvaluators.size()));
+    }
   }
 
   public Tuple evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 1) {
-      throw new IOException("Empirical dist expects 1 column as a parameters");
-    }
-
     StreamEvaluator colEval1 = subEvaluators.get(0);
 
     List<Number> numbers1 = (List<Number>)colEval1.evaluate(tuple);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/FindDelayEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/FindDelayEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/FindDelayEvaluator.java
index 0cdd153..4ffaee5 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/FindDelayEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/FindDelayEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.Locale;
 
 import org.apache.commons.math3.util.MathArrays;
 import org.apache.solr.client.solrj.io.Tuple;
@@ -35,14 +36,14 @@ public class FindDelayEvaluator extends ComplexEvaluator implements Expressible
 
   public FindDelayEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values but found %d",expression,subEvaluators.size()));
+    }
   }
 
   public Number evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Finddelay evaluator expects 2 parameters found: "+subEvaluators.size());
-    }
-
     StreamEvaluator colEval1 = subEvaluators.get(0);
     StreamEvaluator colEval2 = subEvaluators.get(1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/HistogramEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/HistogramEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/HistogramEvaluator.java
index aa8408b..0217bae 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/HistogramEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/HistogramEvaluator.java
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import org.apache.commons.math3.random.EmpiricalDistribution;
@@ -38,14 +39,14 @@ public class HistogramEvaluator extends ComplexEvaluator implements Expressible
 
   public HistogramEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values but found %d",expression,subEvaluators.size()));
+    }
   }
 
   public List<Map> evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Histogram evaluator expects 2 parameters found: "+subEvaluators.size());
-    }
-
     StreamEvaluator colEval1 = subEvaluators.get(0);
 
     List<Number> numbers1 = (List<Number>)colEval1.evaluate(tuple);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/MovingAverageEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/MovingAverageEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/MovingAverageEvaluator.java
index 783116e..bb4909b 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/MovingAverageEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/MovingAverageEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
 import org.apache.solr.client.solrj.io.Tuple;
@@ -35,14 +36,14 @@ public class MovingAverageEvaluator extends ComplexEvaluator implements Expressi
 
   public MovingAverageEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values but found %d",expression,subEvaluators.size()));
+    }
   }
 
   public List<Number> evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Moving average evaluator expects 2 parameters found: "+subEvaluators.size());
-    }
-
     StreamEvaluator colEval = subEvaluators.get(0);
     StreamEvaluator windowEval = subEvaluators.get(1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PercentileEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PercentileEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PercentileEvaluator.java
index 658e66a..6a51360 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PercentileEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PercentileEvaluator.java
@@ -18,6 +18,7 @@
 package org.apache.solr.client.solrj.io.eval;
 
 import java.util.List;
+import java.util.Locale;
 import java.io.IOException;
 
 import org.apache.solr.client.solrj.io.Tuple;
@@ -35,13 +36,13 @@ public class PercentileEvaluator extends ComplexEvaluator implements Expressible
 
   public PercentileEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values (array and number) but found %d",expression,subEvaluators.size()));
+    }
   }
 
   public Number evaluate(Tuple tuple) throws IOException {
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Percentile expects 2 parameters: an array and a number");
-    }
-
     StreamEvaluator colEval = subEvaluators.get(0);
     List<Number> column = (List<Number>)colEval.evaluate(tuple);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PredictEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PredictEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PredictEvaluator.java
index 0d1e763..af8a7f0 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PredictEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PredictEvaluator.java
@@ -18,6 +18,7 @@
 package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
+import java.util.Locale;
 
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.Explanation;
@@ -33,14 +34,15 @@ public class PredictEvaluator extends ComplexEvaluator implements Expressible {
 
   public PredictEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values (regression result and a number) but found %d",expression,subEvaluators.size()));
+    }
+
   }
 
   public Number evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Predict expects 2 parameters: a regression result and a number");
-    }
-
     StreamEvaluator r = subEvaluators.get(0);
     StreamEvaluator d = subEvaluators.get(1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RankEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RankEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RankEvaluator.java
index 2086c92..88a730d 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RankEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RankEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import org.apache.commons.math3.stat.ranking.NaturalRanking;
 import org.apache.solr.client.solrj.io.Tuple;
@@ -35,14 +36,15 @@ public class RankEvaluator extends ComplexEvaluator implements Expressible {
 
   public RankEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(1 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting one value but found %d",expression,subEvaluators.size()));
+    }
+
   }
 
   public List<Number> evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 1) {
-      throw new IOException("Rank evaluator expects 1 parameters found: "+subEvaluators.size());
-    }
-
     StreamEvaluator colEval = subEvaluators.get(0);
 
     List<Number> numbers = (List<Number>)colEval.evaluate(tuple);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RegressionEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RegressionEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RegressionEvaluator.java
index 42a6955..263a69a 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RegressionEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RegressionEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import org.apache.commons.math3.stat.regression.SimpleRegression;
@@ -36,14 +37,15 @@ public class RegressionEvaluator extends ComplexEvaluator implements Expressible
 
   public RegressionEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two columns but found %d",expression,subEvaluators.size()));
+    }
+
   }
 
   public Tuple evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Regress expects 2 columns as parameters");
-    }
-
     StreamEvaluator colEval1 = subEvaluators.get(0);
     StreamEvaluator colEval2 = subEvaluators.get(1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ReverseEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ReverseEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ReverseEvaluator.java
index cb11c91..56e0b63 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ReverseEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ReverseEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.Explanation;
@@ -34,14 +35,15 @@ public class ReverseEvaluator extends ComplexEvaluator implements Expressible {
 
   public ReverseEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(1 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting one value but found %d",expression,subEvaluators.size()));
+    }
+
   }
 
   public List<Number> evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 1) {
-      throw new IOException("Reverse evaluator expects 1 parameters found: "+subEvaluators.size());
-    }
-
     StreamEvaluator colEval1 = subEvaluators.get(0);
 
     List<Number> numbers1 = (List<Number>)colEval1.evaluate(tuple);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ScaleEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ScaleEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ScaleEvaluator.java
index f45e2c4..806e6f6 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ScaleEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ScaleEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import org.apache.commons.math3.util.MathArrays;
 import org.apache.solr.client.solrj.io.Tuple;
@@ -35,14 +36,15 @@ public class ScaleEvaluator extends ComplexEvaluator implements Expressible {
 
   public ScaleEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(2 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting two values but found %d",expression,subEvaluators.size()));
+    }
+
   }
 
   public List<Number> evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 2) {
-      throw new IOException("Scale evaluator expects 2 parameters found: "+subEvaluators.size());
-    }
-
     StreamEvaluator numEval = subEvaluators.get(0);
     StreamEvaluator colEval1 = subEvaluators.get(1);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/aeec043e/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/SequenceEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/SequenceEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/SequenceEvaluator.java
index c45e551..c6db106 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/SequenceEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/SequenceEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 import org.apache.commons.math3.util.MathArrays;
 import org.apache.solr.client.solrj.io.Tuple;
@@ -35,14 +36,15 @@ public class SequenceEvaluator extends ComplexEvaluator implements Expressible {
 
   public SequenceEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
+    
+    if(3 != subEvaluators.size()){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting three values but found %d",expression,subEvaluators.size()));
+    }
+
   }
 
   public List<Number> evaluate(Tuple tuple) throws IOException {
 
-    if(subEvaluators.size() != 3) {
-      throw new IOException("Sequence evaluator expects 3 parameters found: "+subEvaluators.size());
-    }
-
     StreamEvaluator sizeEval = subEvaluators.get(0);
     StreamEvaluator startEval = subEvaluators.get(1);
     StreamEvaluator strideEval = subEvaluators.get(2);


Re: [6/8] lucene-solr:master: SOLR-10882: ArrayEvaluator now works with all types and allows sorts (deleted ArraySortEvaluator)

Posted by Erick Erickson <er...@gmail.com>.
Thanks, I was worried about the commit I did last night but it's not that. Whew!

On Sun, Jun 18, 2017 at 11:24 PM, Shalin Shekhar Mangar
<sh...@gmail.com> wrote:
> This commit has broken StreamExpressionTest.testArraySort
>
> On Sun, Jun 18, 2017 at 9:24 PM,  <dp...@apache.org> wrote:
>> SOLR-10882: ArrayEvaluator now works with all types and allows sorts (deleted ArraySortEvaluator)
>>
>>
>> Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
>> Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/113459a8
>> Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/113459a8
>> Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/113459a8
>>
>> Branch: refs/heads/master
>> Commit: 113459a840e8ca3482ebd36a76dda551fac885ec
>> Parents: 5fca6a4
>> Author: Dennis Gove <dp...@gmail.com>
>> Authored: Thu Jun 15 22:10:37 2017 -0400
>> Committer: Dennis Gove <dp...@gmail.com>
>> Committed: Sun Jun 18 11:50:58 2017 -0400
>>
>> ----------------------------------------------------------------------
>>  .../org/apache/solr/handler/StreamHandler.java  | 479 +++++++++----------
>>  .../client/solrj/io/eval/ArrayEvaluator.java    |  48 +-
>>  .../solrj/io/eval/ArraySortEvaluator.java       |  77 ---
>>  .../client/solrj/io/eval/ComplexEvaluator.java  |  18 +-
>>  .../io/stream/eval/ArrayEvaluatorTest.java      | 155 ++++++
>>  5 files changed, 452 insertions(+), 325 deletions(-)
>> ----------------------------------------------------------------------
>>
>>
>> http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
>> ----------------------------------------------------------------------
>> diff --git a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
>> index 7889bf7..4616204 100644
>> --- a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
>> +++ b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
>> @@ -77,7 +77,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>    private StreamFactory streamFactory = new StreamFactory();
>>    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
>>    private String coreName;
>> -  private Map<String, DaemonStream> daemons = Collections.synchronizedMap(new HashMap());
>> +  private Map<String,DaemonStream> daemons = Collections.synchronizedMap(new HashMap());
>>
>>    @Override
>>    public PermissionNameProvider.Name getPermissionName(AuthorizationContext request) {
>> @@ -89,202 +89,202 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>    }
>>
>>    public void inform(SolrCore core) {
>> -
>> -    /* The stream factory will always contain the zkUrl for the given collection
>> -     * Adds default streams with their corresponding function names. These
>> -     * defaults can be overridden or added to in the solrConfig in the stream
>> -     * RequestHandler def. Example config override
>> -     *  <lst name="streamFunctions">
>> -     *    <str name="group">org.apache.solr.client.solrj.io.stream.ReducerStream</str>
>> -     *    <str name="count">org.apache.solr.client.solrj.io.stream.RecordCountStream</str>
>> -     *  </lst>
>> -     * */
>> +
>> +    /*
>> +     * The stream factory will always contain the zkUrl for the given collection Adds default streams with their
>> +     * corresponding function names. These defaults can be overridden or added to in the solrConfig in the stream
>> +     * RequestHandler def. Example config override
>> +     * <lst name="streamFunctions">
>> +     *  <str name="group">org.apache.solr.client.solrj.io.stream.ReducerStream</str>
>> +     *  <str name="count">org.apache.solr.client.solrj.io.stream.RecordCountStream</str>
>> +     * </lst>
>> +     */
>>
>>      String defaultCollection;
>>      String defaultZkhost;
>>      CoreContainer coreContainer = core.getCoreContainer();
>>      this.coreName = core.getName();
>>
>> -    if(coreContainer.isZooKeeperAware()) {
>> +    if (coreContainer.isZooKeeperAware()) {
>>        defaultCollection = core.getCoreDescriptor().getCollectionName();
>>        defaultZkhost = core.getCoreContainer().getZkController().getZkServerAddress();
>>        streamFactory.withCollectionZkHost(defaultCollection, defaultZkhost);
>>        streamFactory.withDefaultZkHost(defaultZkhost);
>>        modelCache = new ModelCache(250,
>> -                                  defaultZkhost,
>> -                                  clientCache);
>> -    }
>> -
>> -     streamFactory
>> -       // source streams
>> -      .withFunctionName("search", CloudSolrStream.class)
>> -      .withFunctionName("facet", FacetStream.class)
>> -      .withFunctionName("update", UpdateStream.class)
>> -      .withFunctionName("jdbc", JDBCStream.class)
>> -      .withFunctionName("topic", TopicStream.class)
>> -      .withFunctionName("commit", CommitStream.class)
>> -      .withFunctionName("random", RandomStream.class)
>> -      .withFunctionName("knn", KnnStream.class)
>> -
>> -      // decorator streams
>> -      .withFunctionName("merge", MergeStream.class)
>> -      .withFunctionName("unique", UniqueStream.class)
>> -      .withFunctionName("top", RankStream.class)
>> -      .withFunctionName("group", GroupOperation.class)
>> -      .withFunctionName("reduce", ReducerStream.class)
>> -      .withFunctionName("parallel", ParallelStream.class)
>> -      .withFunctionName("rollup", RollupStream.class)
>> -      .withFunctionName("stats", StatsStream.class)
>> -      .withFunctionName("innerJoin", InnerJoinStream.class)
>> -      .withFunctionName("leftOuterJoin", LeftOuterJoinStream.class)
>> -      .withFunctionName("hashJoin", HashJoinStream.class)
>> -      .withFunctionName("outerHashJoin", OuterHashJoinStream.class)
>> -      .withFunctionName("intersect", IntersectStream.class)
>> -      .withFunctionName("complement", ComplementStream.class)
>> -      .withFunctionName(SORT, SortStream.class)
>> -      .withFunctionName("train", TextLogitStream.class)
>> -      .withFunctionName("features", FeaturesSelectionStream.class)
>> -      .withFunctionName("daemon", DaemonStream.class)
>> -      .withFunctionName("shortestPath", ShortestPathStream.class)
>> -      .withFunctionName("gatherNodes", GatherNodesStream.class)
>> -      .withFunctionName("nodes", GatherNodesStream.class)
>> -      .withFunctionName("select", SelectStream.class)
>> -      .withFunctionName("shortestPath", ShortestPathStream.class)
>> -      .withFunctionName("gatherNodes", GatherNodesStream.class)
>> -      .withFunctionName("nodes", GatherNodesStream.class)
>> -      .withFunctionName("scoreNodes", ScoreNodesStream.class)
>> -      .withFunctionName("model", ModelStream.class)
>> -      .withFunctionName("classify", ClassifyStream.class)
>> -      .withFunctionName("fetch", FetchStream.class)
>> -      .withFunctionName("executor", ExecutorStream.class)
>> -      .withFunctionName("null", NullStream.class)
>> -      .withFunctionName("priority", PriorityStream.class)
>> -         .withFunctionName("significantTerms", SignificantTermsStream.class)
>> -      .withFunctionName("cartesianProduct", CartesianProductStream.class)
>> -         .withFunctionName("shuffle", ShuffleStream.class)
>> -         .withFunctionName("calc", CalculatorStream.class)
>> -      .withFunctionName("eval",EvalStream.class)
>> -      .withFunctionName("echo", EchoStream.class)
>> -      .withFunctionName("cell", CellStream.class)
>> -      .withFunctionName("list", ListStream.class)
>> -      .withFunctionName("let", LetStream.class)
>> -      .withFunctionName("get", GetStream.class)
>> -      .withFunctionName("timeseries", TimeSeriesStream.class)
>> -      .withFunctionName("tuple", TupStream.class)
>> -      .withFunctionName("sql", SqlStream.class)
>> -      .withFunctionName("col", ColumnEvaluator.class)
>> -      .withFunctionName("predict", PredictEvaluator.class)
>> -      .withFunctionName("regress", RegressionEvaluator.class)
>> -      .withFunctionName("cov", CovarianceEvaluator.class)
>> -      .withFunctionName("conv", ConvolutionEvaluator.class)
>> -      .withFunctionName("normalize", NormalizeEvaluator.class)
>> -      .withFunctionName("rev", ReverseEvaluator.class)
>> -      .withFunctionName("length", LengthEvaluator.class)
>> -      .withFunctionName("rank", RankEvaluator.class)
>> -      .withFunctionName("scale", ScaleEvaluator.class)
>> -      .withFunctionName("distance", DistanceEvaluator.class)
>> -      .withFunctionName("copyOf", CopyOfEvaluator.class)
>> -      .withFunctionName("copyOfRange", CopyOfRangeEvaluator.class)
>> -      .withFunctionName("percentile", PercentileEvaluator.class)
>> -      .withFunctionName("empiricalDistribution", EmpiricalDistributionEvaluator.class)
>> -      .withFunctionName("cumulativeProbability", CumulativeProbabilityEvaluator.class)
>> -      .withFunctionName("describe", DescribeEvaluator.class)
>> -      .withFunctionName("finddelay", FindDelayEvaluator.class)
>> -      .withFunctionName("sequence", SequenceEvaluator.class)
>> -      .withFunctionName("array", ArrayEvaluator.class)
>> -      .withFunctionName("hist", HistogramEvaluator.class)
>> -      .withFunctionName("anova", AnovaEvaluator.class)
>> -      .withFunctionName("movingAvg", MovingAverageEvaluator.class)
>> -      .withFunctionName("arraySort", ArraySortEvaluator.class)
>> -
>> -      // metrics
>> -         .withFunctionName("min", MinMetric.class)
>> -      .withFunctionName("max", MaxMetric.class)
>> -      .withFunctionName("avg", MeanMetric.class)
>> -      .withFunctionName("sum", SumMetric.class)
>> -      .withFunctionName("count", CountMetric.class)
>> -
>> -      // tuple manipulation operations
>> -         .withFunctionName("replace", ReplaceOperation.class)
>> -      .withFunctionName("concat", ConcatOperation.class)
>> -
>> -      // stream reduction operations
>> -         .withFunctionName("group", GroupOperation.class)
>> -      .withFunctionName("distinct", DistinctOperation.class)
>> -      .withFunctionName("having", HavingStream.class)
>> -
>> -      // Stream Evaluators
>> -         .withFunctionName("val", RawValueEvaluator.class)
>> -
>> -      // Boolean Stream Evaluators
>> -         .withFunctionName("and", AndEvaluator.class)
>> -      .withFunctionName("eor", ExclusiveOrEvaluator.class)
>> -      .withFunctionName("eq", EqualsEvaluator.class)
>> -      .withFunctionName("gt", GreaterThanEvaluator.class)
>> -      .withFunctionName("gteq", GreaterThanEqualToEvaluator.class)
>> -      .withFunctionName("lt", LessThanEvaluator.class)
>> -      .withFunctionName("lteq", LessThanEqualToEvaluator.class)
>> -      .withFunctionName("not", NotEvaluator.class)
>> -         .withFunctionName("or", OrEvaluator.class)
>> -
>> -      // Date Time Evaluators
>> -         .withFunctionName(TemporalEvaluatorYear.FUNCTION_NAME, TemporalEvaluatorYear.class)
>> -      .withFunctionName(TemporalEvaluatorMonth.FUNCTION_NAME, TemporalEvaluatorMonth.class)
>> -      .withFunctionName(TemporalEvaluatorDay.FUNCTION_NAME, TemporalEvaluatorDay.class)
>> -      .withFunctionName(TemporalEvaluatorDayOfYear.FUNCTION_NAME, TemporalEvaluatorDayOfYear.class)
>> -         .withFunctionName(TemporalEvaluatorHour.FUNCTION_NAME, TemporalEvaluatorHour.class)
>> -      .withFunctionName(TemporalEvaluatorMinute.FUNCTION_NAME, TemporalEvaluatorMinute.class)
>> -         .withFunctionName(TemporalEvaluatorSecond.FUNCTION_NAME, TemporalEvaluatorSecond.class)
>> -      .withFunctionName(TemporalEvaluatorEpoch.FUNCTION_NAME, TemporalEvaluatorEpoch.class)
>> -      .withFunctionName(TemporalEvaluatorWeek.FUNCTION_NAME, TemporalEvaluatorWeek.class)
>> -         .withFunctionName(TemporalEvaluatorQuarter.FUNCTION_NAME, TemporalEvaluatorQuarter.class)
>> -         .withFunctionName(TemporalEvaluatorDayOfQuarter.FUNCTION_NAME, TemporalEvaluatorDayOfQuarter.class)
>> -
>> -      // Number Stream Evaluators
>> -         .withFunctionName("abs", AbsoluteValueEvaluator.class)
>> -      .withFunctionName("add", AddEvaluator.class)
>> -      .withFunctionName("div", DivideEvaluator.class)
>> -      .withFunctionName("mult", MultiplyEvaluator.class)
>> -      .withFunctionName("sub", SubtractEvaluator.class)
>> -      .withFunctionName("log", NaturalLogEvaluator.class)
>> -      .withFunctionName("pow", PowerEvaluator.class)
>> -      .withFunctionName("mod", ModuloEvaluator.class)
>> -         .withFunctionName("ceil", CeilingEvaluator.class)
>> -      .withFunctionName("floor", FloorEvaluator.class)
>> -      .withFunctionName("sin", SineEvaluator.class)
>> -      .withFunctionName("asin", ArcSineEvaluator.class)
>> -      .withFunctionName("sinh", HyperbolicSineEvaluator.class)
>> -      .withFunctionName("cos", CosineEvaluator.class)
>> -      .withFunctionName("acos", ArcCosineEvaluator.class)
>> -      .withFunctionName("cosh", HyperbolicCosineEvaluator.class)
>> -      .withFunctionName("tan", TangentEvaluator.class)
>> -      .withFunctionName("atan", ArcTangentEvaluator.class)
>> -      .withFunctionName("tanh", HyperbolicTangentEvaluator.class)
>> -         .withFunctionName("round", RoundEvaluator.class)
>> -      .withFunctionName("sqrt", SquareRootEvaluator.class)
>> -      .withFunctionName("cbrt", CubedRootEvaluator.class)
>> -      .withFunctionName("coalesce", CoalesceEvaluator.class)
>> -      .withFunctionName("uuid", UuidEvaluator.class)
>> -      .withFunctionName("corr", CorrelationEvaluator.class)
>> -
>> -
>> -      // Conditional Stream Evaluators
>> -         .withFunctionName("if", IfThenElseEvaluator.class)
>> -         .withFunctionName("analyze", AnalyzeEvaluator.class)
>> -         .withFunctionName("convert", ConversionEvaluator.class)
>> -      ;
>> -
>> -     // This pulls all the overrides and additions from the config
>> -     List<PluginInfo> pluginInfos = core.getSolrConfig().getPluginInfos(Expressible.class.getName());
>> -     for (PluginInfo pluginInfo : pluginInfos) {
>> -       Class<? extends Expressible> clazz = core.getMemClassLoader().findClass(pluginInfo.className, Expressible.class);
>> -       streamFactory.withFunctionName(pluginInfo.name, clazz);
>> -     }
>> +          defaultZkhost,
>> +          clientCache);
>> +    }
>> +
>> +    streamFactory
>> +        // source streams
>> +        .withFunctionName("search", CloudSolrStream.class)
>> +        .withFunctionName("facet", FacetStream.class)
>> +        .withFunctionName("update", UpdateStream.class)
>> +        .withFunctionName("jdbc", JDBCStream.class)
>> +        .withFunctionName("topic", TopicStream.class)
>> +        .withFunctionName("commit", CommitStream.class)
>> +        .withFunctionName("random", RandomStream.class)
>> +        .withFunctionName("knn", KnnStream.class)
>> +
>> +        // decorator streams
>> +        .withFunctionName("merge", MergeStream.class)
>> +        .withFunctionName("unique", UniqueStream.class)
>> +        .withFunctionName("top", RankStream.class)
>> +        .withFunctionName("group", GroupOperation.class)
>> +        .withFunctionName("reduce", ReducerStream.class)
>> +        .withFunctionName("parallel", ParallelStream.class)
>> +        .withFunctionName("rollup", RollupStream.class)
>> +        .withFunctionName("stats", StatsStream.class)
>> +        .withFunctionName("innerJoin", InnerJoinStream.class)
>> +        .withFunctionName("leftOuterJoin", LeftOuterJoinStream.class)
>> +        .withFunctionName("hashJoin", HashJoinStream.class)
>> +        .withFunctionName("outerHashJoin", OuterHashJoinStream.class)
>> +        .withFunctionName("intersect", IntersectStream.class)
>> +        .withFunctionName("complement", ComplementStream.class)
>> +        .withFunctionName(SORT, SortStream.class)
>> +        .withFunctionName("train", TextLogitStream.class)
>> +        .withFunctionName("features", FeaturesSelectionStream.class)
>> +        .withFunctionName("daemon", DaemonStream.class)
>> +        .withFunctionName("shortestPath", ShortestPathStream.class)
>> +        .withFunctionName("gatherNodes", GatherNodesStream.class)
>> +        .withFunctionName("nodes", GatherNodesStream.class)
>> +        .withFunctionName("select", SelectStream.class)
>> +        .withFunctionName("shortestPath", ShortestPathStream.class)
>> +        .withFunctionName("gatherNodes", GatherNodesStream.class)
>> +        .withFunctionName("nodes", GatherNodesStream.class)
>> +        .withFunctionName("scoreNodes", ScoreNodesStream.class)
>> +        .withFunctionName("model", ModelStream.class)
>> +        .withFunctionName("classify", ClassifyStream.class)
>> +        .withFunctionName("fetch", FetchStream.class)
>> +        .withFunctionName("executor", ExecutorStream.class)
>> +        .withFunctionName("null", NullStream.class)
>> +        .withFunctionName("priority", PriorityStream.class)
>> +        .withFunctionName("significantTerms", SignificantTermsStream.class)
>> +        .withFunctionName("cartesianProduct", CartesianProductStream.class)
>> +        .withFunctionName("shuffle", ShuffleStream.class)
>> +        .withFunctionName("calc", CalculatorStream.class)
>> +        .withFunctionName("eval", EvalStream.class)
>> +        .withFunctionName("echo", EchoStream.class)
>> +        .withFunctionName("cell", CellStream.class)
>> +        .withFunctionName("list", ListStream.class)
>> +        .withFunctionName("let", LetStream.class)
>> +        .withFunctionName("get", GetStream.class)
>> +        .withFunctionName("timeseries", TimeSeriesStream.class)
>> +        .withFunctionName("tuple", TupStream.class)
>> +        .withFunctionName("sql", SqlStream.class)
>> +
>> +        // metrics
>> +        .withFunctionName("min", MinMetric.class)
>> +        .withFunctionName("max", MaxMetric.class)
>> +        .withFunctionName("avg", MeanMetric.class)
>> +        .withFunctionName("sum", SumMetric.class)
>> +        .withFunctionName("count", CountMetric.class)
>> +
>> +        // tuple manipulation operations
>> +        .withFunctionName("replace", ReplaceOperation.class)
>> +        .withFunctionName("concat", ConcatOperation.class)
>> +
>> +        // stream reduction operations
>> +        .withFunctionName("group", GroupOperation.class)
>> +        .withFunctionName("distinct", DistinctOperation.class)
>> +        .withFunctionName("having", HavingStream.class)
>> +
>> +        // Stream Evaluators
>> +        .withFunctionName("val", RawValueEvaluator.class)
>> +
>> +        // New Evaluators
>> +        .withFunctionName("anova", AnovaEvaluator.class)
>> +        .withFunctionName("array", ArrayEvaluator.class)
>> +        .withFunctionName("col", ColumnEvaluator.class)
>> +        .withFunctionName("conv", ConvolutionEvaluator.class)
>> +        .withFunctionName("copyOf", CopyOfEvaluator.class)
>> +        .withFunctionName("copyOfRange", CopyOfRangeEvaluator.class)
>> +        .withFunctionName("cov", CovarianceEvaluator.class)
>> +        .withFunctionName("cumulativeProbability", CumulativeProbabilityEvaluator.class)
>> +        .withFunctionName("describe", DescribeEvaluator.class)
>> +        .withFunctionName("distance", DistanceEvaluator.class)
>> +        .withFunctionName("empiricalDistribution", EmpiricalDistributionEvaluator.class)
>> +        .withFunctionName("finddelay", FindDelayEvaluator.class)
>> +        .withFunctionName("hist", HistogramEvaluator.class)
>> +        .withFunctionName("length", LengthEvaluator.class)
>> +        .withFunctionName("movingAvg", MovingAverageEvaluator.class)
>> +        .withFunctionName("normalize", NormalizeEvaluator.class)
>> +        .withFunctionName("percentile", PercentileEvaluator.class)
>> +        .withFunctionName("predict", PredictEvaluator.class)
>> +        .withFunctionName("rank", RankEvaluator.class)
>> +        .withFunctionName("regress", RegressionEvaluator.class)
>> +        .withFunctionName("rev", ReverseEvaluator.class)
>> +        .withFunctionName("scale", ScaleEvaluator.class)
>> +        .withFunctionName("sequence", SequenceEvaluator.class)
>> +
>>
>> +        // Boolean Stream Evaluators
>> +        .withFunctionName("and", AndEvaluator.class)
>> +        .withFunctionName("eor", ExclusiveOrEvaluator.class)
>> +        .withFunctionName("eq", EqualsEvaluator.class)
>> +        .withFunctionName("gt", GreaterThanEvaluator.class)
>> +        .withFunctionName("gteq", GreaterThanEqualToEvaluator.class)
>> +        .withFunctionName("lt", LessThanEvaluator.class)
>> +        .withFunctionName("lteq", LessThanEqualToEvaluator.class)
>> +        .withFunctionName("not", NotEvaluator.class)
>> +        .withFunctionName("or", OrEvaluator.class)
>> +
>> +        // Date Time Evaluators
>> +        .withFunctionName(TemporalEvaluatorYear.FUNCTION_NAME, TemporalEvaluatorYear.class)
>> +        .withFunctionName(TemporalEvaluatorMonth.FUNCTION_NAME, TemporalEvaluatorMonth.class)
>> +        .withFunctionName(TemporalEvaluatorDay.FUNCTION_NAME, TemporalEvaluatorDay.class)
>> +        .withFunctionName(TemporalEvaluatorDayOfYear.FUNCTION_NAME, TemporalEvaluatorDayOfYear.class)
>> +        .withFunctionName(TemporalEvaluatorHour.FUNCTION_NAME, TemporalEvaluatorHour.class)
>> +        .withFunctionName(TemporalEvaluatorMinute.FUNCTION_NAME, TemporalEvaluatorMinute.class)
>> +        .withFunctionName(TemporalEvaluatorSecond.FUNCTION_NAME, TemporalEvaluatorSecond.class)
>> +        .withFunctionName(TemporalEvaluatorEpoch.FUNCTION_NAME, TemporalEvaluatorEpoch.class)
>> +        .withFunctionName(TemporalEvaluatorWeek.FUNCTION_NAME, TemporalEvaluatorWeek.class)
>> +        .withFunctionName(TemporalEvaluatorQuarter.FUNCTION_NAME, TemporalEvaluatorQuarter.class)
>> +        .withFunctionName(TemporalEvaluatorDayOfQuarter.FUNCTION_NAME, TemporalEvaluatorDayOfQuarter.class)
>> +
>> +        // Number Stream Evaluators
>> +        .withFunctionName("abs", AbsoluteValueEvaluator.class)
>> +        .withFunctionName("add", AddEvaluator.class)
>> +        .withFunctionName("div", DivideEvaluator.class)
>> +        .withFunctionName("mult", MultiplyEvaluator.class)
>> +        .withFunctionName("sub", SubtractEvaluator.class)
>> +        .withFunctionName("log", NaturalLogEvaluator.class)
>> +        .withFunctionName("pow", PowerEvaluator.class)
>> +        .withFunctionName("mod", ModuloEvaluator.class)
>> +        .withFunctionName("ceil", CeilingEvaluator.class)
>> +        .withFunctionName("floor", FloorEvaluator.class)
>> +        .withFunctionName("sin", SineEvaluator.class)
>> +        .withFunctionName("asin", ArcSineEvaluator.class)
>> +        .withFunctionName("sinh", HyperbolicSineEvaluator.class)
>> +        .withFunctionName("cos", CosineEvaluator.class)
>> +        .withFunctionName("acos", ArcCosineEvaluator.class)
>> +        .withFunctionName("cosh", HyperbolicCosineEvaluator.class)
>> +        .withFunctionName("tan", TangentEvaluator.class)
>> +        .withFunctionName("atan", ArcTangentEvaluator.class)
>> +        .withFunctionName("tanh", HyperbolicTangentEvaluator.class)
>> +        .withFunctionName("round", RoundEvaluator.class)
>> +        .withFunctionName("sqrt", SquareRootEvaluator.class)
>> +        .withFunctionName("cbrt", CubedRootEvaluator.class)
>> +        .withFunctionName("coalesce", CoalesceEvaluator.class)
>> +        .withFunctionName("uuid", UuidEvaluator.class)
>> +        .withFunctionName("corr", CorrelationEvaluator.class)
>> +
>> +        // Conditional Stream Evaluators
>> +        .withFunctionName("if", IfThenElseEvaluator.class)
>> +        .withFunctionName("analyze", AnalyzeEvaluator.class)
>> +        .withFunctionName("convert", ConversionEvaluator.class);
>> +
>> +    // This pulls all the overrides and additions from the config
>> +    List<PluginInfo> pluginInfos = core.getSolrConfig().getPluginInfos(Expressible.class.getName());
>> +    for (PluginInfo pluginInfo : pluginInfos) {
>> +      Class<? extends Expressible> clazz = core.getMemClassLoader().findClass(pluginInfo.className, Expressible.class);
>> +      streamFactory.withFunctionName(pluginInfo.name, clazz);
>> +    }
>> +
>>      core.addCloseHook(new CloseHook() {
>>        @Override
>>        public void preClose(SolrCore core) {
>> -        //To change body of implemented methods use File | Settings | File Templates.
>> +        // To change body of implemented methods use File | Settings | File Templates.
>>        }
>>
>>        @Override
>> @@ -299,7 +299,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>      params = adjustParams(params);
>>      req.setParams(params);
>>
>> -    if(params.get("action") != null) {
>> +    if (params.get("action") != null) {
>>        handleAdmin(req, rsp, params);
>>        return;
>>      }
>> @@ -308,7 +308,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>
>>      try {
>>        StreamExpression streamExpression = StreamExpressionParser.parse(params.get("expr"));
>> -      if(this.streamFactory.isEvaluator(streamExpression)) {
>> +      if (this.streamFactory.isEvaluator(streamExpression)) {
>>          StreamExpression tupleExpression = new StreamExpression("tuple");
>>          tupleExpression.addParameter(new StreamExpressionNamedParameter("return-value", streamExpression));
>>          tupleStream = this.streamFactory.constructStream(tupleExpression);
>> @@ -316,7 +316,8 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>          tupleStream = this.streamFactory.constructStream(streamExpression);
>>        }
>>      } catch (Exception e) {
>> -      //Catch exceptions that occur while the stream is being created. This will include streaming expression parse rules.
>> +      // Catch exceptions that occur while the stream is being created. This will include streaming expression parse
>> +      // rules.
>>        SolrException.log(logger, e);
>>        rsp.add("result-set", new DummyErrorStream(e));
>>
>> @@ -334,21 +335,21 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>      context.put("core", this.coreName);
>>      context.put("solr-core", req.getCore());
>>      tupleStream.setStreamContext(context);
>> -
>> +
>>      // if asking for explanation then go get it
>> -    if(params.getBool("explain", false)){
>> +    if (params.getBool("explain", false)) {
>>        rsp.add("explanation", tupleStream.toExplanation(this.streamFactory));
>>      }
>> -
>> -    if(tupleStream instanceof DaemonStream) {
>> -      DaemonStream daemonStream = (DaemonStream)tupleStream;
>> -      if(daemons.containsKey(daemonStream.getId())) {
>> +
>> +    if (tupleStream instanceof DaemonStream) {
>> +      DaemonStream daemonStream = (DaemonStream) tupleStream;
>> +      if (daemons.containsKey(daemonStream.getId())) {
>>          daemons.remove(daemonStream.getId()).close();
>>        }
>>        daemonStream.setDaemons(daemons);
>> -      daemonStream.open();  //This will start the deamonStream
>> +      daemonStream.open(); // This will start the deamonStream
>>        daemons.put(daemonStream.getId(), daemonStream);
>> -      rsp.add("result-set", new DaemonResponseStream("Deamon:"+daemonStream.getId()+" started on "+coreName));
>> +      rsp.add("result-set", new DaemonResponseStream("Deamon:" + daemonStream.getId() + " started on " + coreName));
>>      } else {
>>        rsp.add("result-set", new TimerStream(new ExceptionStream(tupleStream)));
>>      }
>> @@ -356,10 +357,10 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>
>>    private void handleAdmin(SolrQueryRequest req, SolrQueryResponse rsp, SolrParams params) {
>>      String action = params.get("action");
>> -    if("stop".equalsIgnoreCase(action)) {
>> +    if ("stop".equalsIgnoreCase(action)) {
>>        String id = params.get(ID);
>>        DaemonStream d = daemons.get(id);
>> -      if(d != null) {
>> +      if (d != null) {
>>          d.close();
>>          rsp.add("result-set", new DaemonResponseStream("Deamon:" + id + " stopped on " + coreName));
>>        } else {
>> @@ -400,50 +401,46 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>      return null;
>>    }
>>
>> -
>>    public static class DummyErrorStream extends TupleStream {
>>      private Exception e;
>>
>>      public DummyErrorStream(Exception e) {
>>        this.e = e;
>>      }
>> +
>>      public StreamComparator getStreamSort() {
>>        return null;
>>      }
>>
>> -    public void close() {
>> -    }
>> +    public void close() {}
>>
>> -    public void open() {
>> -    }
>> +    public void open() {}
>>
>> -    public void setStreamContext(StreamContext context) {
>> -    }
>> +    public void setStreamContext(StreamContext context) {}
>>
>>      public List<TupleStream> children() {
>>        return null;
>>      }
>> -
>> +
>>      @Override
>>      public Explanation toExplanation(StreamFactory factory) throws IOException {
>>
>>        return new StreamExplanation(getStreamNodeId().toString())
>> -        .withFunctionName("error")
>> -        .withImplementingClass(this.getClass().getName())
>> -        .withExpressionType(ExpressionType.STREAM_DECORATOR)
>> -        .withExpression("--non-expressible--");
>> +          .withFunctionName("error")
>> +          .withImplementingClass(this.getClass().getName())
>> +          .withExpressionType(ExpressionType.STREAM_DECORATOR)
>> +          .withExpression("--non-expressible--");
>>      }
>>
>>      public Tuple read() {
>>        String msg = e.getMessage();
>>
>>        Throwable t = e.getCause();
>> -      while(t != null) {
>> +      while (t != null) {
>>          msg = t.getMessage();
>>          t = t.getCause();
>>        }
>>
>> -
>>        Map m = new HashMap();
>>        m.put("EOF", true);
>>        m.put("EXCEPTION", msg);
>> @@ -457,18 +454,16 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>      public DaemonCollectionStream(Collection<DaemonStream> col) {
>>        this.it = col.iterator();
>>      }
>> +
>>      public StreamComparator getStreamSort() {
>>        return null;
>>      }
>>
>> -    public void close() {
>> -    }
>> +    public void close() {}
>>
>> -    public void open() {
>> -    }
>> +    public void open() {}
>>
>> -    public void setStreamContext(StreamContext context) {
>> -    }
>> +    public void setStreamContext(StreamContext context) {}
>>
>>      public List<TupleStream> children() {
>>        return null;
>> @@ -478,14 +473,14 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>      public Explanation toExplanation(StreamFactory factory) throws IOException {
>>
>>        return new StreamExplanation(getStreamNodeId().toString())
>> -        .withFunctionName("daemon-collection")
>> -        .withImplementingClass(this.getClass().getName())
>> -        .withExpressionType(ExpressionType.STREAM_DECORATOR)
>> -        .withExpression("--non-expressible--");
>> +          .withFunctionName("daemon-collection")
>> +          .withImplementingClass(this.getClass().getName())
>> +          .withExpressionType(ExpressionType.STREAM_DECORATOR)
>> +          .withExpression("--non-expressible--");
>>      }
>> -
>> +
>>      public Tuple read() {
>> -      if(it.hasNext()) {
>> +      if (it.hasNext()) {
>>          return it.next().getInfo();
>>        } else {
>>          Map m = new HashMap();
>> @@ -502,18 +497,16 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>      public DaemonResponseStream(String message) {
>>        this.message = message;
>>      }
>> +
>>      public StreamComparator getStreamSort() {
>>        return null;
>>      }
>>
>> -    public void close() {
>> -    }
>> +    public void close() {}
>>
>> -    public void open() {
>> -    }
>> +    public void open() {}
>>
>> -    public void setStreamContext(StreamContext context) {
>> -    }
>> +    public void setStreamContext(StreamContext context) {}
>>
>>      public List<TupleStream> children() {
>>        return null;
>> @@ -523,10 +516,10 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>      public Explanation toExplanation(StreamFactory factory) throws IOException {
>>
>>        return new StreamExplanation(getStreamNodeId().toString())
>> -        .withFunctionName("daemon-response")
>> -        .withImplementingClass(this.getClass().getName())
>> -        .withExpressionType(ExpressionType.STREAM_DECORATOR)
>> -        .withExpression("--non-expressible--");
>> +          .withFunctionName("daemon-response")
>> +          .withImplementingClass(this.getClass().getName())
>> +          .withExpressionType(ExpressionType.STREAM_DECORATOR)
>> +          .withExpression("--non-expressible--");
>>      }
>>
>>      public Tuple read() {
>> @@ -537,7 +530,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>        } else {
>>          sendEOF = true;
>>          Map m = new HashMap();
>> -        m.put("DaemonOp",message);
>> +        m.put("DaemonOp", message);
>>          return new Tuple(m);
>>        }
>>      }
>> @@ -577,15 +570,15 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>      public Explanation toExplanation(StreamFactory factory) throws IOException {
>>
>>        return new StreamExplanation(getStreamNodeId().toString())
>> -        .withFunctionName("timer")
>> -        .withImplementingClass(this.getClass().getName())
>> -        .withExpressionType(ExpressionType.STREAM_DECORATOR)
>> -        .withExpression("--non-expressible--");
>> +          .withFunctionName("timer")
>> +          .withImplementingClass(this.getClass().getName())
>> +          .withExpressionType(ExpressionType.STREAM_DECORATOR)
>> +          .withExpression("--non-expressible--");
>>      }
>>
>>      public Tuple read() throws IOException {
>>        Tuple tuple = this.tupleStream.read();
>> -      if(tuple.EOF) {
>> +      if (tuple.EOF) {
>>          long totalTime = (System.nanoTime() - begin) / 1000000;
>>          tuple.fields.put("RESPONSE_TIME", totalTime);
>>        }
>> @@ -593,25 +586,25 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>>      }
>>    }
>>
>> -  private Map<String, List<String>> getCollectionShards(SolrParams params) {
>> +  private Map<String,List<String>> getCollectionShards(SolrParams params) {
>>
>> -    Map<String, List<String>> collectionShards = new HashMap();
>> +    Map<String,List<String>> collectionShards = new HashMap();
>>      Iterator<String> paramsIt = params.getParameterNamesIterator();
>> -    while(paramsIt.hasNext()) {
>> +    while (paramsIt.hasNext()) {
>>        String param = paramsIt.next();
>> -      if(param.indexOf(".shards") > -1) {
>> +      if (param.indexOf(".shards") > -1) {
>>          String collection = param.split("\\.")[0];
>>          String shardString = params.get(param);
>>          String[] shards = shardString.split(",");
>>          List<String> shardList = new ArrayList();
>> -        for(String shard : shards) {
>> +        for (String shard : shards) {
>>            shardList.add(shard);
>>          }
>>          collectionShards.put(collection, shardList);
>>        }
>>      }
>>
>> -    if(collectionShards.size() > 0) {
>> +    if (collectionShards.size() > 0) {
>>        return collectionShards;
>>      } else {
>>        return null;
>>
>> http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
>> ----------------------------------------------------------------------
>> diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
>> index ed45ee9..065335b 100644
>> --- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
>> +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
>> @@ -18,30 +18,72 @@ package org.apache.solr.client.solrj.io.eval;
>>
>>  import java.io.IOException;
>>  import java.util.ArrayList;
>> +import java.util.Comparator;
>>  import java.util.List;
>> +import java.util.Locale;
>> +import java.util.stream.Collectors;
>>
>>  import org.apache.solr.client.solrj.io.Tuple;
>>  import org.apache.solr.client.solrj.io.stream.expr.Explanation;
>>  import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
>>  import org.apache.solr.client.solrj.io.stream.expr.Expressible;
>>  import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
>> +import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionNamedParameter;
>>  import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
>> +import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionValue;
>>  import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
>>
>> +import com.google.common.collect.Lists;
>> +
>>  public class ArrayEvaluator extends ComplexEvaluator implements Expressible {
>>
>>    private static final long serialVersionUID = 1;
>> -
>> +  private String sortOrder;
>> +
>>    public ArrayEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
>> -    super(expression, factory);
>> +    super(expression, factory, Lists.newArrayList("sort"));
>> +
>> +    sortOrder = extractSortOrder(expression, factory);
>> +  }
>> +
>> +  private String extractSortOrder(StreamExpression expression, StreamFactory factory) throws IOException{
>> +    StreamExpressionNamedParameter sortParam = factory.getNamedOperand(expression, "sort");
>> +    if(null == sortParam){
>> +      return null; // this is ok
>> +    }
>> +
>> +    if(sortParam.getParameter() instanceof StreamExpressionValue){
>> +      String sortOrder = ((StreamExpressionValue)sortParam.getParameter()).getValue().trim().toLowerCase(Locale.ROOT);
>> +      if("asc".equals(sortOrder) || "desc".equals(sortOrder)){
>> +        return sortOrder;
>> +      }
>> +    }
>> +
>> +    throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - invalid 'sort' parameter - expecting either 'asc' or 'desc'", expression));
>>    }
>>
>>    public List<Object> evaluate(Tuple tuple) throws IOException {
>>      List<Object> list = new ArrayList<>();
>>      for(StreamEvaluator subEvaluator : subEvaluators) {
>> -      Object value = (Number)subEvaluator.evaluate(tuple);
>> +      Object value = subEvaluator.evaluate(tuple);
>> +
>> +      // if we want sorting but the evaluated value is not comparable then we have an error
>> +      if(null != sortOrder && !(value instanceof Comparable<?>)){
>> +        String message = String.format(Locale.ROOT,"Failed to evaluate to a comparable object - evaluator '%s' resulted in type '%s' and value '%s'",
>> +            subEvaluator.toExpression(constructingFactory),
>> +            value.getClass().getName(),
>> +            value.toString());
>> +        throw new IOException(message);
>> +      }
>> +
>>        list.add(value);
>>      }
>> +
>> +    if(null != sortOrder){
>> +      // Because of the type checking above we know that the value is at least Comparable
>> +      Comparator<Comparable> comparator = "asc".equals(sortOrder) ? (left,right) -> left.compareTo(right) : (left,right) -> right.compareTo(left);
>> +      list = list.stream().map(value -> (Comparable<Object>)value).sorted(comparator).collect(Collectors.toList());
>> +    }
>>
>>      return list;
>>    }
>>
>> http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java
>> ----------------------------------------------------------------------
>> diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java
>> deleted file mode 100644
>> index dabc615..0000000
>> --- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java
>> +++ /dev/null
>> @@ -1,77 +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.client.solrj.io.eval;
>> -
>> -import java.io.IOException;
>> -import java.util.ArrayList;
>> -import java.util.Collections;
>> -import java.util.Comparator;
>> -import java.util.List;
>> -
>> -import org.apache.solr.client.solrj.io.Tuple;
>> -import org.apache.solr.client.solrj.io.stream.expr.Explanation;
>> -import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
>> -import org.apache.solr.client.solrj.io.stream.expr.Expressible;
>> -import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
>> -import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
>> -import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
>> -
>> -public class ArraySortEvaluator extends ComplexEvaluator implements Expressible {
>> -
>> -  private static final long serialVersionUID = 1;
>> -
>> -  public ArraySortEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
>> -    super(expression, factory);
>> -  }
>> -
>> -  public List<Number> evaluate(Tuple tuple) throws IOException {
>> -
>> -    if(subEvaluators.size() != 1) {
>> -      throw new IOException("Array sort evaluator expects 1 parameters found: "+subEvaluators.size());
>> -    }
>> -
>> -    StreamEvaluator colEval1 = subEvaluators.get(0);
>> -
>> -    List<Number> numbers1 = (List<Number>)colEval1.evaluate(tuple);
>> -    List<Number> numbers2 = new ArrayList();
>> -    numbers2.addAll(numbers1);
>> -    Collections.sort(numbers2, new Comparator<Number>() {
>> -      @Override
>> -      public int compare(Number o1, Number o2) {
>> -        Double d1 = o1.doubleValue();
>> -        Double d2 = o2.doubleValue();
>> -        return d1.compareTo(d2);
>> -      }
>> -    });
>> -    return numbers2;
>> -  }
>> -
>> -  @Override
>> -  public StreamExpressionParameter toExpression(StreamFactory factory) throws IOException {
>> -    StreamExpression expression = new StreamExpression(factory.getFunctionName(getClass()));
>> -    return expression;
>> -  }
>> -
>> -  @Override
>> -  public Explanation toExplanation(StreamFactory factory) throws IOException {
>> -    return new Explanation(nodeId.toString())
>> -        .withExpressionType(ExpressionType.EVALUATOR)
>> -        .withFunctionName(factory.getFunctionName(getClass()))
>> -        .withImplementingClass(getClass().getName())
>> -        .withExpression(toExpression(factory).toString());
>> -  }
>> -}
>> \ No newline at end of file
>>
>> http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
>> ----------------------------------------------------------------------
>> diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
>> index ea4c88c..ca1f0de 100644
>> --- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
>> +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
>> @@ -20,7 +20,9 @@ import java.io.IOException;
>>  import java.util.ArrayList;
>>  import java.util.List;
>>  import java.util.Locale;
>> +import java.util.Set;
>>  import java.util.UUID;
>> +import java.util.stream.Collectors;
>>
>>  import org.apache.solr.client.solrj.io.stream.StreamContext;
>>  import org.apache.solr.client.solrj.io.stream.expr.Explanation;
>> @@ -40,6 +42,10 @@ public abstract class ComplexEvaluator implements StreamEvaluator {
>>    protected List<StreamEvaluator> subEvaluators = new ArrayList<StreamEvaluator>();
>>
>>    public ComplexEvaluator(StreamExpression expression, StreamFactory factory) throws IOException{
>> +    this(expression, factory, new ArrayList<>());
>> +  }
>> +
>> +  public ComplexEvaluator(StreamExpression expression, StreamFactory factory, List<String> ignoredNamedParameters) throws IOException{
>>      constructingFactory = factory;
>>
>>      // We have to do this because order of the parameters matter
>> @@ -75,8 +81,16 @@ public abstract class ComplexEvaluator implements StreamEvaluator {
>>        }
>>      }
>>
>> -    if(expression.getParameters().size() != subEvaluators.size()){
>> -      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - unknown operands found - expecting only StreamEvaluators or field names", expression));
>> +    Set<String> namedParameters = factory.getNamedOperands(expression).stream().map(param -> param.getName()).collect(Collectors.toSet());
>> +    long ignorableCount = ignoredNamedParameters.stream().filter(name -> namedParameters.contains(name)).count();
>> +
>> +    if(0 != expression.getParameters().size() - subEvaluators.size() - ignorableCount){
>> +      if(namedParameters.isEmpty()){
>> +        throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - unknown operands found - expecting only StreamEvaluators or field names", expression));
>> +      }
>> +      else{
>> +        throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - unknown operands found - expecting only StreamEvaluators, field names, or named parameters [%s]", expression, namedParameters.stream().collect(Collectors.joining(","))));
>> +      }
>>      }
>>    }
>>
>>
>> http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java
>> ----------------------------------------------------------------------
>> diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java
>> new file mode 100644
>> index 0000000..36e5e78
>> --- /dev/null
>> +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java
>> @@ -0,0 +1,155 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one or more
>> + * contributor license agreements.  See the NOTICE file distributed with
>> + * this work for additional information regarding copyright ownership.
>> + * The ASF licenses this file to You under the Apache License, Version 2.0
>> + * (the "License"); you may not use this file except in compliance with
>> + * the License.  You may obtain a copy of the License at
>> + *
>> + *     http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS 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.client.solrj.io.stream.eval;
>> +
>> +import java.io.IOException;
>> +import java.util.HashMap;
>> +import java.util.List;
>> +import java.util.Map;
>> +
>> +import org.apache.lucene.util.LuceneTestCase;
>> +import org.apache.solr.client.solrj.io.Tuple;
>> +import org.apache.solr.client.solrj.io.eval.ArrayEvaluator;
>> +import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
>> +import org.apache.solr.client.solrj.io.stream.StreamContext;
>> +import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
>> +import org.junit.Test;
>> +
>> +import junit.framework.Assert;
>> +
>> +public class ArrayEvaluatorTest extends LuceneTestCase {
>> +
>> +  StreamFactory factory;
>> +  Map<String, Object> values;
>> +
>> +  public ArrayEvaluatorTest() {
>> +    super();
>> +
>> +    factory = new StreamFactory()
>> +      .withFunctionName("array", ArrayEvaluator.class);
>> +    values = new HashMap<String,Object>();
>> +  }
>> +
>> +  @Test
>> +  public void arrayLongSortAscTest() throws IOException{
>> +    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=asc)");
>> +    StreamContext context = new StreamContext();
>> +    evaluator.setStreamContext(context);
>> +    Object result;
>> +
>> +    values.put("a", 1L);
>> +    values.put("b", 3L);
>> +    values.put("c", 2L);
>> +
>> +    result = evaluator.evaluate(new Tuple(values));
>> +
>> +    Assert.assertTrue(result instanceof List<?>);
>> +
>> +    Assert.assertEquals(3, ((List<?>)result).size());
>> +    Assert.assertEquals(1L, ((List<?>)result).get(0));
>> +    Assert.assertEquals(2L, ((List<?>)result).get(1));
>> +    Assert.assertEquals(3L, ((List<?>)result).get(2));
>> +  }
>> +
>> +  @Test
>> +  public void arrayLongSortDescTest() throws IOException{
>> +    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=desc)");
>> +    StreamContext context = new StreamContext();
>> +    evaluator.setStreamContext(context);
>> +    Object result;
>> +
>> +    values.put("a", 1L);
>> +    values.put("b", 3L);
>> +    values.put("c", 2L);
>> +
>> +    result = evaluator.evaluate(new Tuple(values));
>> +
>> +    Assert.assertTrue(result instanceof List<?>);
>> +
>> +    Assert.assertEquals(3, ((List<?>)result).size());
>> +    Assert.assertEquals(3L, ((List<?>)result).get(0));
>> +    Assert.assertEquals(2L, ((List<?>)result).get(1));
>> +    Assert.assertEquals(1L, ((List<?>)result).get(2));
>> +  }
>> +
>> +  @Test
>> +  public void arrayStringSortAscTest() throws IOException{
>> +    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=asc)");
>> +    StreamContext context = new StreamContext();
>> +    evaluator.setStreamContext(context);
>> +    Object result;
>> +
>> +    values.put("a", "a");
>> +    values.put("b", "c");
>> +    values.put("c", "b");
>> +
>> +    result = evaluator.evaluate(new Tuple(values));
>> +
>> +    Assert.assertTrue(result instanceof List<?>);
>> +
>> +    Assert.assertEquals(3, ((List<?>)result).size());
>> +    Assert.assertEquals("a", ((List<?>)result).get(0));
>> +    Assert.assertEquals("b", ((List<?>)result).get(1));
>> +    Assert.assertEquals("c", ((List<?>)result).get(2));
>> +  }
>> +
>> +  @Test
>> +  public void arrayStringSortDescTest() throws IOException{
>> +    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=desc)");
>> +    StreamContext context = new StreamContext();
>> +    evaluator.setStreamContext(context);
>> +    Object result;
>> +
>> +    values.put("a", "a");
>> +    values.put("b", "c");
>> +    values.put("c", "b");
>> +
>> +    result = evaluator.evaluate(new Tuple(values));
>> +
>> +    Assert.assertTrue(result instanceof List<?>);
>> +
>> +    Assert.assertEquals(3, ((List<?>)result).size());
>> +    Assert.assertEquals("c", ((List<?>)result).get(0));
>> +    Assert.assertEquals("b", ((List<?>)result).get(1));
>> +    Assert.assertEquals("a", ((List<?>)result).get(2));
>> +  }
>> +
>> +  @Test
>> +  public void arrayStringUnsortedTest() throws IOException{
>> +    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c)");
>> +    StreamContext context = new StreamContext();
>> +    evaluator.setStreamContext(context);
>> +    Object result;
>> +
>> +    values.put("a", "a");
>> +    values.put("b", "c");
>> +    values.put("c", "b");
>> +
>> +    result = evaluator.evaluate(new Tuple(values));
>> +
>> +    Assert.assertTrue(result instanceof List<?>);
>> +
>> +    Assert.assertEquals(3, ((List<?>)result).size());
>> +    Assert.assertEquals("a", ((List<?>)result).get(0));
>> +    Assert.assertEquals("c", ((List<?>)result).get(1));
>> +    Assert.assertEquals("b", ((List<?>)result).get(2));
>> +  }
>> +
>> +
>> +
>> +
>> +}
>>
>
>
>
> --
> Regards,
> Shalin Shekhar Mangar.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@lucene.apache.org
> For additional commands, e-mail: dev-help@lucene.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@lucene.apache.org
For additional commands, e-mail: dev-help@lucene.apache.org


Re: [6/8] lucene-solr:master: SOLR-10882: ArrayEvaluator now works with all types and allows sorts (deleted ArraySortEvaluator)

Posted by Shalin Shekhar Mangar <sh...@gmail.com>.
This commit has broken StreamExpressionTest.testArraySort

On Sun, Jun 18, 2017 at 9:24 PM,  <dp...@apache.org> wrote:
> SOLR-10882: ArrayEvaluator now works with all types and allows sorts (deleted ArraySortEvaluator)
>
>
> Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
> Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/113459a8
> Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/113459a8
> Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/113459a8
>
> Branch: refs/heads/master
> Commit: 113459a840e8ca3482ebd36a76dda551fac885ec
> Parents: 5fca6a4
> Author: Dennis Gove <dp...@gmail.com>
> Authored: Thu Jun 15 22:10:37 2017 -0400
> Committer: Dennis Gove <dp...@gmail.com>
> Committed: Sun Jun 18 11:50:58 2017 -0400
>
> ----------------------------------------------------------------------
>  .../org/apache/solr/handler/StreamHandler.java  | 479 +++++++++----------
>  .../client/solrj/io/eval/ArrayEvaluator.java    |  48 +-
>  .../solrj/io/eval/ArraySortEvaluator.java       |  77 ---
>  .../client/solrj/io/eval/ComplexEvaluator.java  |  18 +-
>  .../io/stream/eval/ArrayEvaluatorTest.java      | 155 ++++++
>  5 files changed, 452 insertions(+), 325 deletions(-)
> ----------------------------------------------------------------------
>
>
> http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
> ----------------------------------------------------------------------
> diff --git a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
> index 7889bf7..4616204 100644
> --- a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
> +++ b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
> @@ -77,7 +77,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>    private StreamFactory streamFactory = new StreamFactory();
>    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
>    private String coreName;
> -  private Map<String, DaemonStream> daemons = Collections.synchronizedMap(new HashMap());
> +  private Map<String,DaemonStream> daemons = Collections.synchronizedMap(new HashMap());
>
>    @Override
>    public PermissionNameProvider.Name getPermissionName(AuthorizationContext request) {
> @@ -89,202 +89,202 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>    }
>
>    public void inform(SolrCore core) {
> -
> -    /* The stream factory will always contain the zkUrl for the given collection
> -     * Adds default streams with their corresponding function names. These
> -     * defaults can be overridden or added to in the solrConfig in the stream
> -     * RequestHandler def. Example config override
> -     *  <lst name="streamFunctions">
> -     *    <str name="group">org.apache.solr.client.solrj.io.stream.ReducerStream</str>
> -     *    <str name="count">org.apache.solr.client.solrj.io.stream.RecordCountStream</str>
> -     *  </lst>
> -     * */
> +
> +    /*
> +     * The stream factory will always contain the zkUrl for the given collection Adds default streams with their
> +     * corresponding function names. These defaults can be overridden or added to in the solrConfig in the stream
> +     * RequestHandler def. Example config override
> +     * <lst name="streamFunctions">
> +     *  <str name="group">org.apache.solr.client.solrj.io.stream.ReducerStream</str>
> +     *  <str name="count">org.apache.solr.client.solrj.io.stream.RecordCountStream</str>
> +     * </lst>
> +     */
>
>      String defaultCollection;
>      String defaultZkhost;
>      CoreContainer coreContainer = core.getCoreContainer();
>      this.coreName = core.getName();
>
> -    if(coreContainer.isZooKeeperAware()) {
> +    if (coreContainer.isZooKeeperAware()) {
>        defaultCollection = core.getCoreDescriptor().getCollectionName();
>        defaultZkhost = core.getCoreContainer().getZkController().getZkServerAddress();
>        streamFactory.withCollectionZkHost(defaultCollection, defaultZkhost);
>        streamFactory.withDefaultZkHost(defaultZkhost);
>        modelCache = new ModelCache(250,
> -                                  defaultZkhost,
> -                                  clientCache);
> -    }
> -
> -     streamFactory
> -       // source streams
> -      .withFunctionName("search", CloudSolrStream.class)
> -      .withFunctionName("facet", FacetStream.class)
> -      .withFunctionName("update", UpdateStream.class)
> -      .withFunctionName("jdbc", JDBCStream.class)
> -      .withFunctionName("topic", TopicStream.class)
> -      .withFunctionName("commit", CommitStream.class)
> -      .withFunctionName("random", RandomStream.class)
> -      .withFunctionName("knn", KnnStream.class)
> -
> -      // decorator streams
> -      .withFunctionName("merge", MergeStream.class)
> -      .withFunctionName("unique", UniqueStream.class)
> -      .withFunctionName("top", RankStream.class)
> -      .withFunctionName("group", GroupOperation.class)
> -      .withFunctionName("reduce", ReducerStream.class)
> -      .withFunctionName("parallel", ParallelStream.class)
> -      .withFunctionName("rollup", RollupStream.class)
> -      .withFunctionName("stats", StatsStream.class)
> -      .withFunctionName("innerJoin", InnerJoinStream.class)
> -      .withFunctionName("leftOuterJoin", LeftOuterJoinStream.class)
> -      .withFunctionName("hashJoin", HashJoinStream.class)
> -      .withFunctionName("outerHashJoin", OuterHashJoinStream.class)
> -      .withFunctionName("intersect", IntersectStream.class)
> -      .withFunctionName("complement", ComplementStream.class)
> -      .withFunctionName(SORT, SortStream.class)
> -      .withFunctionName("train", TextLogitStream.class)
> -      .withFunctionName("features", FeaturesSelectionStream.class)
> -      .withFunctionName("daemon", DaemonStream.class)
> -      .withFunctionName("shortestPath", ShortestPathStream.class)
> -      .withFunctionName("gatherNodes", GatherNodesStream.class)
> -      .withFunctionName("nodes", GatherNodesStream.class)
> -      .withFunctionName("select", SelectStream.class)
> -      .withFunctionName("shortestPath", ShortestPathStream.class)
> -      .withFunctionName("gatherNodes", GatherNodesStream.class)
> -      .withFunctionName("nodes", GatherNodesStream.class)
> -      .withFunctionName("scoreNodes", ScoreNodesStream.class)
> -      .withFunctionName("model", ModelStream.class)
> -      .withFunctionName("classify", ClassifyStream.class)
> -      .withFunctionName("fetch", FetchStream.class)
> -      .withFunctionName("executor", ExecutorStream.class)
> -      .withFunctionName("null", NullStream.class)
> -      .withFunctionName("priority", PriorityStream.class)
> -         .withFunctionName("significantTerms", SignificantTermsStream.class)
> -      .withFunctionName("cartesianProduct", CartesianProductStream.class)
> -         .withFunctionName("shuffle", ShuffleStream.class)
> -         .withFunctionName("calc", CalculatorStream.class)
> -      .withFunctionName("eval",EvalStream.class)
> -      .withFunctionName("echo", EchoStream.class)
> -      .withFunctionName("cell", CellStream.class)
> -      .withFunctionName("list", ListStream.class)
> -      .withFunctionName("let", LetStream.class)
> -      .withFunctionName("get", GetStream.class)
> -      .withFunctionName("timeseries", TimeSeriesStream.class)
> -      .withFunctionName("tuple", TupStream.class)
> -      .withFunctionName("sql", SqlStream.class)
> -      .withFunctionName("col", ColumnEvaluator.class)
> -      .withFunctionName("predict", PredictEvaluator.class)
> -      .withFunctionName("regress", RegressionEvaluator.class)
> -      .withFunctionName("cov", CovarianceEvaluator.class)
> -      .withFunctionName("conv", ConvolutionEvaluator.class)
> -      .withFunctionName("normalize", NormalizeEvaluator.class)
> -      .withFunctionName("rev", ReverseEvaluator.class)
> -      .withFunctionName("length", LengthEvaluator.class)
> -      .withFunctionName("rank", RankEvaluator.class)
> -      .withFunctionName("scale", ScaleEvaluator.class)
> -      .withFunctionName("distance", DistanceEvaluator.class)
> -      .withFunctionName("copyOf", CopyOfEvaluator.class)
> -      .withFunctionName("copyOfRange", CopyOfRangeEvaluator.class)
> -      .withFunctionName("percentile", PercentileEvaluator.class)
> -      .withFunctionName("empiricalDistribution", EmpiricalDistributionEvaluator.class)
> -      .withFunctionName("cumulativeProbability", CumulativeProbabilityEvaluator.class)
> -      .withFunctionName("describe", DescribeEvaluator.class)
> -      .withFunctionName("finddelay", FindDelayEvaluator.class)
> -      .withFunctionName("sequence", SequenceEvaluator.class)
> -      .withFunctionName("array", ArrayEvaluator.class)
> -      .withFunctionName("hist", HistogramEvaluator.class)
> -      .withFunctionName("anova", AnovaEvaluator.class)
> -      .withFunctionName("movingAvg", MovingAverageEvaluator.class)
> -      .withFunctionName("arraySort", ArraySortEvaluator.class)
> -
> -      // metrics
> -         .withFunctionName("min", MinMetric.class)
> -      .withFunctionName("max", MaxMetric.class)
> -      .withFunctionName("avg", MeanMetric.class)
> -      .withFunctionName("sum", SumMetric.class)
> -      .withFunctionName("count", CountMetric.class)
> -
> -      // tuple manipulation operations
> -         .withFunctionName("replace", ReplaceOperation.class)
> -      .withFunctionName("concat", ConcatOperation.class)
> -
> -      // stream reduction operations
> -         .withFunctionName("group", GroupOperation.class)
> -      .withFunctionName("distinct", DistinctOperation.class)
> -      .withFunctionName("having", HavingStream.class)
> -
> -      // Stream Evaluators
> -         .withFunctionName("val", RawValueEvaluator.class)
> -
> -      // Boolean Stream Evaluators
> -         .withFunctionName("and", AndEvaluator.class)
> -      .withFunctionName("eor", ExclusiveOrEvaluator.class)
> -      .withFunctionName("eq", EqualsEvaluator.class)
> -      .withFunctionName("gt", GreaterThanEvaluator.class)
> -      .withFunctionName("gteq", GreaterThanEqualToEvaluator.class)
> -      .withFunctionName("lt", LessThanEvaluator.class)
> -      .withFunctionName("lteq", LessThanEqualToEvaluator.class)
> -      .withFunctionName("not", NotEvaluator.class)
> -         .withFunctionName("or", OrEvaluator.class)
> -
> -      // Date Time Evaluators
> -         .withFunctionName(TemporalEvaluatorYear.FUNCTION_NAME, TemporalEvaluatorYear.class)
> -      .withFunctionName(TemporalEvaluatorMonth.FUNCTION_NAME, TemporalEvaluatorMonth.class)
> -      .withFunctionName(TemporalEvaluatorDay.FUNCTION_NAME, TemporalEvaluatorDay.class)
> -      .withFunctionName(TemporalEvaluatorDayOfYear.FUNCTION_NAME, TemporalEvaluatorDayOfYear.class)
> -         .withFunctionName(TemporalEvaluatorHour.FUNCTION_NAME, TemporalEvaluatorHour.class)
> -      .withFunctionName(TemporalEvaluatorMinute.FUNCTION_NAME, TemporalEvaluatorMinute.class)
> -         .withFunctionName(TemporalEvaluatorSecond.FUNCTION_NAME, TemporalEvaluatorSecond.class)
> -      .withFunctionName(TemporalEvaluatorEpoch.FUNCTION_NAME, TemporalEvaluatorEpoch.class)
> -      .withFunctionName(TemporalEvaluatorWeek.FUNCTION_NAME, TemporalEvaluatorWeek.class)
> -         .withFunctionName(TemporalEvaluatorQuarter.FUNCTION_NAME, TemporalEvaluatorQuarter.class)
> -         .withFunctionName(TemporalEvaluatorDayOfQuarter.FUNCTION_NAME, TemporalEvaluatorDayOfQuarter.class)
> -
> -      // Number Stream Evaluators
> -         .withFunctionName("abs", AbsoluteValueEvaluator.class)
> -      .withFunctionName("add", AddEvaluator.class)
> -      .withFunctionName("div", DivideEvaluator.class)
> -      .withFunctionName("mult", MultiplyEvaluator.class)
> -      .withFunctionName("sub", SubtractEvaluator.class)
> -      .withFunctionName("log", NaturalLogEvaluator.class)
> -      .withFunctionName("pow", PowerEvaluator.class)
> -      .withFunctionName("mod", ModuloEvaluator.class)
> -         .withFunctionName("ceil", CeilingEvaluator.class)
> -      .withFunctionName("floor", FloorEvaluator.class)
> -      .withFunctionName("sin", SineEvaluator.class)
> -      .withFunctionName("asin", ArcSineEvaluator.class)
> -      .withFunctionName("sinh", HyperbolicSineEvaluator.class)
> -      .withFunctionName("cos", CosineEvaluator.class)
> -      .withFunctionName("acos", ArcCosineEvaluator.class)
> -      .withFunctionName("cosh", HyperbolicCosineEvaluator.class)
> -      .withFunctionName("tan", TangentEvaluator.class)
> -      .withFunctionName("atan", ArcTangentEvaluator.class)
> -      .withFunctionName("tanh", HyperbolicTangentEvaluator.class)
> -         .withFunctionName("round", RoundEvaluator.class)
> -      .withFunctionName("sqrt", SquareRootEvaluator.class)
> -      .withFunctionName("cbrt", CubedRootEvaluator.class)
> -      .withFunctionName("coalesce", CoalesceEvaluator.class)
> -      .withFunctionName("uuid", UuidEvaluator.class)
> -      .withFunctionName("corr", CorrelationEvaluator.class)
> -
> -
> -      // Conditional Stream Evaluators
> -         .withFunctionName("if", IfThenElseEvaluator.class)
> -         .withFunctionName("analyze", AnalyzeEvaluator.class)
> -         .withFunctionName("convert", ConversionEvaluator.class)
> -      ;
> -
> -     // This pulls all the overrides and additions from the config
> -     List<PluginInfo> pluginInfos = core.getSolrConfig().getPluginInfos(Expressible.class.getName());
> -     for (PluginInfo pluginInfo : pluginInfos) {
> -       Class<? extends Expressible> clazz = core.getMemClassLoader().findClass(pluginInfo.className, Expressible.class);
> -       streamFactory.withFunctionName(pluginInfo.name, clazz);
> -     }
> +          defaultZkhost,
> +          clientCache);
> +    }
> +
> +    streamFactory
> +        // source streams
> +        .withFunctionName("search", CloudSolrStream.class)
> +        .withFunctionName("facet", FacetStream.class)
> +        .withFunctionName("update", UpdateStream.class)
> +        .withFunctionName("jdbc", JDBCStream.class)
> +        .withFunctionName("topic", TopicStream.class)
> +        .withFunctionName("commit", CommitStream.class)
> +        .withFunctionName("random", RandomStream.class)
> +        .withFunctionName("knn", KnnStream.class)
> +
> +        // decorator streams
> +        .withFunctionName("merge", MergeStream.class)
> +        .withFunctionName("unique", UniqueStream.class)
> +        .withFunctionName("top", RankStream.class)
> +        .withFunctionName("group", GroupOperation.class)
> +        .withFunctionName("reduce", ReducerStream.class)
> +        .withFunctionName("parallel", ParallelStream.class)
> +        .withFunctionName("rollup", RollupStream.class)
> +        .withFunctionName("stats", StatsStream.class)
> +        .withFunctionName("innerJoin", InnerJoinStream.class)
> +        .withFunctionName("leftOuterJoin", LeftOuterJoinStream.class)
> +        .withFunctionName("hashJoin", HashJoinStream.class)
> +        .withFunctionName("outerHashJoin", OuterHashJoinStream.class)
> +        .withFunctionName("intersect", IntersectStream.class)
> +        .withFunctionName("complement", ComplementStream.class)
> +        .withFunctionName(SORT, SortStream.class)
> +        .withFunctionName("train", TextLogitStream.class)
> +        .withFunctionName("features", FeaturesSelectionStream.class)
> +        .withFunctionName("daemon", DaemonStream.class)
> +        .withFunctionName("shortestPath", ShortestPathStream.class)
> +        .withFunctionName("gatherNodes", GatherNodesStream.class)
> +        .withFunctionName("nodes", GatherNodesStream.class)
> +        .withFunctionName("select", SelectStream.class)
> +        .withFunctionName("shortestPath", ShortestPathStream.class)
> +        .withFunctionName("gatherNodes", GatherNodesStream.class)
> +        .withFunctionName("nodes", GatherNodesStream.class)
> +        .withFunctionName("scoreNodes", ScoreNodesStream.class)
> +        .withFunctionName("model", ModelStream.class)
> +        .withFunctionName("classify", ClassifyStream.class)
> +        .withFunctionName("fetch", FetchStream.class)
> +        .withFunctionName("executor", ExecutorStream.class)
> +        .withFunctionName("null", NullStream.class)
> +        .withFunctionName("priority", PriorityStream.class)
> +        .withFunctionName("significantTerms", SignificantTermsStream.class)
> +        .withFunctionName("cartesianProduct", CartesianProductStream.class)
> +        .withFunctionName("shuffle", ShuffleStream.class)
> +        .withFunctionName("calc", CalculatorStream.class)
> +        .withFunctionName("eval", EvalStream.class)
> +        .withFunctionName("echo", EchoStream.class)
> +        .withFunctionName("cell", CellStream.class)
> +        .withFunctionName("list", ListStream.class)
> +        .withFunctionName("let", LetStream.class)
> +        .withFunctionName("get", GetStream.class)
> +        .withFunctionName("timeseries", TimeSeriesStream.class)
> +        .withFunctionName("tuple", TupStream.class)
> +        .withFunctionName("sql", SqlStream.class)
> +
> +        // metrics
> +        .withFunctionName("min", MinMetric.class)
> +        .withFunctionName("max", MaxMetric.class)
> +        .withFunctionName("avg", MeanMetric.class)
> +        .withFunctionName("sum", SumMetric.class)
> +        .withFunctionName("count", CountMetric.class)
> +
> +        // tuple manipulation operations
> +        .withFunctionName("replace", ReplaceOperation.class)
> +        .withFunctionName("concat", ConcatOperation.class)
> +
> +        // stream reduction operations
> +        .withFunctionName("group", GroupOperation.class)
> +        .withFunctionName("distinct", DistinctOperation.class)
> +        .withFunctionName("having", HavingStream.class)
> +
> +        // Stream Evaluators
> +        .withFunctionName("val", RawValueEvaluator.class)
> +
> +        // New Evaluators
> +        .withFunctionName("anova", AnovaEvaluator.class)
> +        .withFunctionName("array", ArrayEvaluator.class)
> +        .withFunctionName("col", ColumnEvaluator.class)
> +        .withFunctionName("conv", ConvolutionEvaluator.class)
> +        .withFunctionName("copyOf", CopyOfEvaluator.class)
> +        .withFunctionName("copyOfRange", CopyOfRangeEvaluator.class)
> +        .withFunctionName("cov", CovarianceEvaluator.class)
> +        .withFunctionName("cumulativeProbability", CumulativeProbabilityEvaluator.class)
> +        .withFunctionName("describe", DescribeEvaluator.class)
> +        .withFunctionName("distance", DistanceEvaluator.class)
> +        .withFunctionName("empiricalDistribution", EmpiricalDistributionEvaluator.class)
> +        .withFunctionName("finddelay", FindDelayEvaluator.class)
> +        .withFunctionName("hist", HistogramEvaluator.class)
> +        .withFunctionName("length", LengthEvaluator.class)
> +        .withFunctionName("movingAvg", MovingAverageEvaluator.class)
> +        .withFunctionName("normalize", NormalizeEvaluator.class)
> +        .withFunctionName("percentile", PercentileEvaluator.class)
> +        .withFunctionName("predict", PredictEvaluator.class)
> +        .withFunctionName("rank", RankEvaluator.class)
> +        .withFunctionName("regress", RegressionEvaluator.class)
> +        .withFunctionName("rev", ReverseEvaluator.class)
> +        .withFunctionName("scale", ScaleEvaluator.class)
> +        .withFunctionName("sequence", SequenceEvaluator.class)
> +
>
> +        // Boolean Stream Evaluators
> +        .withFunctionName("and", AndEvaluator.class)
> +        .withFunctionName("eor", ExclusiveOrEvaluator.class)
> +        .withFunctionName("eq", EqualsEvaluator.class)
> +        .withFunctionName("gt", GreaterThanEvaluator.class)
> +        .withFunctionName("gteq", GreaterThanEqualToEvaluator.class)
> +        .withFunctionName("lt", LessThanEvaluator.class)
> +        .withFunctionName("lteq", LessThanEqualToEvaluator.class)
> +        .withFunctionName("not", NotEvaluator.class)
> +        .withFunctionName("or", OrEvaluator.class)
> +
> +        // Date Time Evaluators
> +        .withFunctionName(TemporalEvaluatorYear.FUNCTION_NAME, TemporalEvaluatorYear.class)
> +        .withFunctionName(TemporalEvaluatorMonth.FUNCTION_NAME, TemporalEvaluatorMonth.class)
> +        .withFunctionName(TemporalEvaluatorDay.FUNCTION_NAME, TemporalEvaluatorDay.class)
> +        .withFunctionName(TemporalEvaluatorDayOfYear.FUNCTION_NAME, TemporalEvaluatorDayOfYear.class)
> +        .withFunctionName(TemporalEvaluatorHour.FUNCTION_NAME, TemporalEvaluatorHour.class)
> +        .withFunctionName(TemporalEvaluatorMinute.FUNCTION_NAME, TemporalEvaluatorMinute.class)
> +        .withFunctionName(TemporalEvaluatorSecond.FUNCTION_NAME, TemporalEvaluatorSecond.class)
> +        .withFunctionName(TemporalEvaluatorEpoch.FUNCTION_NAME, TemporalEvaluatorEpoch.class)
> +        .withFunctionName(TemporalEvaluatorWeek.FUNCTION_NAME, TemporalEvaluatorWeek.class)
> +        .withFunctionName(TemporalEvaluatorQuarter.FUNCTION_NAME, TemporalEvaluatorQuarter.class)
> +        .withFunctionName(TemporalEvaluatorDayOfQuarter.FUNCTION_NAME, TemporalEvaluatorDayOfQuarter.class)
> +
> +        // Number Stream Evaluators
> +        .withFunctionName("abs", AbsoluteValueEvaluator.class)
> +        .withFunctionName("add", AddEvaluator.class)
> +        .withFunctionName("div", DivideEvaluator.class)
> +        .withFunctionName("mult", MultiplyEvaluator.class)
> +        .withFunctionName("sub", SubtractEvaluator.class)
> +        .withFunctionName("log", NaturalLogEvaluator.class)
> +        .withFunctionName("pow", PowerEvaluator.class)
> +        .withFunctionName("mod", ModuloEvaluator.class)
> +        .withFunctionName("ceil", CeilingEvaluator.class)
> +        .withFunctionName("floor", FloorEvaluator.class)
> +        .withFunctionName("sin", SineEvaluator.class)
> +        .withFunctionName("asin", ArcSineEvaluator.class)
> +        .withFunctionName("sinh", HyperbolicSineEvaluator.class)
> +        .withFunctionName("cos", CosineEvaluator.class)
> +        .withFunctionName("acos", ArcCosineEvaluator.class)
> +        .withFunctionName("cosh", HyperbolicCosineEvaluator.class)
> +        .withFunctionName("tan", TangentEvaluator.class)
> +        .withFunctionName("atan", ArcTangentEvaluator.class)
> +        .withFunctionName("tanh", HyperbolicTangentEvaluator.class)
> +        .withFunctionName("round", RoundEvaluator.class)
> +        .withFunctionName("sqrt", SquareRootEvaluator.class)
> +        .withFunctionName("cbrt", CubedRootEvaluator.class)
> +        .withFunctionName("coalesce", CoalesceEvaluator.class)
> +        .withFunctionName("uuid", UuidEvaluator.class)
> +        .withFunctionName("corr", CorrelationEvaluator.class)
> +
> +        // Conditional Stream Evaluators
> +        .withFunctionName("if", IfThenElseEvaluator.class)
> +        .withFunctionName("analyze", AnalyzeEvaluator.class)
> +        .withFunctionName("convert", ConversionEvaluator.class);
> +
> +    // This pulls all the overrides and additions from the config
> +    List<PluginInfo> pluginInfos = core.getSolrConfig().getPluginInfos(Expressible.class.getName());
> +    for (PluginInfo pluginInfo : pluginInfos) {
> +      Class<? extends Expressible> clazz = core.getMemClassLoader().findClass(pluginInfo.className, Expressible.class);
> +      streamFactory.withFunctionName(pluginInfo.name, clazz);
> +    }
> +
>      core.addCloseHook(new CloseHook() {
>        @Override
>        public void preClose(SolrCore core) {
> -        //To change body of implemented methods use File | Settings | File Templates.
> +        // To change body of implemented methods use File | Settings | File Templates.
>        }
>
>        @Override
> @@ -299,7 +299,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>      params = adjustParams(params);
>      req.setParams(params);
>
> -    if(params.get("action") != null) {
> +    if (params.get("action") != null) {
>        handleAdmin(req, rsp, params);
>        return;
>      }
> @@ -308,7 +308,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>
>      try {
>        StreamExpression streamExpression = StreamExpressionParser.parse(params.get("expr"));
> -      if(this.streamFactory.isEvaluator(streamExpression)) {
> +      if (this.streamFactory.isEvaluator(streamExpression)) {
>          StreamExpression tupleExpression = new StreamExpression("tuple");
>          tupleExpression.addParameter(new StreamExpressionNamedParameter("return-value", streamExpression));
>          tupleStream = this.streamFactory.constructStream(tupleExpression);
> @@ -316,7 +316,8 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>          tupleStream = this.streamFactory.constructStream(streamExpression);
>        }
>      } catch (Exception e) {
> -      //Catch exceptions that occur while the stream is being created. This will include streaming expression parse rules.
> +      // Catch exceptions that occur while the stream is being created. This will include streaming expression parse
> +      // rules.
>        SolrException.log(logger, e);
>        rsp.add("result-set", new DummyErrorStream(e));
>
> @@ -334,21 +335,21 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>      context.put("core", this.coreName);
>      context.put("solr-core", req.getCore());
>      tupleStream.setStreamContext(context);
> -
> +
>      // if asking for explanation then go get it
> -    if(params.getBool("explain", false)){
> +    if (params.getBool("explain", false)) {
>        rsp.add("explanation", tupleStream.toExplanation(this.streamFactory));
>      }
> -
> -    if(tupleStream instanceof DaemonStream) {
> -      DaemonStream daemonStream = (DaemonStream)tupleStream;
> -      if(daemons.containsKey(daemonStream.getId())) {
> +
> +    if (tupleStream instanceof DaemonStream) {
> +      DaemonStream daemonStream = (DaemonStream) tupleStream;
> +      if (daemons.containsKey(daemonStream.getId())) {
>          daemons.remove(daemonStream.getId()).close();
>        }
>        daemonStream.setDaemons(daemons);
> -      daemonStream.open();  //This will start the deamonStream
> +      daemonStream.open(); // This will start the deamonStream
>        daemons.put(daemonStream.getId(), daemonStream);
> -      rsp.add("result-set", new DaemonResponseStream("Deamon:"+daemonStream.getId()+" started on "+coreName));
> +      rsp.add("result-set", new DaemonResponseStream("Deamon:" + daemonStream.getId() + " started on " + coreName));
>      } else {
>        rsp.add("result-set", new TimerStream(new ExceptionStream(tupleStream)));
>      }
> @@ -356,10 +357,10 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>
>    private void handleAdmin(SolrQueryRequest req, SolrQueryResponse rsp, SolrParams params) {
>      String action = params.get("action");
> -    if("stop".equalsIgnoreCase(action)) {
> +    if ("stop".equalsIgnoreCase(action)) {
>        String id = params.get(ID);
>        DaemonStream d = daemons.get(id);
> -      if(d != null) {
> +      if (d != null) {
>          d.close();
>          rsp.add("result-set", new DaemonResponseStream("Deamon:" + id + " stopped on " + coreName));
>        } else {
> @@ -400,50 +401,46 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>      return null;
>    }
>
> -
>    public static class DummyErrorStream extends TupleStream {
>      private Exception e;
>
>      public DummyErrorStream(Exception e) {
>        this.e = e;
>      }
> +
>      public StreamComparator getStreamSort() {
>        return null;
>      }
>
> -    public void close() {
> -    }
> +    public void close() {}
>
> -    public void open() {
> -    }
> +    public void open() {}
>
> -    public void setStreamContext(StreamContext context) {
> -    }
> +    public void setStreamContext(StreamContext context) {}
>
>      public List<TupleStream> children() {
>        return null;
>      }
> -
> +
>      @Override
>      public Explanation toExplanation(StreamFactory factory) throws IOException {
>
>        return new StreamExplanation(getStreamNodeId().toString())
> -        .withFunctionName("error")
> -        .withImplementingClass(this.getClass().getName())
> -        .withExpressionType(ExpressionType.STREAM_DECORATOR)
> -        .withExpression("--non-expressible--");
> +          .withFunctionName("error")
> +          .withImplementingClass(this.getClass().getName())
> +          .withExpressionType(ExpressionType.STREAM_DECORATOR)
> +          .withExpression("--non-expressible--");
>      }
>
>      public Tuple read() {
>        String msg = e.getMessage();
>
>        Throwable t = e.getCause();
> -      while(t != null) {
> +      while (t != null) {
>          msg = t.getMessage();
>          t = t.getCause();
>        }
>
> -
>        Map m = new HashMap();
>        m.put("EOF", true);
>        m.put("EXCEPTION", msg);
> @@ -457,18 +454,16 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>      public DaemonCollectionStream(Collection<DaemonStream> col) {
>        this.it = col.iterator();
>      }
> +
>      public StreamComparator getStreamSort() {
>        return null;
>      }
>
> -    public void close() {
> -    }
> +    public void close() {}
>
> -    public void open() {
> -    }
> +    public void open() {}
>
> -    public void setStreamContext(StreamContext context) {
> -    }
> +    public void setStreamContext(StreamContext context) {}
>
>      public List<TupleStream> children() {
>        return null;
> @@ -478,14 +473,14 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>      public Explanation toExplanation(StreamFactory factory) throws IOException {
>
>        return new StreamExplanation(getStreamNodeId().toString())
> -        .withFunctionName("daemon-collection")
> -        .withImplementingClass(this.getClass().getName())
> -        .withExpressionType(ExpressionType.STREAM_DECORATOR)
> -        .withExpression("--non-expressible--");
> +          .withFunctionName("daemon-collection")
> +          .withImplementingClass(this.getClass().getName())
> +          .withExpressionType(ExpressionType.STREAM_DECORATOR)
> +          .withExpression("--non-expressible--");
>      }
> -
> +
>      public Tuple read() {
> -      if(it.hasNext()) {
> +      if (it.hasNext()) {
>          return it.next().getInfo();
>        } else {
>          Map m = new HashMap();
> @@ -502,18 +497,16 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>      public DaemonResponseStream(String message) {
>        this.message = message;
>      }
> +
>      public StreamComparator getStreamSort() {
>        return null;
>      }
>
> -    public void close() {
> -    }
> +    public void close() {}
>
> -    public void open() {
> -    }
> +    public void open() {}
>
> -    public void setStreamContext(StreamContext context) {
> -    }
> +    public void setStreamContext(StreamContext context) {}
>
>      public List<TupleStream> children() {
>        return null;
> @@ -523,10 +516,10 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>      public Explanation toExplanation(StreamFactory factory) throws IOException {
>
>        return new StreamExplanation(getStreamNodeId().toString())
> -        .withFunctionName("daemon-response")
> -        .withImplementingClass(this.getClass().getName())
> -        .withExpressionType(ExpressionType.STREAM_DECORATOR)
> -        .withExpression("--non-expressible--");
> +          .withFunctionName("daemon-response")
> +          .withImplementingClass(this.getClass().getName())
> +          .withExpressionType(ExpressionType.STREAM_DECORATOR)
> +          .withExpression("--non-expressible--");
>      }
>
>      public Tuple read() {
> @@ -537,7 +530,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>        } else {
>          sendEOF = true;
>          Map m = new HashMap();
> -        m.put("DaemonOp",message);
> +        m.put("DaemonOp", message);
>          return new Tuple(m);
>        }
>      }
> @@ -577,15 +570,15 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>      public Explanation toExplanation(StreamFactory factory) throws IOException {
>
>        return new StreamExplanation(getStreamNodeId().toString())
> -        .withFunctionName("timer")
> -        .withImplementingClass(this.getClass().getName())
> -        .withExpressionType(ExpressionType.STREAM_DECORATOR)
> -        .withExpression("--non-expressible--");
> +          .withFunctionName("timer")
> +          .withImplementingClass(this.getClass().getName())
> +          .withExpressionType(ExpressionType.STREAM_DECORATOR)
> +          .withExpression("--non-expressible--");
>      }
>
>      public Tuple read() throws IOException {
>        Tuple tuple = this.tupleStream.read();
> -      if(tuple.EOF) {
> +      if (tuple.EOF) {
>          long totalTime = (System.nanoTime() - begin) / 1000000;
>          tuple.fields.put("RESPONSE_TIME", totalTime);
>        }
> @@ -593,25 +586,25 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
>      }
>    }
>
> -  private Map<String, List<String>> getCollectionShards(SolrParams params) {
> +  private Map<String,List<String>> getCollectionShards(SolrParams params) {
>
> -    Map<String, List<String>> collectionShards = new HashMap();
> +    Map<String,List<String>> collectionShards = new HashMap();
>      Iterator<String> paramsIt = params.getParameterNamesIterator();
> -    while(paramsIt.hasNext()) {
> +    while (paramsIt.hasNext()) {
>        String param = paramsIt.next();
> -      if(param.indexOf(".shards") > -1) {
> +      if (param.indexOf(".shards") > -1) {
>          String collection = param.split("\\.")[0];
>          String shardString = params.get(param);
>          String[] shards = shardString.split(",");
>          List<String> shardList = new ArrayList();
> -        for(String shard : shards) {
> +        for (String shard : shards) {
>            shardList.add(shard);
>          }
>          collectionShards.put(collection, shardList);
>        }
>      }
>
> -    if(collectionShards.size() > 0) {
> +    if (collectionShards.size() > 0) {
>        return collectionShards;
>      } else {
>        return null;
>
> http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
> ----------------------------------------------------------------------
> diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
> index ed45ee9..065335b 100644
> --- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
> +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
> @@ -18,30 +18,72 @@ package org.apache.solr.client.solrj.io.eval;
>
>  import java.io.IOException;
>  import java.util.ArrayList;
> +import java.util.Comparator;
>  import java.util.List;
> +import java.util.Locale;
> +import java.util.stream.Collectors;
>
>  import org.apache.solr.client.solrj.io.Tuple;
>  import org.apache.solr.client.solrj.io.stream.expr.Explanation;
>  import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
>  import org.apache.solr.client.solrj.io.stream.expr.Expressible;
>  import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
> +import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionNamedParameter;
>  import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
> +import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionValue;
>  import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
>
> +import com.google.common.collect.Lists;
> +
>  public class ArrayEvaluator extends ComplexEvaluator implements Expressible {
>
>    private static final long serialVersionUID = 1;
> -
> +  private String sortOrder;
> +
>    public ArrayEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
> -    super(expression, factory);
> +    super(expression, factory, Lists.newArrayList("sort"));
> +
> +    sortOrder = extractSortOrder(expression, factory);
> +  }
> +
> +  private String extractSortOrder(StreamExpression expression, StreamFactory factory) throws IOException{
> +    StreamExpressionNamedParameter sortParam = factory.getNamedOperand(expression, "sort");
> +    if(null == sortParam){
> +      return null; // this is ok
> +    }
> +
> +    if(sortParam.getParameter() instanceof StreamExpressionValue){
> +      String sortOrder = ((StreamExpressionValue)sortParam.getParameter()).getValue().trim().toLowerCase(Locale.ROOT);
> +      if("asc".equals(sortOrder) || "desc".equals(sortOrder)){
> +        return sortOrder;
> +      }
> +    }
> +
> +    throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - invalid 'sort' parameter - expecting either 'asc' or 'desc'", expression));
>    }
>
>    public List<Object> evaluate(Tuple tuple) throws IOException {
>      List<Object> list = new ArrayList<>();
>      for(StreamEvaluator subEvaluator : subEvaluators) {
> -      Object value = (Number)subEvaluator.evaluate(tuple);
> +      Object value = subEvaluator.evaluate(tuple);
> +
> +      // if we want sorting but the evaluated value is not comparable then we have an error
> +      if(null != sortOrder && !(value instanceof Comparable<?>)){
> +        String message = String.format(Locale.ROOT,"Failed to evaluate to a comparable object - evaluator '%s' resulted in type '%s' and value '%s'",
> +            subEvaluator.toExpression(constructingFactory),
> +            value.getClass().getName(),
> +            value.toString());
> +        throw new IOException(message);
> +      }
> +
>        list.add(value);
>      }
> +
> +    if(null != sortOrder){
> +      // Because of the type checking above we know that the value is at least Comparable
> +      Comparator<Comparable> comparator = "asc".equals(sortOrder) ? (left,right) -> left.compareTo(right) : (left,right) -> right.compareTo(left);
> +      list = list.stream().map(value -> (Comparable<Object>)value).sorted(comparator).collect(Collectors.toList());
> +    }
>
>      return list;
>    }
>
> http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java
> ----------------------------------------------------------------------
> diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java
> deleted file mode 100644
> index dabc615..0000000
> --- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java
> +++ /dev/null
> @@ -1,77 +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.client.solrj.io.eval;
> -
> -import java.io.IOException;
> -import java.util.ArrayList;
> -import java.util.Collections;
> -import java.util.Comparator;
> -import java.util.List;
> -
> -import org.apache.solr.client.solrj.io.Tuple;
> -import org.apache.solr.client.solrj.io.stream.expr.Explanation;
> -import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
> -import org.apache.solr.client.solrj.io.stream.expr.Expressible;
> -import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
> -import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
> -import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
> -
> -public class ArraySortEvaluator extends ComplexEvaluator implements Expressible {
> -
> -  private static final long serialVersionUID = 1;
> -
> -  public ArraySortEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
> -    super(expression, factory);
> -  }
> -
> -  public List<Number> evaluate(Tuple tuple) throws IOException {
> -
> -    if(subEvaluators.size() != 1) {
> -      throw new IOException("Array sort evaluator expects 1 parameters found: "+subEvaluators.size());
> -    }
> -
> -    StreamEvaluator colEval1 = subEvaluators.get(0);
> -
> -    List<Number> numbers1 = (List<Number>)colEval1.evaluate(tuple);
> -    List<Number> numbers2 = new ArrayList();
> -    numbers2.addAll(numbers1);
> -    Collections.sort(numbers2, new Comparator<Number>() {
> -      @Override
> -      public int compare(Number o1, Number o2) {
> -        Double d1 = o1.doubleValue();
> -        Double d2 = o2.doubleValue();
> -        return d1.compareTo(d2);
> -      }
> -    });
> -    return numbers2;
> -  }
> -
> -  @Override
> -  public StreamExpressionParameter toExpression(StreamFactory factory) throws IOException {
> -    StreamExpression expression = new StreamExpression(factory.getFunctionName(getClass()));
> -    return expression;
> -  }
> -
> -  @Override
> -  public Explanation toExplanation(StreamFactory factory) throws IOException {
> -    return new Explanation(nodeId.toString())
> -        .withExpressionType(ExpressionType.EVALUATOR)
> -        .withFunctionName(factory.getFunctionName(getClass()))
> -        .withImplementingClass(getClass().getName())
> -        .withExpression(toExpression(factory).toString());
> -  }
> -}
> \ No newline at end of file
>
> http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
> ----------------------------------------------------------------------
> diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
> index ea4c88c..ca1f0de 100644
> --- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
> +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
> @@ -20,7 +20,9 @@ import java.io.IOException;
>  import java.util.ArrayList;
>  import java.util.List;
>  import java.util.Locale;
> +import java.util.Set;
>  import java.util.UUID;
> +import java.util.stream.Collectors;
>
>  import org.apache.solr.client.solrj.io.stream.StreamContext;
>  import org.apache.solr.client.solrj.io.stream.expr.Explanation;
> @@ -40,6 +42,10 @@ public abstract class ComplexEvaluator implements StreamEvaluator {
>    protected List<StreamEvaluator> subEvaluators = new ArrayList<StreamEvaluator>();
>
>    public ComplexEvaluator(StreamExpression expression, StreamFactory factory) throws IOException{
> +    this(expression, factory, new ArrayList<>());
> +  }
> +
> +  public ComplexEvaluator(StreamExpression expression, StreamFactory factory, List<String> ignoredNamedParameters) throws IOException{
>      constructingFactory = factory;
>
>      // We have to do this because order of the parameters matter
> @@ -75,8 +81,16 @@ public abstract class ComplexEvaluator implements StreamEvaluator {
>        }
>      }
>
> -    if(expression.getParameters().size() != subEvaluators.size()){
> -      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - unknown operands found - expecting only StreamEvaluators or field names", expression));
> +    Set<String> namedParameters = factory.getNamedOperands(expression).stream().map(param -> param.getName()).collect(Collectors.toSet());
> +    long ignorableCount = ignoredNamedParameters.stream().filter(name -> namedParameters.contains(name)).count();
> +
> +    if(0 != expression.getParameters().size() - subEvaluators.size() - ignorableCount){
> +      if(namedParameters.isEmpty()){
> +        throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - unknown operands found - expecting only StreamEvaluators or field names", expression));
> +      }
> +      else{
> +        throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - unknown operands found - expecting only StreamEvaluators, field names, or named parameters [%s]", expression, namedParameters.stream().collect(Collectors.joining(","))));
> +      }
>      }
>    }
>
>
> http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java
> ----------------------------------------------------------------------
> diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java
> new file mode 100644
> index 0000000..36e5e78
> --- /dev/null
> +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java
> @@ -0,0 +1,155 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one or more
> + * contributor license agreements.  See the NOTICE file distributed with
> + * this work for additional information regarding copyright ownership.
> + * The ASF licenses this file to You under the Apache License, Version 2.0
> + * (the "License"); you may not use this file except in compliance with
> + * the License.  You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS 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.client.solrj.io.stream.eval;
> +
> +import java.io.IOException;
> +import java.util.HashMap;
> +import java.util.List;
> +import java.util.Map;
> +
> +import org.apache.lucene.util.LuceneTestCase;
> +import org.apache.solr.client.solrj.io.Tuple;
> +import org.apache.solr.client.solrj.io.eval.ArrayEvaluator;
> +import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
> +import org.apache.solr.client.solrj.io.stream.StreamContext;
> +import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
> +import org.junit.Test;
> +
> +import junit.framework.Assert;
> +
> +public class ArrayEvaluatorTest extends LuceneTestCase {
> +
> +  StreamFactory factory;
> +  Map<String, Object> values;
> +
> +  public ArrayEvaluatorTest() {
> +    super();
> +
> +    factory = new StreamFactory()
> +      .withFunctionName("array", ArrayEvaluator.class);
> +    values = new HashMap<String,Object>();
> +  }
> +
> +  @Test
> +  public void arrayLongSortAscTest() throws IOException{
> +    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=asc)");
> +    StreamContext context = new StreamContext();
> +    evaluator.setStreamContext(context);
> +    Object result;
> +
> +    values.put("a", 1L);
> +    values.put("b", 3L);
> +    values.put("c", 2L);
> +
> +    result = evaluator.evaluate(new Tuple(values));
> +
> +    Assert.assertTrue(result instanceof List<?>);
> +
> +    Assert.assertEquals(3, ((List<?>)result).size());
> +    Assert.assertEquals(1L, ((List<?>)result).get(0));
> +    Assert.assertEquals(2L, ((List<?>)result).get(1));
> +    Assert.assertEquals(3L, ((List<?>)result).get(2));
> +  }
> +
> +  @Test
> +  public void arrayLongSortDescTest() throws IOException{
> +    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=desc)");
> +    StreamContext context = new StreamContext();
> +    evaluator.setStreamContext(context);
> +    Object result;
> +
> +    values.put("a", 1L);
> +    values.put("b", 3L);
> +    values.put("c", 2L);
> +
> +    result = evaluator.evaluate(new Tuple(values));
> +
> +    Assert.assertTrue(result instanceof List<?>);
> +
> +    Assert.assertEquals(3, ((List<?>)result).size());
> +    Assert.assertEquals(3L, ((List<?>)result).get(0));
> +    Assert.assertEquals(2L, ((List<?>)result).get(1));
> +    Assert.assertEquals(1L, ((List<?>)result).get(2));
> +  }
> +
> +  @Test
> +  public void arrayStringSortAscTest() throws IOException{
> +    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=asc)");
> +    StreamContext context = new StreamContext();
> +    evaluator.setStreamContext(context);
> +    Object result;
> +
> +    values.put("a", "a");
> +    values.put("b", "c");
> +    values.put("c", "b");
> +
> +    result = evaluator.evaluate(new Tuple(values));
> +
> +    Assert.assertTrue(result instanceof List<?>);
> +
> +    Assert.assertEquals(3, ((List<?>)result).size());
> +    Assert.assertEquals("a", ((List<?>)result).get(0));
> +    Assert.assertEquals("b", ((List<?>)result).get(1));
> +    Assert.assertEquals("c", ((List<?>)result).get(2));
> +  }
> +
> +  @Test
> +  public void arrayStringSortDescTest() throws IOException{
> +    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=desc)");
> +    StreamContext context = new StreamContext();
> +    evaluator.setStreamContext(context);
> +    Object result;
> +
> +    values.put("a", "a");
> +    values.put("b", "c");
> +    values.put("c", "b");
> +
> +    result = evaluator.evaluate(new Tuple(values));
> +
> +    Assert.assertTrue(result instanceof List<?>);
> +
> +    Assert.assertEquals(3, ((List<?>)result).size());
> +    Assert.assertEquals("c", ((List<?>)result).get(0));
> +    Assert.assertEquals("b", ((List<?>)result).get(1));
> +    Assert.assertEquals("a", ((List<?>)result).get(2));
> +  }
> +
> +  @Test
> +  public void arrayStringUnsortedTest() throws IOException{
> +    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c)");
> +    StreamContext context = new StreamContext();
> +    evaluator.setStreamContext(context);
> +    Object result;
> +
> +    values.put("a", "a");
> +    values.put("b", "c");
> +    values.put("c", "b");
> +
> +    result = evaluator.evaluate(new Tuple(values));
> +
> +    Assert.assertTrue(result instanceof List<?>);
> +
> +    Assert.assertEquals(3, ((List<?>)result).size());
> +    Assert.assertEquals("a", ((List<?>)result).get(0));
> +    Assert.assertEquals("c", ((List<?>)result).get(1));
> +    Assert.assertEquals("b", ((List<?>)result).get(2));
> +  }
> +
> +
> +
> +
> +}
>



-- 
Regards,
Shalin Shekhar Mangar.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@lucene.apache.org
For additional commands, e-mail: dev-help@lucene.apache.org


[6/8] lucene-solr:master: SOLR-10882: ArrayEvaluator now works with all types and allows sorts (deleted ArraySortEvaluator)

Posted by dp...@apache.org.
SOLR-10882: ArrayEvaluator now works with all types and allows sorts (deleted ArraySortEvaluator)


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

Branch: refs/heads/master
Commit: 113459a840e8ca3482ebd36a76dda551fac885ec
Parents: 5fca6a4
Author: Dennis Gove <dp...@gmail.com>
Authored: Thu Jun 15 22:10:37 2017 -0400
Committer: Dennis Gove <dp...@gmail.com>
Committed: Sun Jun 18 11:50:58 2017 -0400

----------------------------------------------------------------------
 .../org/apache/solr/handler/StreamHandler.java  | 479 +++++++++----------
 .../client/solrj/io/eval/ArrayEvaluator.java    |  48 +-
 .../solrj/io/eval/ArraySortEvaluator.java       |  77 ---
 .../client/solrj/io/eval/ComplexEvaluator.java  |  18 +-
 .../io/stream/eval/ArrayEvaluatorTest.java      | 155 ++++++
 5 files changed, 452 insertions(+), 325 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
index 7889bf7..4616204 100644
--- a/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/StreamHandler.java
@@ -77,7 +77,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
   private StreamFactory streamFactory = new StreamFactory();
   private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   private String coreName;
-  private Map<String, DaemonStream> daemons = Collections.synchronizedMap(new HashMap());
+  private Map<String,DaemonStream> daemons = Collections.synchronizedMap(new HashMap());
 
   @Override
   public PermissionNameProvider.Name getPermissionName(AuthorizationContext request) {
@@ -89,202 +89,202 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
   }
 
   public void inform(SolrCore core) {
-    
-    /* The stream factory will always contain the zkUrl for the given collection
-     * Adds default streams with their corresponding function names. These 
-     * defaults can be overridden or added to in the solrConfig in the stream 
-     * RequestHandler def. Example config override
-     *  <lst name="streamFunctions">
-     *    <str name="group">org.apache.solr.client.solrj.io.stream.ReducerStream</str>
-     *    <str name="count">org.apache.solr.client.solrj.io.stream.RecordCountStream</str>
-     *  </lst>
-     * */
+
+    /*
+     * The stream factory will always contain the zkUrl for the given collection Adds default streams with their
+     * corresponding function names. These defaults can be overridden or added to in the solrConfig in the stream
+     * RequestHandler def. Example config override 
+     * <lst name="streamFunctions"> 
+     *  <str name="group">org.apache.solr.client.solrj.io.stream.ReducerStream</str> 
+     *  <str name="count">org.apache.solr.client.solrj.io.stream.RecordCountStream</str> 
+     * </lst>
+     */
 
     String defaultCollection;
     String defaultZkhost;
     CoreContainer coreContainer = core.getCoreContainer();
     this.coreName = core.getName();
 
-    if(coreContainer.isZooKeeperAware()) {
+    if (coreContainer.isZooKeeperAware()) {
       defaultCollection = core.getCoreDescriptor().getCollectionName();
       defaultZkhost = core.getCoreContainer().getZkController().getZkServerAddress();
       streamFactory.withCollectionZkHost(defaultCollection, defaultZkhost);
       streamFactory.withDefaultZkHost(defaultZkhost);
       modelCache = new ModelCache(250,
-                                  defaultZkhost,
-                                  clientCache);
-    }
-
-     streamFactory
-       // source streams
-      .withFunctionName("search", CloudSolrStream.class)
-      .withFunctionName("facet", FacetStream.class)
-      .withFunctionName("update", UpdateStream.class)
-      .withFunctionName("jdbc", JDBCStream.class)
-      .withFunctionName("topic", TopicStream.class)
-      .withFunctionName("commit", CommitStream.class)
-      .withFunctionName("random", RandomStream.class)
-      .withFunctionName("knn", KnnStream.class)
-      
-      // decorator streams
-      .withFunctionName("merge", MergeStream.class)
-      .withFunctionName("unique", UniqueStream.class)
-      .withFunctionName("top", RankStream.class)
-      .withFunctionName("group", GroupOperation.class)
-      .withFunctionName("reduce", ReducerStream.class)
-      .withFunctionName("parallel", ParallelStream.class)
-      .withFunctionName("rollup", RollupStream.class)
-      .withFunctionName("stats", StatsStream.class)
-      .withFunctionName("innerJoin", InnerJoinStream.class)
-      .withFunctionName("leftOuterJoin", LeftOuterJoinStream.class) 
-      .withFunctionName("hashJoin", HashJoinStream.class)
-      .withFunctionName("outerHashJoin", OuterHashJoinStream.class)
-      .withFunctionName("intersect", IntersectStream.class)
-      .withFunctionName("complement", ComplementStream.class)
-      .withFunctionName(SORT, SortStream.class)
-      .withFunctionName("train", TextLogitStream.class)
-      .withFunctionName("features", FeaturesSelectionStream.class)
-      .withFunctionName("daemon", DaemonStream.class)
-      .withFunctionName("shortestPath", ShortestPathStream.class)
-      .withFunctionName("gatherNodes", GatherNodesStream.class)
-      .withFunctionName("nodes", GatherNodesStream.class)
-      .withFunctionName("select", SelectStream.class)
-      .withFunctionName("shortestPath", ShortestPathStream.class)
-      .withFunctionName("gatherNodes", GatherNodesStream.class)
-      .withFunctionName("nodes", GatherNodesStream.class)
-      .withFunctionName("scoreNodes", ScoreNodesStream.class)
-      .withFunctionName("model", ModelStream.class)
-      .withFunctionName("classify", ClassifyStream.class)
-      .withFunctionName("fetch", FetchStream.class)
-      .withFunctionName("executor", ExecutorStream.class)
-      .withFunctionName("null", NullStream.class)
-      .withFunctionName("priority", PriorityStream.class)
-         .withFunctionName("significantTerms", SignificantTermsStream.class)
-      .withFunctionName("cartesianProduct", CartesianProductStream.class)
-         .withFunctionName("shuffle", ShuffleStream.class)
-         .withFunctionName("calc", CalculatorStream.class)
-      .withFunctionName("eval",EvalStream.class)
-      .withFunctionName("echo", EchoStream.class)
-      .withFunctionName("cell", CellStream.class)
-      .withFunctionName("list", ListStream.class)
-      .withFunctionName("let", LetStream.class)
-      .withFunctionName("get", GetStream.class)
-      .withFunctionName("timeseries", TimeSeriesStream.class)
-      .withFunctionName("tuple", TupStream.class)
-      .withFunctionName("sql", SqlStream.class)
-      .withFunctionName("col", ColumnEvaluator.class)
-      .withFunctionName("predict", PredictEvaluator.class)
-      .withFunctionName("regress", RegressionEvaluator.class)
-      .withFunctionName("cov", CovarianceEvaluator.class)
-      .withFunctionName("conv", ConvolutionEvaluator.class)
-      .withFunctionName("normalize", NormalizeEvaluator.class)
-      .withFunctionName("rev", ReverseEvaluator.class)
-      .withFunctionName("length", LengthEvaluator.class)
-      .withFunctionName("rank", RankEvaluator.class)
-      .withFunctionName("scale", ScaleEvaluator.class)
-      .withFunctionName("distance", DistanceEvaluator.class)
-      .withFunctionName("copyOf", CopyOfEvaluator.class)
-      .withFunctionName("copyOfRange", CopyOfRangeEvaluator.class)
-      .withFunctionName("percentile", PercentileEvaluator.class)
-      .withFunctionName("empiricalDistribution", EmpiricalDistributionEvaluator.class)
-      .withFunctionName("cumulativeProbability", CumulativeProbabilityEvaluator.class)
-      .withFunctionName("describe", DescribeEvaluator.class)
-      .withFunctionName("finddelay", FindDelayEvaluator.class)
-      .withFunctionName("sequence", SequenceEvaluator.class)
-      .withFunctionName("array", ArrayEvaluator.class)
-      .withFunctionName("hist", HistogramEvaluator.class)
-      .withFunctionName("anova", AnovaEvaluator.class)
-      .withFunctionName("movingAvg", MovingAverageEvaluator.class)
-      .withFunctionName("arraySort", ArraySortEvaluator.class)
-
-      // metrics
-         .withFunctionName("min", MinMetric.class)
-      .withFunctionName("max", MaxMetric.class)
-      .withFunctionName("avg", MeanMetric.class)
-      .withFunctionName("sum", SumMetric.class)
-      .withFunctionName("count", CountMetric.class)
-      
-      // tuple manipulation operations
-         .withFunctionName("replace", ReplaceOperation.class)
-      .withFunctionName("concat", ConcatOperation.class)
-      
-      // stream reduction operations
-         .withFunctionName("group", GroupOperation.class)
-      .withFunctionName("distinct", DistinctOperation.class)
-      .withFunctionName("having", HavingStream.class)
-      
-      // Stream Evaluators
-         .withFunctionName("val", RawValueEvaluator.class)
-      
-      // Boolean Stream Evaluators
-         .withFunctionName("and", AndEvaluator.class)
-      .withFunctionName("eor", ExclusiveOrEvaluator.class)
-      .withFunctionName("eq", EqualsEvaluator.class)
-      .withFunctionName("gt", GreaterThanEvaluator.class)
-      .withFunctionName("gteq", GreaterThanEqualToEvaluator.class)
-      .withFunctionName("lt", LessThanEvaluator.class)
-      .withFunctionName("lteq", LessThanEqualToEvaluator.class)
-      .withFunctionName("not", NotEvaluator.class)
-         .withFunctionName("or", OrEvaluator.class)
-
-      // Date Time Evaluators
-         .withFunctionName(TemporalEvaluatorYear.FUNCTION_NAME, TemporalEvaluatorYear.class)
-      .withFunctionName(TemporalEvaluatorMonth.FUNCTION_NAME, TemporalEvaluatorMonth.class)
-      .withFunctionName(TemporalEvaluatorDay.FUNCTION_NAME, TemporalEvaluatorDay.class)
-      .withFunctionName(TemporalEvaluatorDayOfYear.FUNCTION_NAME, TemporalEvaluatorDayOfYear.class)
-         .withFunctionName(TemporalEvaluatorHour.FUNCTION_NAME, TemporalEvaluatorHour.class)
-      .withFunctionName(TemporalEvaluatorMinute.FUNCTION_NAME, TemporalEvaluatorMinute.class)
-         .withFunctionName(TemporalEvaluatorSecond.FUNCTION_NAME, TemporalEvaluatorSecond.class)
-      .withFunctionName(TemporalEvaluatorEpoch.FUNCTION_NAME, TemporalEvaluatorEpoch.class)
-      .withFunctionName(TemporalEvaluatorWeek.FUNCTION_NAME, TemporalEvaluatorWeek.class)
-         .withFunctionName(TemporalEvaluatorQuarter.FUNCTION_NAME, TemporalEvaluatorQuarter.class)
-         .withFunctionName(TemporalEvaluatorDayOfQuarter.FUNCTION_NAME, TemporalEvaluatorDayOfQuarter.class)
-
-      // Number Stream Evaluators
-         .withFunctionName("abs", AbsoluteValueEvaluator.class)
-      .withFunctionName("add", AddEvaluator.class)
-      .withFunctionName("div", DivideEvaluator.class)
-      .withFunctionName("mult", MultiplyEvaluator.class)
-      .withFunctionName("sub", SubtractEvaluator.class)
-      .withFunctionName("log", NaturalLogEvaluator.class)
-      .withFunctionName("pow", PowerEvaluator.class)
-      .withFunctionName("mod", ModuloEvaluator.class)
-         .withFunctionName("ceil", CeilingEvaluator.class)
-      .withFunctionName("floor", FloorEvaluator.class)
-      .withFunctionName("sin", SineEvaluator.class)
-      .withFunctionName("asin", ArcSineEvaluator.class)
-      .withFunctionName("sinh", HyperbolicSineEvaluator.class)
-      .withFunctionName("cos", CosineEvaluator.class)
-      .withFunctionName("acos", ArcCosineEvaluator.class)
-      .withFunctionName("cosh", HyperbolicCosineEvaluator.class)
-      .withFunctionName("tan", TangentEvaluator.class)
-      .withFunctionName("atan", ArcTangentEvaluator.class)
-      .withFunctionName("tanh", HyperbolicTangentEvaluator.class)
-         .withFunctionName("round", RoundEvaluator.class)
-      .withFunctionName("sqrt", SquareRootEvaluator.class)
-      .withFunctionName("cbrt", CubedRootEvaluator.class)
-      .withFunctionName("coalesce", CoalesceEvaluator.class)
-      .withFunctionName("uuid", UuidEvaluator.class)
-      .withFunctionName("corr", CorrelationEvaluator.class)
-
-
-      // Conditional Stream Evaluators
-         .withFunctionName("if", IfThenElseEvaluator.class)
-         .withFunctionName("analyze", AnalyzeEvaluator.class)
-         .withFunctionName("convert", ConversionEvaluator.class)
-      ;
-
-     // This pulls all the overrides and additions from the config
-     List<PluginInfo> pluginInfos = core.getSolrConfig().getPluginInfos(Expressible.class.getName());
-     for (PluginInfo pluginInfo : pluginInfos) {
-       Class<? extends Expressible> clazz = core.getMemClassLoader().findClass(pluginInfo.className, Expressible.class);
-       streamFactory.withFunctionName(pluginInfo.name, clazz);
-     }
+          defaultZkhost,
+          clientCache);
+    }
+
+    streamFactory
+        // source streams
+        .withFunctionName("search", CloudSolrStream.class)
+        .withFunctionName("facet", FacetStream.class)
+        .withFunctionName("update", UpdateStream.class)
+        .withFunctionName("jdbc", JDBCStream.class)
+        .withFunctionName("topic", TopicStream.class)
+        .withFunctionName("commit", CommitStream.class)
+        .withFunctionName("random", RandomStream.class)
+        .withFunctionName("knn", KnnStream.class)
+
+        // decorator streams
+        .withFunctionName("merge", MergeStream.class)
+        .withFunctionName("unique", UniqueStream.class)
+        .withFunctionName("top", RankStream.class)
+        .withFunctionName("group", GroupOperation.class)
+        .withFunctionName("reduce", ReducerStream.class)
+        .withFunctionName("parallel", ParallelStream.class)
+        .withFunctionName("rollup", RollupStream.class)
+        .withFunctionName("stats", StatsStream.class)
+        .withFunctionName("innerJoin", InnerJoinStream.class)
+        .withFunctionName("leftOuterJoin", LeftOuterJoinStream.class)
+        .withFunctionName("hashJoin", HashJoinStream.class)
+        .withFunctionName("outerHashJoin", OuterHashJoinStream.class)
+        .withFunctionName("intersect", IntersectStream.class)
+        .withFunctionName("complement", ComplementStream.class)
+        .withFunctionName(SORT, SortStream.class)
+        .withFunctionName("train", TextLogitStream.class)
+        .withFunctionName("features", FeaturesSelectionStream.class)
+        .withFunctionName("daemon", DaemonStream.class)
+        .withFunctionName("shortestPath", ShortestPathStream.class)
+        .withFunctionName("gatherNodes", GatherNodesStream.class)
+        .withFunctionName("nodes", GatherNodesStream.class)
+        .withFunctionName("select", SelectStream.class)
+        .withFunctionName("shortestPath", ShortestPathStream.class)
+        .withFunctionName("gatherNodes", GatherNodesStream.class)
+        .withFunctionName("nodes", GatherNodesStream.class)
+        .withFunctionName("scoreNodes", ScoreNodesStream.class)
+        .withFunctionName("model", ModelStream.class)
+        .withFunctionName("classify", ClassifyStream.class)
+        .withFunctionName("fetch", FetchStream.class)
+        .withFunctionName("executor", ExecutorStream.class)
+        .withFunctionName("null", NullStream.class)
+        .withFunctionName("priority", PriorityStream.class)
+        .withFunctionName("significantTerms", SignificantTermsStream.class)
+        .withFunctionName("cartesianProduct", CartesianProductStream.class)
+        .withFunctionName("shuffle", ShuffleStream.class)
+        .withFunctionName("calc", CalculatorStream.class)
+        .withFunctionName("eval", EvalStream.class)
+        .withFunctionName("echo", EchoStream.class)
+        .withFunctionName("cell", CellStream.class)
+        .withFunctionName("list", ListStream.class)
+        .withFunctionName("let", LetStream.class)
+        .withFunctionName("get", GetStream.class)
+        .withFunctionName("timeseries", TimeSeriesStream.class)
+        .withFunctionName("tuple", TupStream.class)
+        .withFunctionName("sql", SqlStream.class)
+
+        // metrics
+        .withFunctionName("min", MinMetric.class)
+        .withFunctionName("max", MaxMetric.class)
+        .withFunctionName("avg", MeanMetric.class)
+        .withFunctionName("sum", SumMetric.class)
+        .withFunctionName("count", CountMetric.class)
+
+        // tuple manipulation operations
+        .withFunctionName("replace", ReplaceOperation.class)
+        .withFunctionName("concat", ConcatOperation.class)
+
+        // stream reduction operations
+        .withFunctionName("group", GroupOperation.class)
+        .withFunctionName("distinct", DistinctOperation.class)
+        .withFunctionName("having", HavingStream.class)
+
+        // Stream Evaluators
+        .withFunctionName("val", RawValueEvaluator.class)
+
+        // New Evaluators
+        .withFunctionName("anova", AnovaEvaluator.class)
+        .withFunctionName("array", ArrayEvaluator.class)
+        .withFunctionName("col", ColumnEvaluator.class)
+        .withFunctionName("conv", ConvolutionEvaluator.class)
+        .withFunctionName("copyOf", CopyOfEvaluator.class)
+        .withFunctionName("copyOfRange", CopyOfRangeEvaluator.class)
+        .withFunctionName("cov", CovarianceEvaluator.class)
+        .withFunctionName("cumulativeProbability", CumulativeProbabilityEvaluator.class)
+        .withFunctionName("describe", DescribeEvaluator.class)
+        .withFunctionName("distance", DistanceEvaluator.class)
+        .withFunctionName("empiricalDistribution", EmpiricalDistributionEvaluator.class)
+        .withFunctionName("finddelay", FindDelayEvaluator.class)
+        .withFunctionName("hist", HistogramEvaluator.class)
+        .withFunctionName("length", LengthEvaluator.class)
+        .withFunctionName("movingAvg", MovingAverageEvaluator.class)
+        .withFunctionName("normalize", NormalizeEvaluator.class)
+        .withFunctionName("percentile", PercentileEvaluator.class)
+        .withFunctionName("predict", PredictEvaluator.class)
+        .withFunctionName("rank", RankEvaluator.class)
+        .withFunctionName("regress", RegressionEvaluator.class)
+        .withFunctionName("rev", ReverseEvaluator.class)
+        .withFunctionName("scale", ScaleEvaluator.class)
+        .withFunctionName("sequence", SequenceEvaluator.class)
+
         
+        // Boolean Stream Evaluators
+        .withFunctionName("and", AndEvaluator.class)
+        .withFunctionName("eor", ExclusiveOrEvaluator.class)
+        .withFunctionName("eq", EqualsEvaluator.class)
+        .withFunctionName("gt", GreaterThanEvaluator.class)
+        .withFunctionName("gteq", GreaterThanEqualToEvaluator.class)
+        .withFunctionName("lt", LessThanEvaluator.class)
+        .withFunctionName("lteq", LessThanEqualToEvaluator.class)
+        .withFunctionName("not", NotEvaluator.class)
+        .withFunctionName("or", OrEvaluator.class)
+
+        // Date Time Evaluators
+        .withFunctionName(TemporalEvaluatorYear.FUNCTION_NAME, TemporalEvaluatorYear.class)
+        .withFunctionName(TemporalEvaluatorMonth.FUNCTION_NAME, TemporalEvaluatorMonth.class)
+        .withFunctionName(TemporalEvaluatorDay.FUNCTION_NAME, TemporalEvaluatorDay.class)
+        .withFunctionName(TemporalEvaluatorDayOfYear.FUNCTION_NAME, TemporalEvaluatorDayOfYear.class)
+        .withFunctionName(TemporalEvaluatorHour.FUNCTION_NAME, TemporalEvaluatorHour.class)
+        .withFunctionName(TemporalEvaluatorMinute.FUNCTION_NAME, TemporalEvaluatorMinute.class)
+        .withFunctionName(TemporalEvaluatorSecond.FUNCTION_NAME, TemporalEvaluatorSecond.class)
+        .withFunctionName(TemporalEvaluatorEpoch.FUNCTION_NAME, TemporalEvaluatorEpoch.class)
+        .withFunctionName(TemporalEvaluatorWeek.FUNCTION_NAME, TemporalEvaluatorWeek.class)
+        .withFunctionName(TemporalEvaluatorQuarter.FUNCTION_NAME, TemporalEvaluatorQuarter.class)
+        .withFunctionName(TemporalEvaluatorDayOfQuarter.FUNCTION_NAME, TemporalEvaluatorDayOfQuarter.class)
+
+        // Number Stream Evaluators
+        .withFunctionName("abs", AbsoluteValueEvaluator.class)
+        .withFunctionName("add", AddEvaluator.class)
+        .withFunctionName("div", DivideEvaluator.class)
+        .withFunctionName("mult", MultiplyEvaluator.class)
+        .withFunctionName("sub", SubtractEvaluator.class)
+        .withFunctionName("log", NaturalLogEvaluator.class)
+        .withFunctionName("pow", PowerEvaluator.class)
+        .withFunctionName("mod", ModuloEvaluator.class)
+        .withFunctionName("ceil", CeilingEvaluator.class)
+        .withFunctionName("floor", FloorEvaluator.class)
+        .withFunctionName("sin", SineEvaluator.class)
+        .withFunctionName("asin", ArcSineEvaluator.class)
+        .withFunctionName("sinh", HyperbolicSineEvaluator.class)
+        .withFunctionName("cos", CosineEvaluator.class)
+        .withFunctionName("acos", ArcCosineEvaluator.class)
+        .withFunctionName("cosh", HyperbolicCosineEvaluator.class)
+        .withFunctionName("tan", TangentEvaluator.class)
+        .withFunctionName("atan", ArcTangentEvaluator.class)
+        .withFunctionName("tanh", HyperbolicTangentEvaluator.class)
+        .withFunctionName("round", RoundEvaluator.class)
+        .withFunctionName("sqrt", SquareRootEvaluator.class)
+        .withFunctionName("cbrt", CubedRootEvaluator.class)
+        .withFunctionName("coalesce", CoalesceEvaluator.class)
+        .withFunctionName("uuid", UuidEvaluator.class)
+        .withFunctionName("corr", CorrelationEvaluator.class)
+
+        // Conditional Stream Evaluators
+        .withFunctionName("if", IfThenElseEvaluator.class)
+        .withFunctionName("analyze", AnalyzeEvaluator.class)
+        .withFunctionName("convert", ConversionEvaluator.class);
+
+    // This pulls all the overrides and additions from the config
+    List<PluginInfo> pluginInfos = core.getSolrConfig().getPluginInfos(Expressible.class.getName());
+    for (PluginInfo pluginInfo : pluginInfos) {
+      Class<? extends Expressible> clazz = core.getMemClassLoader().findClass(pluginInfo.className, Expressible.class);
+      streamFactory.withFunctionName(pluginInfo.name, clazz);
+    }
+
     core.addCloseHook(new CloseHook() {
       @Override
       public void preClose(SolrCore core) {
-        //To change body of implemented methods use File | Settings | File Templates.
+        // To change body of implemented methods use File | Settings | File Templates.
       }
 
       @Override
@@ -299,7 +299,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
     params = adjustParams(params);
     req.setParams(params);
 
-    if(params.get("action") != null) {
+    if (params.get("action") != null) {
       handleAdmin(req, rsp, params);
       return;
     }
@@ -308,7 +308,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
 
     try {
       StreamExpression streamExpression = StreamExpressionParser.parse(params.get("expr"));
-      if(this.streamFactory.isEvaluator(streamExpression)) {
+      if (this.streamFactory.isEvaluator(streamExpression)) {
         StreamExpression tupleExpression = new StreamExpression("tuple");
         tupleExpression.addParameter(new StreamExpressionNamedParameter("return-value", streamExpression));
         tupleStream = this.streamFactory.constructStream(tupleExpression);
@@ -316,7 +316,8 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
         tupleStream = this.streamFactory.constructStream(streamExpression);
       }
     } catch (Exception e) {
-      //Catch exceptions that occur while the stream is being created. This will include streaming expression parse rules.
+      // Catch exceptions that occur while the stream is being created. This will include streaming expression parse
+      // rules.
       SolrException.log(logger, e);
       rsp.add("result-set", new DummyErrorStream(e));
 
@@ -334,21 +335,21 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
     context.put("core", this.coreName);
     context.put("solr-core", req.getCore());
     tupleStream.setStreamContext(context);
-    
+
     // if asking for explanation then go get it
-    if(params.getBool("explain", false)){
+    if (params.getBool("explain", false)) {
       rsp.add("explanation", tupleStream.toExplanation(this.streamFactory));
     }
-    
-    if(tupleStream instanceof DaemonStream) {
-      DaemonStream daemonStream = (DaemonStream)tupleStream;
-      if(daemons.containsKey(daemonStream.getId())) {
+
+    if (tupleStream instanceof DaemonStream) {
+      DaemonStream daemonStream = (DaemonStream) tupleStream;
+      if (daemons.containsKey(daemonStream.getId())) {
         daemons.remove(daemonStream.getId()).close();
       }
       daemonStream.setDaemons(daemons);
-      daemonStream.open();  //This will start the deamonStream
+      daemonStream.open(); // This will start the deamonStream
       daemons.put(daemonStream.getId(), daemonStream);
-      rsp.add("result-set", new DaemonResponseStream("Deamon:"+daemonStream.getId()+" started on "+coreName));
+      rsp.add("result-set", new DaemonResponseStream("Deamon:" + daemonStream.getId() + " started on " + coreName));
     } else {
       rsp.add("result-set", new TimerStream(new ExceptionStream(tupleStream)));
     }
@@ -356,10 +357,10 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
 
   private void handleAdmin(SolrQueryRequest req, SolrQueryResponse rsp, SolrParams params) {
     String action = params.get("action");
-    if("stop".equalsIgnoreCase(action)) {
+    if ("stop".equalsIgnoreCase(action)) {
       String id = params.get(ID);
       DaemonStream d = daemons.get(id);
-      if(d != null) {
+      if (d != null) {
         d.close();
         rsp.add("result-set", new DaemonResponseStream("Deamon:" + id + " stopped on " + coreName));
       } else {
@@ -400,50 +401,46 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
     return null;
   }
 
-
   public static class DummyErrorStream extends TupleStream {
     private Exception e;
 
     public DummyErrorStream(Exception e) {
       this.e = e;
     }
+
     public StreamComparator getStreamSort() {
       return null;
     }
 
-    public void close() {
-    }
+    public void close() {}
 
-    public void open() {
-    }
+    public void open() {}
 
-    public void setStreamContext(StreamContext context) {
-    }
+    public void setStreamContext(StreamContext context) {}
 
     public List<TupleStream> children() {
       return null;
     }
-    
+
     @Override
     public Explanation toExplanation(StreamFactory factory) throws IOException {
 
       return new StreamExplanation(getStreamNodeId().toString())
-        .withFunctionName("error")
-        .withImplementingClass(this.getClass().getName())
-        .withExpressionType(ExpressionType.STREAM_DECORATOR)
-        .withExpression("--non-expressible--");
+          .withFunctionName("error")
+          .withImplementingClass(this.getClass().getName())
+          .withExpressionType(ExpressionType.STREAM_DECORATOR)
+          .withExpression("--non-expressible--");
     }
 
     public Tuple read() {
       String msg = e.getMessage();
 
       Throwable t = e.getCause();
-      while(t != null) {
+      while (t != null) {
         msg = t.getMessage();
         t = t.getCause();
       }
 
-
       Map m = new HashMap();
       m.put("EOF", true);
       m.put("EXCEPTION", msg);
@@ -457,18 +454,16 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
     public DaemonCollectionStream(Collection<DaemonStream> col) {
       this.it = col.iterator();
     }
+
     public StreamComparator getStreamSort() {
       return null;
     }
 
-    public void close() {
-    }
+    public void close() {}
 
-    public void open() {
-    }
+    public void open() {}
 
-    public void setStreamContext(StreamContext context) {
-    }
+    public void setStreamContext(StreamContext context) {}
 
     public List<TupleStream> children() {
       return null;
@@ -478,14 +473,14 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
     public Explanation toExplanation(StreamFactory factory) throws IOException {
 
       return new StreamExplanation(getStreamNodeId().toString())
-        .withFunctionName("daemon-collection")
-        .withImplementingClass(this.getClass().getName())
-        .withExpressionType(ExpressionType.STREAM_DECORATOR)
-        .withExpression("--non-expressible--");
+          .withFunctionName("daemon-collection")
+          .withImplementingClass(this.getClass().getName())
+          .withExpressionType(ExpressionType.STREAM_DECORATOR)
+          .withExpression("--non-expressible--");
     }
-    
+
     public Tuple read() {
-      if(it.hasNext()) {
+      if (it.hasNext()) {
         return it.next().getInfo();
       } else {
         Map m = new HashMap();
@@ -502,18 +497,16 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
     public DaemonResponseStream(String message) {
       this.message = message;
     }
+
     public StreamComparator getStreamSort() {
       return null;
     }
 
-    public void close() {
-    }
+    public void close() {}
 
-    public void open() {
-    }
+    public void open() {}
 
-    public void setStreamContext(StreamContext context) {
-    }
+    public void setStreamContext(StreamContext context) {}
 
     public List<TupleStream> children() {
       return null;
@@ -523,10 +516,10 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
     public Explanation toExplanation(StreamFactory factory) throws IOException {
 
       return new StreamExplanation(getStreamNodeId().toString())
-        .withFunctionName("daemon-response")
-        .withImplementingClass(this.getClass().getName())
-        .withExpressionType(ExpressionType.STREAM_DECORATOR)
-        .withExpression("--non-expressible--");
+          .withFunctionName("daemon-response")
+          .withImplementingClass(this.getClass().getName())
+          .withExpressionType(ExpressionType.STREAM_DECORATOR)
+          .withExpression("--non-expressible--");
     }
 
     public Tuple read() {
@@ -537,7 +530,7 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
       } else {
         sendEOF = true;
         Map m = new HashMap();
-        m.put("DaemonOp",message);
+        m.put("DaemonOp", message);
         return new Tuple(m);
       }
     }
@@ -577,15 +570,15 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
     public Explanation toExplanation(StreamFactory factory) throws IOException {
 
       return new StreamExplanation(getStreamNodeId().toString())
-        .withFunctionName("timer")
-        .withImplementingClass(this.getClass().getName())
-        .withExpressionType(ExpressionType.STREAM_DECORATOR)
-        .withExpression("--non-expressible--");
+          .withFunctionName("timer")
+          .withImplementingClass(this.getClass().getName())
+          .withExpressionType(ExpressionType.STREAM_DECORATOR)
+          .withExpression("--non-expressible--");
     }
 
     public Tuple read() throws IOException {
       Tuple tuple = this.tupleStream.read();
-      if(tuple.EOF) {
+      if (tuple.EOF) {
         long totalTime = (System.nanoTime() - begin) / 1000000;
         tuple.fields.put("RESPONSE_TIME", totalTime);
       }
@@ -593,25 +586,25 @@ public class StreamHandler extends RequestHandlerBase implements SolrCoreAware,
     }
   }
 
-  private Map<String, List<String>> getCollectionShards(SolrParams params) {
+  private Map<String,List<String>> getCollectionShards(SolrParams params) {
 
-    Map<String, List<String>> collectionShards = new HashMap();
+    Map<String,List<String>> collectionShards = new HashMap();
     Iterator<String> paramsIt = params.getParameterNamesIterator();
-    while(paramsIt.hasNext()) {
+    while (paramsIt.hasNext()) {
       String param = paramsIt.next();
-      if(param.indexOf(".shards") > -1) {
+      if (param.indexOf(".shards") > -1) {
         String collection = param.split("\\.")[0];
         String shardString = params.get(param);
         String[] shards = shardString.split(",");
         List<String> shardList = new ArrayList();
-        for(String shard : shards) {
+        for (String shard : shards) {
           shardList.add(shard);
         }
         collectionShards.put(collection, shardList);
       }
     }
 
-    if(collectionShards.size() > 0) {
+    if (collectionShards.size() > 0) {
       return collectionShards;
     } else {
       return null;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
index ed45ee9..065335b 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
@@ -18,30 +18,72 @@ package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
 
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.Explanation;
 import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
 import org.apache.solr.client.solrj.io.stream.expr.Expressible;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
+import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionNamedParameter;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
+import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionValue;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
 
+import com.google.common.collect.Lists;
+
 public class ArrayEvaluator extends ComplexEvaluator implements Expressible {
 
   private static final long serialVersionUID = 1;
-
+  private String sortOrder;
+  
   public ArrayEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
-    super(expression, factory);
+    super(expression, factory, Lists.newArrayList("sort"));
+    
+    sortOrder = extractSortOrder(expression, factory);
+  }
+  
+  private String extractSortOrder(StreamExpression expression, StreamFactory factory) throws IOException{
+    StreamExpressionNamedParameter sortParam = factory.getNamedOperand(expression, "sort");
+    if(null == sortParam){
+      return null; // this is ok
+    }
+    
+    if(sortParam.getParameter() instanceof StreamExpressionValue){
+      String sortOrder = ((StreamExpressionValue)sortParam.getParameter()).getValue().trim().toLowerCase(Locale.ROOT);
+      if("asc".equals(sortOrder) || "desc".equals(sortOrder)){
+        return sortOrder;
+      }
+    }
+    
+    throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - invalid 'sort' parameter - expecting either 'asc' or 'desc'", expression));
   }
 
   public List<Object> evaluate(Tuple tuple) throws IOException {
     List<Object> list = new ArrayList<>();
     for(StreamEvaluator subEvaluator : subEvaluators) {
-      Object value = (Number)subEvaluator.evaluate(tuple);
+      Object value = subEvaluator.evaluate(tuple);
+      
+      // if we want sorting but the evaluated value is not comparable then we have an error
+      if(null != sortOrder && !(value instanceof Comparable<?>)){
+        String message = String.format(Locale.ROOT,"Failed to evaluate to a comparable object - evaluator '%s' resulted in type '%s' and value '%s'",
+            subEvaluator.toExpression(constructingFactory),
+            value.getClass().getName(),
+            value.toString());
+        throw new IOException(message);
+      }
+      
       list.add(value);
     }
+    
+    if(null != sortOrder){
+      // Because of the type checking above we know that the value is at least Comparable
+      Comparator<Comparable> comparator = "asc".equals(sortOrder) ? (left,right) -> left.compareTo(right) : (left,right) -> right.compareTo(left);
+      list = list.stream().map(value -> (Comparable<Object>)value).sorted(comparator).collect(Collectors.toList());
+    }
 
     return list;
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java
deleted file mode 100644
index dabc615..0000000
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArraySortEvaluator.java
+++ /dev/null
@@ -1,77 +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.client.solrj.io.eval;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import org.apache.solr.client.solrj.io.Tuple;
-import org.apache.solr.client.solrj.io.stream.expr.Explanation;
-import org.apache.solr.client.solrj.io.stream.expr.Explanation.ExpressionType;
-import org.apache.solr.client.solrj.io.stream.expr.Expressible;
-import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
-import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
-import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
-
-public class ArraySortEvaluator extends ComplexEvaluator implements Expressible {
-
-  private static final long serialVersionUID = 1;
-
-  public ArraySortEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
-    super(expression, factory);
-  }
-
-  public List<Number> evaluate(Tuple tuple) throws IOException {
-
-    if(subEvaluators.size() != 1) {
-      throw new IOException("Array sort evaluator expects 1 parameters found: "+subEvaluators.size());
-    }
-
-    StreamEvaluator colEval1 = subEvaluators.get(0);
-
-    List<Number> numbers1 = (List<Number>)colEval1.evaluate(tuple);
-    List<Number> numbers2 = new ArrayList();
-    numbers2.addAll(numbers1);
-    Collections.sort(numbers2, new Comparator<Number>() {
-      @Override
-      public int compare(Number o1, Number o2) {
-        Double d1 = o1.doubleValue();
-        Double d2 = o2.doubleValue();
-        return d1.compareTo(d2);
-      }
-    });
-    return numbers2;
-  }
-
-  @Override
-  public StreamExpressionParameter toExpression(StreamFactory factory) throws IOException {
-    StreamExpression expression = new StreamExpression(factory.getFunctionName(getClass()));
-    return expression;
-  }
-
-  @Override
-  public Explanation toExplanation(StreamFactory factory) throws IOException {
-    return new Explanation(nodeId.toString())
-        .withExpressionType(ExpressionType.EVALUATOR)
-        .withFunctionName(factory.getFunctionName(getClass()))
-        .withImplementingClass(getClass().getName())
-        .withExpression(toExpression(factory).toString());
-  }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
index ea4c88c..ca1f0de 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ComplexEvaluator.java
@@ -20,7 +20,9 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 import java.util.UUID;
+import java.util.stream.Collectors;
 
 import org.apache.solr.client.solrj.io.stream.StreamContext;
 import org.apache.solr.client.solrj.io.stream.expr.Explanation;
@@ -40,6 +42,10 @@ public abstract class ComplexEvaluator implements StreamEvaluator {
   protected List<StreamEvaluator> subEvaluators = new ArrayList<StreamEvaluator>();
   
   public ComplexEvaluator(StreamExpression expression, StreamFactory factory) throws IOException{
+    this(expression, factory, new ArrayList<>());
+  }
+  
+  public ComplexEvaluator(StreamExpression expression, StreamFactory factory, List<String> ignoredNamedParameters) throws IOException{
     constructingFactory = factory;
     
     // We have to do this because order of the parameters matter
@@ -75,8 +81,16 @@ public abstract class ComplexEvaluator implements StreamEvaluator {
       }
     }
     
-    if(expression.getParameters().size() != subEvaluators.size()){
-      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - unknown operands found - expecting only StreamEvaluators or field names", expression));
+    Set<String> namedParameters = factory.getNamedOperands(expression).stream().map(param -> param.getName()).collect(Collectors.toSet());
+    long ignorableCount = ignoredNamedParameters.stream().filter(name -> namedParameters.contains(name)).count();
+    
+    if(0 != expression.getParameters().size() - subEvaluators.size() - ignorableCount){
+      if(namedParameters.isEmpty()){
+        throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - unknown operands found - expecting only StreamEvaluators or field names", expression));
+      }
+      else{
+        throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - unknown operands found - expecting only StreamEvaluators, field names, or named parameters [%s]", expression, namedParameters.stream().collect(Collectors.joining(","))));
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/113459a8/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java
new file mode 100644
index 0000000..36e5e78
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/io/stream/eval/ArrayEvaluatorTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.client.solrj.io.stream.eval;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.solr.client.solrj.io.Tuple;
+import org.apache.solr.client.solrj.io.eval.ArrayEvaluator;
+import org.apache.solr.client.solrj.io.eval.StreamEvaluator;
+import org.apache.solr.client.solrj.io.stream.StreamContext;
+import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
+import org.junit.Test;
+
+import junit.framework.Assert;
+
+public class ArrayEvaluatorTest extends LuceneTestCase {
+
+  StreamFactory factory;
+  Map<String, Object> values;
+  
+  public ArrayEvaluatorTest() {
+    super();
+    
+    factory = new StreamFactory()
+      .withFunctionName("array", ArrayEvaluator.class);
+    values = new HashMap<String,Object>();
+  }
+
+  @Test
+  public void arrayLongSortAscTest() throws IOException{
+    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=asc)");
+    StreamContext context = new StreamContext();
+    evaluator.setStreamContext(context);
+    Object result;
+    
+    values.put("a", 1L);
+    values.put("b", 3L);
+    values.put("c", 2L);
+    
+    result = evaluator.evaluate(new Tuple(values));
+    
+    Assert.assertTrue(result instanceof List<?>);
+    
+    Assert.assertEquals(3, ((List<?>)result).size());
+    Assert.assertEquals(1L, ((List<?>)result).get(0));
+    Assert.assertEquals(2L, ((List<?>)result).get(1));
+    Assert.assertEquals(3L, ((List<?>)result).get(2));
+  }
+
+  @Test
+  public void arrayLongSortDescTest() throws IOException{
+    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=desc)");
+    StreamContext context = new StreamContext();
+    evaluator.setStreamContext(context);
+    Object result;
+    
+    values.put("a", 1L);
+    values.put("b", 3L);
+    values.put("c", 2L);
+    
+    result = evaluator.evaluate(new Tuple(values));
+    
+    Assert.assertTrue(result instanceof List<?>);
+    
+    Assert.assertEquals(3, ((List<?>)result).size());
+    Assert.assertEquals(3L, ((List<?>)result).get(0));
+    Assert.assertEquals(2L, ((List<?>)result).get(1));
+    Assert.assertEquals(1L, ((List<?>)result).get(2));
+  }
+  
+  @Test
+  public void arrayStringSortAscTest() throws IOException{
+    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=asc)");
+    StreamContext context = new StreamContext();
+    evaluator.setStreamContext(context);
+    Object result;
+    
+    values.put("a", "a");
+    values.put("b", "c");
+    values.put("c", "b");
+    
+    result = evaluator.evaluate(new Tuple(values));
+    
+    Assert.assertTrue(result instanceof List<?>);
+    
+    Assert.assertEquals(3, ((List<?>)result).size());
+    Assert.assertEquals("a", ((List<?>)result).get(0));
+    Assert.assertEquals("b", ((List<?>)result).get(1));
+    Assert.assertEquals("c", ((List<?>)result).get(2));
+  }
+
+  @Test
+  public void arrayStringSortDescTest() throws IOException{
+    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c, sort=desc)");
+    StreamContext context = new StreamContext();
+    evaluator.setStreamContext(context);
+    Object result;
+    
+    values.put("a", "a");
+    values.put("b", "c");
+    values.put("c", "b");
+    
+    result = evaluator.evaluate(new Tuple(values));
+    
+    Assert.assertTrue(result instanceof List<?>);
+    
+    Assert.assertEquals(3, ((List<?>)result).size());
+    Assert.assertEquals("c", ((List<?>)result).get(0));
+    Assert.assertEquals("b", ((List<?>)result).get(1));
+    Assert.assertEquals("a", ((List<?>)result).get(2));
+  }
+  
+  @Test
+  public void arrayStringUnsortedTest() throws IOException{
+    StreamEvaluator evaluator = factory.constructEvaluator("array(a,b,c)");
+    StreamContext context = new StreamContext();
+    evaluator.setStreamContext(context);
+    Object result;
+    
+    values.put("a", "a");
+    values.put("b", "c");
+    values.put("c", "b");
+    
+    result = evaluator.evaluate(new Tuple(values));
+    
+    Assert.assertTrue(result instanceof List<?>);
+    
+    Assert.assertEquals(3, ((List<?>)result).size());
+    Assert.assertEquals("a", ((List<?>)result).get(0));
+    Assert.assertEquals("c", ((List<?>)result).get(1));
+    Assert.assertEquals("b", ((List<?>)result).get(2));
+  }
+
+
+
+
+}


[8/8] lucene-solr:master: SOLR-10882: Fixes use of Lists in evaluators

Posted by dp...@apache.org.
SOLR-10882: Fixes use of Lists in evaluators


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

Branch: refs/heads/master
Commit: 943bf5ab5bb5d72da3038284a8571c3620413691
Parents: aeec043
Author: Dennis Gove <dp...@gmail.com>
Authored: Sat Jun 17 22:12:23 2017 -0400
Committer: Dennis Gove <dp...@gmail.com>
Committed: Sun Jun 18 11:50:58 2017 -0400

----------------------------------------------------------------------
 .../org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java    | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/943bf5ab/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
index 065335b..127f587 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ArrayEvaluator.java
@@ -18,6 +18,7 @@ package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Locale;
@@ -33,15 +34,13 @@ import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionValue;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
 
-import com.google.common.collect.Lists;
-
 public class ArrayEvaluator extends ComplexEvaluator implements Expressible {
 
   private static final long serialVersionUID = 1;
   private String sortOrder;
   
   public ArrayEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
-    super(expression, factory, Lists.newArrayList("sort"));
+    super(expression, factory, Arrays.asList("sort"));
     
     sortOrder = extractSortOrder(expression, factory);
   }


[2/8] lucene-solr:master: SOLR-10882: Moves parameter checking of anova evaluator

Posted by dp...@apache.org.
SOLR-10882: Moves parameter checking of anova evaluator


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

Branch: refs/heads/master
Commit: 8988862698d95d2fc1239ffdf4f9c0e47eebbd99
Parents: f169510
Author: Dennis Gove <dp...@gmail.com>
Authored: Tue Jun 13 09:14:02 2017 -0400
Committer: Dennis Gove <dp...@gmail.com>
Committed: Sun Jun 18 11:50:57 2017 -0400

----------------------------------------------------------------------
 .../org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/89888626/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
index d80e693..45c3c3f 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
@@ -37,13 +37,13 @@ public class AnovaEvaluator extends ComplexEvaluator implements Expressible {
 
   public AnovaEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
-  }
-
-  public Tuple evaluate(Tuple tuple) throws IOException {
-
+    
     if(subEvaluators.size() < 2) {
       throw new IOException("ANOVA evaluator expects atleast 2 parameters found: "+subEvaluators.size());
     }
+  }
+
+  public Tuple evaluate(Tuple tuple) throws IOException {
 
     List<double[]> list = new ArrayList();
     for(StreamEvaluator subEvaluator : subEvaluators) {


[4/8] lucene-solr:master: SOLR-10882: Rewords error message on Anova evaluator

Posted by dp...@apache.org.
SOLR-10882: Rewords error message on Anova evaluator


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

Branch: refs/heads/master
Commit: 5fca6a4d829ad6c77fffd772a4006e885129b79b
Parents: 606824a
Author: Dennis Gove <dp...@gmail.com>
Authored: Tue Jun 13 09:35:16 2017 -0400
Committer: Dennis Gove <dp...@gmail.com>
Committed: Sun Jun 18 11:50:57 2017 -0400

----------------------------------------------------------------------
 .../org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java    | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5fca6a4d/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
index 45c3c3f..ca962f1 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -38,8 +39,8 @@ public class AnovaEvaluator extends ComplexEvaluator implements Expressible {
   public AnovaEvaluator(StreamExpression expression, StreamFactory factory) throws IOException {
     super(expression, factory);
     
-    if(subEvaluators.size() < 2) {
-      throw new IOException("ANOVA evaluator expects atleast 2 parameters found: "+subEvaluators.size());
+    if(subEvaluators.size() < 2){
+      throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - expecting at least two values but found %d",expression,subEvaluators.size()));
     }
   }