docs: @SuppressWarnings("fallthrough")
    private void getAggregatedMetrics(List<MetricTimeRangeValue> metricValue,
                                      long startTime, long endTime, long bucketId,
                                      MetricsFilter.MetricAggregationType type,
                                      MetricGranularity granularity) {
      LOG.fine("getAggregatedMetrics " + startTime + " " + endTime);
      // per request
      long outterCountAvg = 0;
  
      // prepare range value
      long outterStartTime = Long.MAX_VALUE;
      long outterEndTime = 0;
      String outterValue = null;
  
      double outterResult = 0;
      Long startKey = cacheMetric.floorKey(startTime);
      for (Long key = startKey != null ? startKey : cacheMetric.firstKey();
           key != null && key <= endTime;
           key = cacheMetric.higherKey(key)) {
        LinkedList<MetricDatapoint> bucket = cacheMetric.get(key).get(bucketId);
  
        if (bucket != null) {
          // per bucket
          long innerCountAvg = 0;
  
          // prepare range value
          long innerStartTime = Long.MAX_VALUE;
          long innerEndTime = 0;
          String innerValue = null;
  
          double innerResult = 0;
          for (MetricDatapoint datapoint : bucket) {
            if (datapoint.inRange(startTime, endTime)) {
              switch (type) {
                case AVG:
                  outterCountAvg++;
                  innerCountAvg++;
                case SUM:
                  outterResult += Double.parseDouble(datapoint.getValue());
                  innerResult += Double.parseDouble(datapoint.getValue());
                  break;
                case LAST:
                  if (outterEndTime < datapoint.getTimestamp()) {
                    outterValue = datapoint.getValue();
                  }
                  if (innerEndTime < datapoint.getTimestamp()) {
                    innerValue = datapoint.getValue();
                  }
                  break;
                case UNKNOWN:
                default:
                  LOG.warning(
                      "Unknown metric type, CacheCore does not know how to aggregate " + type);
                  return;
              }
              outterStartTime = Math.min(outterStartTime, datapoint.getTimestamp());
              outterEndTime = Math.max(outterEndTime, datapoint.getTimestamp());
              innerStartTime = Math.min(innerStartTime, datapoint.getTimestamp());
              innerEndTime = Math.max(innerEndTime, datapoint.getTimestamp());
            }
          } // end bucket
  
          if (type.equals(MetricsFilter.MetricAggregationType.AVG) && innerCountAvg > 0) {
            innerValue = String.valueOf(innerResult / innerCountAvg);
          } else if (type.equals(MetricsFilter.MetricAggregationType.SUM)) {
            innerValue = String.valueOf(innerResult);
          }
          if (innerValue != null && granularity.equals(MetricGranularity.AGGREGATE_BY_BUCKET)) {
            metricValue.add(new MetricTimeRangeValue(innerStartTime, innerEndTime, innerValue));
          }
        }
  
      } // end tree
  
      if (type.equals(MetricsFilter.MetricAggregationType.AVG) && outterCountAvg > 0) {
        outterValue = String.valueOf(outterResult / outterCountAvg);
      } else if (type.equals(MetricsFilter.MetricAggregationType.SUM)) {
        outterValue = String.valueOf(outterResult);
      }
      if (outterValue != null && granularity.equals(MetricGranularity.AGGREGATE_ALL_METRICS)) {
        metricValue.add(new MetricTimeRangeValue(outterStartTime, outterEndTime, outterValue));
      }
    }