You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by da...@apache.org on 2018/11/02 11:16:58 UTC

[49/56] lucene-solr:jira/gradle: Add :solr:contrib:analytics module

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

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

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

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

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