package com.insightfullogic.honest_profiler.core.aggregation.filter; import static com.insightfullogic.honest_profiler.core.aggregation.filter.Comparison.NUMBER_COMPARISONS; import static com.insightfullogic.honest_profiler.core.aggregation.filter.Comparison.PCT_INTERPRETER; import static com.insightfullogic.honest_profiler.core.aggregation.filter.Comparison.STRING_COMPARISONS; import static java.util.Arrays.asList; import java.util.List; import java.util.function.Function; import java.util.function.Predicate;; /** * Enumeration for the various types of values in aggregation items. A ValueType also provides a validator, which tests * whether an input String can be converted to a value of the specified type, an interpreter which converts an input * String to a value of the specified type, and a list of {@link Comparison}s which are compatible with the ValueType. * <p> * Note the presence of the PCT_INTERPRETER, which can't be defined as a constant before the enum declarations, so it * was defined in the {@link Comparison} enumeration instead. Just the way the cookie crumbles, I guess. */ public enum ValueType { /** ValueType for {@link Double}s */ DOUBLE(validatorFor(Double::parseDouble), Double::parseDouble, NUMBER_COMPARISONS), /** SHARE represents a percentage representing a part/total relation, i.e. it is between 0 and 100. */ SHARE(validatorFor(Double::parseDouble, 0, 100), PCT_INTERPRETER, NUMBER_COMPARISONS), /** PERCENT represents an arbitrary, unbounded percentage. */ PERCENT(validatorFor(Double::parseDouble), PCT_INTERPRETER, NUMBER_COMPARISONS), /** ValueType for {@link Integer}s */ INTEGER(validatorFor(Integer::parseInt), Integer::parseInt, NUMBER_COMPARISONS), /** ValueType for {@link Long}s */ LONG(validatorFor(Long::parseLong), Long::parseLong, NUMBER_COMPARISONS), /** ValueType for {@link String}s */ STRING(str -> true, str -> str, STRING_COMPARISONS); // Internal Validator Class Factory Methods /** * Returns a validator {@link Predicate} which tests the String by trying to apply corresponding the convertor. If * that operation throws an Exception, the String cannot be converted. * <p> * @param <T> the type of the result of the convertor {@link Function} * @param convertor the convertor {@link Function} which converts a String to a value of the specified type T * @return a validator {@link Predicate} */ private static final <T> Predicate<String> validatorFor(Function<String, T> convertor) { return new Predicate<String>() { @Override public boolean test(String value) { try { convertor.apply(value); return true; } catch (Throwable t) { return false; } } }; } /** * Returns a validator {@link Predicate} for {@link Double}s as in {@link #validatorFor(Function)}, with an extra * boundary check. * <p> * @param convertor the convertor {@link Function} which converts a String to a Double * @param lower the lower bound the value has to be equal to or greater than in order to be accepted * @param upper the upper bound the value has to be equal to or less than in order to be accepted * @return a validator {@link Predicate} checking whether the String represents a Double within the specified range */ private static final Predicate<String> validatorFor(Function<String, Double> convertor, double lower, double upper) { return new Predicate<String>() { @Override public boolean test(String value) { try { double converted = convertor.apply(value); return converted >= lower && converted <= upper; } catch (Throwable t) { return false; } } }; } // Instance Properties private Predicate<String> stringValidator; private Function<String, ?> stringInterpreter; private List<Comparison> allowedComparisons; // Instance Constructors private ValueType(Predicate<String> stringValidator, Function<String, ?> stringInterpreter, Comparison... allowedComparisons) { this.stringValidator = stringValidator; this.stringInterpreter = stringInterpreter; this.allowedComparisons = asList(allowedComparisons); } // Instance Accessors /** * Returns a list of {@link Comparison}s compatible with this ValueType. * <p> * @return a list of {@link Comparison}s compatible with this ValueType */ public List<Comparison> getAllowedComparisons() { return allowedComparisons; } /** * Returns a {@link Predicate} for testing whether a String can be converted to a value of this type. * <p> * @return a {@link Predicate} for testing whether a String can be converted to a value of this type */ public Predicate<String> getValidator() { return stringValidator; } /** * Returns a {@link Function} for converting a String to a value of this type. * <p> * @param <T> the type of the result of the conversion {@link Function} * @return a {@link Function} for converting a String to a value of this type */ @SuppressWarnings("unchecked") public <T> Function<String, T> getInterpreter() { return (Function<String, T>)stringInterpreter; } }