/**
   * A recursive method for determining which {@link PivotFacetValue}s need to be refined for this
   * pivot.
   *
   * @see PivotFacet#queuePivotRefinementRequests
   */
  public void queuePivotRefinementRequests(PivotFacet pf) {

    if (needRefinementAtThisLevel && !valueCollection.getExplicitValuesList().isEmpty()) {

      if (FacetParams.FACET_SORT_COUNT.equals(facetFieldSort)) {
        // we only need to things that are currently in our limit,
        // or might be in our limit if we get increased counts from shards that
        // didn't include this value the first time
        final int indexOfCountThreshold =
            Math.min(
                    valueCollection.getExplicitValuesListSize(), facetFieldOffset + facetFieldLimit)
                - 1;
        final int countThreshold = valueCollection.getAt(indexOfCountThreshold).getCount();

        int positionInResults = 0;

        for (PivotFacetValue value : valueCollection.getExplicitValuesList()) {
          if (positionInResults <= indexOfCountThreshold) {
            // This element is within the top results, so we need to get information
            // from all of the shards.
            processDefiniteCandidateElement(pf, value);
          } else {
            // This element is not within the top results, but may still need to be refined.
            processPossibleCandidateElement(pf, value, countThreshold);
          }

          positionInResults++;
        }
      } else { // FACET_SORT_INDEX
        // everything needs refined to see what the per-shard mincount excluded
        for (PivotFacetValue value : valueCollection.getExplicitValuesList()) {
          processDefiniteCandidateElement(pf, value);
        }
      }

      needRefinementAtThisLevel = false;
    }

    if (pf.isRefinementsRequired()) {
      // if any refinements are needed, then we need to stop and wait to
      // see how the picture may change before drilling down to child pivot fields
      return;
    } else {
      // Since outstanding requests have been filled, then we can drill down
      // to the next deeper level and check it.
      refineNextLevelOfFacets(pf);
    }
  }
  /**
   * Checks the {@link #lowestCountContributedbyShard} for each shard, combined with the counts we
   * already know, to see if this value is a viable candidate -- <b>Does not make sense when using
   * {@link FacetParams#FACET_SORT_INDEX}</b>
   *
   * @see #processDefiniteCandidateElement
   */
  private void processPossibleCandidateElement(
      PivotFacet pf, PivotFacetValue value, final int refinementThreshold) {

    assert FacetParams.FACET_SORT_COUNT.equals(facetFieldSort)
        : "Method only makes sense when sorting by count";

    int maxPossibleCountAfterRefinement = value.getCount();

    for (int shard = pf.knownShards.nextSetBit(0);
        0 <= shard;
        shard = pf.knownShards.nextSetBit(shard + 1)) {
      if (!value.shardHasContributed(shard)) {
        maxPossibleCountAfterRefinement += lowestCountContributedbyShard(shard);
      }
    }

    if (refinementThreshold <= maxPossibleCountAfterRefinement) {
      processDefiniteCandidateElement(pf, value);
    }
  }