/** {@inheritDoc} */
 public void setNextReader(LeafReaderContext ctx) throws IOException {
   if (valueSource == null) {
     // first time we've collected local values, get the right ValueSource
     valueSource = (null == ft) ? statsField.getValueSource() : ft.getValueSource(sf, null);
     vsContext = ValueSource.newContext(statsField.getSearcher());
   }
   values = valueSource.getValues(vsContext, ctx);
 }
  public NumericStatsValues(StatsField statsField) {
    super(statsField);

    this.computeSum = statsField.calculateStats(Stat.sum);
    this.computeSumOfSquares = statsField.calculateStats(Stat.sumOfSquares);

    this.computePercentiles = statsField.calculateStats(Stat.percentiles);
    if (computePercentiles) {
      tdigest = new AVLTreeDigest(statsField.getTdigestCompression());
    }
  }
  /**
   * Creates an instance of StatsValues which supports values from the specified {@link StatsField}
   *
   * @param statsField {@link StatsField} whose statistics will be created by the resulting {@link
   *     StatsValues}
   * @return Instance of {@link StatsValues} that will create statistics from values from the
   *     specified {@link StatsField}
   */
  public static StatsValues createStatsValues(StatsField statsField) {

    final SchemaField sf = statsField.getSchemaField();

    if (null == sf) {
      // function stats
      return new NumericStatsValues(statsField);
    }

    final FieldType fieldType = sf.getType(); // TODO: allow FieldType to provide impl.

    if (TrieDateField.class.isInstance(fieldType)) {
      return new DateStatsValues(statsField);
    } else if (TrieField.class.isInstance(fieldType)) {
      return new NumericStatsValues(statsField);
    } else if (StrField.class.isInstance(fieldType)) {
      return new StringStatsValues(statsField);
    } else if (sf.getType().getClass().equals(EnumField.class)) {
      return new EnumStatsValues(statsField);
    } else {
      throw new SolrException(
          SolrException.ErrorCode.BAD_REQUEST,
          "Field type " + fieldType + " is not currently supported");
    }
  }
  /** {@inheritDoc} */
  @Override
  public NamedList<?> getStatsValues() {
    NamedList<Object> res = new SimpleOrderedMap<>();

    if (statsField.includeInResponse(Stat.min)) {
      res.add("min", min);
    }
    if (statsField.includeInResponse(Stat.max)) {
      res.add("max", max);
    }
    if (statsField.includeInResponse(Stat.count)) {
      res.add("count", count);
    }
    if (statsField.includeInResponse(Stat.missing)) {
      res.add("missing", missing);
    }
    if (statsField.includeInResponse(Stat.distinctValues)) {
      res.add("distinctValues", distinctValues);
    }
    if (statsField.includeInResponse(Stat.countDistinct)) {
      res.add("countDistinct", countDistinct);
    }
    if (statsField.includeInResponse(Stat.cardinality)) {
      if (statsField.getIsShard()) {
        res.add("cardinality", hll.toBytes());
      } else {
        res.add("cardinality", hll.cardinality());
      }
    }

    addTypeSpecificStats(res);

    if (!facets.isEmpty()) {

      // add the facet stats
      NamedList<NamedList<?>> nl = new SimpleOrderedMap<>();
      for (Map.Entry<String, Map<String, StatsValues>> entry : facets.entrySet()) {
        NamedList<NamedList<?>> nl2 = new SimpleOrderedMap<>();
        nl.add(entry.getKey(), nl2);
        for (Map.Entry<String, StatsValues> e2 : entry.getValue().entrySet()) {
          nl2.add(e2.getKey(), e2.getValue().getStatsValues());
        }
      }

      res.add(FACETS, nl);
    }

    return res;
  }
 public DateStatsValues(StatsField statsField) {
   super(statsField);
   this.computeSum = statsField.calculateStats(Stat.sum);
   this.computeSumOfSquares = statsField.calculateStats(Stat.sumOfSquares);
 }
  protected AbstractStatsValues(StatsField statsField) {
    this.statsField = statsField;
    this.computeCount = statsField.calculateStats(Stat.count);
    this.computeMissing = statsField.calculateStats(Stat.missing);
    this.computeCalcDistinct =
        statsField.calculateStats(Stat.countDistinct)
            || statsField.calculateStats(Stat.distinctValues);
    this.computeMin = statsField.calculateStats(Stat.min);
    this.computeMax = statsField.calculateStats(Stat.max);
    this.computeMinOrMax = computeMin || computeMax;

    this.distinctValues = computeCalcDistinct ? new TreeSet<T>() : null;

    this.computeCardinality = statsField.calculateStats(Stat.cardinality);
    if (computeCardinality) {

      hasher = statsField.getHllOptions().getHasher();
      hll = statsField.getHllOptions().newHLL();
      assert null != hll : "Cardinality requires an HLL";
    } else {
      hll = null;
      hasher = null;
    }

    // alternatively, we could refactor a common base class that doesn't know/care
    // about either SchemaField or ValueSource - but then there would be a lot of
    // duplicate code between "NumericSchemaFieldStatsValues" and
    // "NumericValueSourceStatsValues" which would have diff parent classes
    //
    // part of the complexity here being that the StatsValues API serves two
    // masters: collecting concrete Values from things like DocValuesStats and
    // the distributed aggregation logic, but also collecting docIds which it
    // then
    // uses to go out and pull concreate values from the ValueSource
    // (from a func, or single valued field)
    if (null != statsField.getSchemaField()) {
      assert null == statsField.getValueSource();
      this.sf = statsField.getSchemaField();
      this.ft = sf.getType();
    } else {
      assert null != statsField.getValueSource();
      assert null == statsField.getSchemaField();
      this.sf = null;
      this.ft = null;
    }
  }