/**
   * 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);
    }
  }
  /**
   * Adds refinement requests for the value for each shard that has not already contributed a count
   * for this value.
   */
  private void processDefiniteCandidateElement(PivotFacet pf, PivotFacetValue value) {

    for (int shard = pf.knownShards.nextSetBit(0);
        0 <= shard;
        shard = pf.knownShards.nextSetBit(shard + 1)) {
      if (!value.shardHasContributed(shard)) {
        if ( // if we're doing index order, we need to refine anything
        // (mincount may have excluded from a shard)
        FacetParams.FACET_SORT_INDEX.equals(facetFieldSort)
            // if we are doing count order, we need to refine if the limit was hit
            // (if not, the shard doesn't have the value or it would have returned already)
            || numberOfValuesContributedByShardWasLimitedByFacetFieldLimit(shard)) {

          pf.addRefinement(shard, value);
        }
      }
    }
  }