com.wavefront.agent.preprocessor.Predicates Maven / Gradle / Ivy
package com.wavefront.agent.preprocessor;
import static com.wavefront.predicates.PredicateEvalExpression.asDouble;
import static com.wavefront.predicates.PredicateEvalExpression.isTrue;
import static com.wavefront.predicates.Predicates.fromPredicateEvalExpression;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.wavefront.predicates.ExpressionPredicate;
import com.wavefront.predicates.PredicateEvalExpression;
import com.wavefront.predicates.StringComparisonExpression;
import com.wavefront.predicates.TemplateStringExpression;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
/**
* Collection of helper methods Base factory class for predicates; supports both text parsing as
* well as YAML logic.
*
* @author [email protected].
*/
public abstract class Predicates {
@VisibleForTesting static final String[] LOGICAL_OPS = {"all", "any", "none", "ignore"};
private Predicates() {}
@Nullable
public static Predicate getPredicate(Map ruleMap) {
Object value = ruleMap.get("if");
if (value == null) return null;
if (value instanceof String) {
return fromPredicateEvalExpression((String) value);
} else if (value instanceof Map) {
//noinspection unchecked
Map v2PredicateMap = (Map) value;
Preconditions.checkArgument(
v2PredicateMap.size() == 1,
"Argument [if] can have only 1 top level predicate, but found :: "
+ v2PredicateMap.size()
+ ".");
return parsePredicate(v2PredicateMap);
} else {
throw new IllegalArgumentException(
"Argument [if] value can only be String or Map, got "
+ value.getClass().getCanonicalName());
}
}
/**
* Parses the entire v2 Predicate tree into a Predicate.
*
* @param v2Predicate the predicate tree.
* @return parsed predicate
*/
@VisibleForTesting
static Predicate parsePredicate(Map v2Predicate) {
if (v2Predicate != null && !v2Predicate.isEmpty()) {
return new ExpressionPredicate<>(processLogicalOp(v2Predicate));
}
return x -> true;
}
private static PredicateEvalExpression processLogicalOp(Map element) {
for (Map.Entry tlEntry : element.entrySet()) {
switch (tlEntry.getKey()) {
case "all":
List allOps = processOperation(tlEntry);
return entity -> asDouble(allOps.stream().allMatch(x -> isTrue(x.getValue(entity))));
case "any":
List anyOps = processOperation(tlEntry);
return entity -> asDouble(anyOps.stream().anyMatch(x -> isTrue(x.getValue(entity))));
case "none":
List noneOps = processOperation(tlEntry);
return entity -> asDouble(noneOps.stream().noneMatch(x -> isTrue(x.getValue(entity))));
case "ignore":
// Always return true.
return x -> 1;
default:
return processComparisonOp(tlEntry);
}
}
return x -> 0;
}
private static List processOperation(Map.Entry tlEntry) {
List ops = new ArrayList<>();
//noinspection unchecked
for (Map tlValue : (List