/**
  * Gets a reference to the {@link org.terracotta.statistics.OperationStatistic} instance holding
  * the class of statistics specified for the {@code Ehcache} instance provided.
  *
  * @param ehcache the {@code Ehcache} instance for which the {@code OperationStatistic} instance
  *     should be obtained
  * @param statsClass the {@code Class} of statistics for which the {@code OperationStatistic}
  *     instance should be obtained
  * @param <E> the {@code Enum} type for the statistics
  * @return a reference to the {@code OperationStatistic} instance holding the {@code statsClass}
  *     statistics; may be {@code null} if {@code statsClass} statistics do not exist for {@code
  *     ehcache}
  */
 private static <E extends Enum<E>> OperationStatistic<E> getOperationStatistic(
     final Ehcache<?, ?> ehcache, final Class<E> statsClass) {
   for (final TreeNode statNode : ContextManager.nodeFor(ehcache).getChildren()) {
     final Object statObj = statNode.getContext().attributes().get("this");
     if (statObj instanceof OperationStatistic<?>) {
       @SuppressWarnings("unchecked")
       final OperationStatistic<E> statistic = (OperationStatistic<E>) statObj;
       if (statistic.type().equals(statsClass)) {
         return statistic;
       }
     }
   }
   return null;
 }
 private OperationStatistic<StoreOperationOutcomes.ExpirationOutcome> getExpirationStatistic(
     Store<?, ?> store) {
   StatisticsManager statisticsManager = new StatisticsManager();
   statisticsManager.root(store);
   TreeNode treeNode =
       statisticsManager.queryForSingleton(
           QueryBuilder.queryBuilder()
               .descendants()
               .filter(
                   org.terracotta.context.query.Matchers.context(
                       org.terracotta.context.query.Matchers.<ContextElement>allOf(
                           org.terracotta.context.query.Matchers.identifier(
                               org.terracotta.context.query.Matchers.subclassOf(
                                   OperationStatistic.class)),
                           org.terracotta.context.query.Matchers.attributes(
                               org.terracotta.context.query.Matchers.hasAttribute(
                                   "name", "expiration")))))
               .build());
   return (OperationStatistic<StoreOperationOutcomes.ExpirationOutcome>)
       treeNode.getContext().attributes().get("this");
 }
  <T extends Enum<T>> OperationStatistic<T> findLowestTierStatistic(
      Cache<?, ?> cache, Class<T> type, String statName) {

    Query statQuery =
        queryBuilder()
            .descendants()
            .filter(
                context(
                    attributes(
                        Matchers.<Map<String, Object>>allOf(
                            hasAttribute("name", statName), hasAttribute("type", type)))))
            .build();

    Set<TreeNode> statResult =
        statQuery.execute(Collections.singleton(ContextManager.nodeFor(cache)));

    if (statResult.size() < 1) {
      throw new RuntimeException(
          "Failed to find lowest tier statistic: "
              + statName
              + " , valid result Set sizes must 1 or more.  Found result Set size of: "
              + statResult.size());
    }

    // if only 1 store then you don't need to find the lowest tier
    if (statResult.size() == 1) {
      return (OperationStatistic)
          statResult.iterator().next().getContext().attributes().get("this");
    }

    String lowestStoreType = "onheap";
    TreeNode lowestTierNode = null;
    for (TreeNode treeNode : statResult) {
      if (((Set) treeNode.getContext().attributes().get("tags")).size() != 1) {
        throw new RuntimeException(
            "Failed to find lowest tier statistic. \"tags\" set must be size 1");
      }

      String storeType = treeNode.getContext().attributes().get("tags").toString();
      if (storeType.compareToIgnoreCase(lowestStoreType) < 0) {
        lowestStoreType = treeNode.getContext().attributes().get("tags").toString();
        lowestTierNode = treeNode;
      }
    }

    return (OperationStatistic) lowestTierNode.getContext().attributes().get("this");
  }