package org.rakam.automation; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import io.netty.handler.codec.http.HttpResponseStatus; import org.rakam.collection.Event; import org.rakam.server.http.annotations.ApiParam; import org.rakam.util.RakamException; import java.util.List; import java.util.function.Predicate; public class AutomationRule { public final int id; @JsonProperty("is_active") public boolean isActive; public final List<ScenarioStep> scenarios; public final List<SerializableAction> actions; @JsonProperty("custom_data") public final String customData; @JsonCreator public AutomationRule(@ApiParam(value = "is_active", required = false) Boolean isActive, @ApiParam("scenarios") List<ScenarioStep> scenarios, @ApiParam("actions") List<SerializableAction> actions, @ApiParam(value = "custom_data", required = false) String customData) { this.id = -1; this.customData = customData; this.isActive = isActive == null ? true : isActive.booleanValue(); this.scenarios = scenarios; this.actions = actions; } public AutomationRule(int id, boolean isActive, List<ScenarioStep> scenarios, List<SerializableAction> actions, String customData) { this.id = id; this.isActive = isActive; this.scenarios = scenarios; this.actions = actions; this.customData = customData; } public synchronized void setActive(boolean active) { this.isActive = active; } public enum ThresholdAggregation { count(false), sum(true); private final boolean fieldRequired; ThresholdAggregation(boolean fieldRequired) { this.fieldRequired = fieldRequired; } public boolean isFieldRequired() { return fieldRequired; } } public static class SerializableAction<T> { public final AutomationActionType type; public final T value; @JsonIgnore public AutomationAction action; @JsonCreator public SerializableAction(@JsonProperty("type") AutomationActionType type, @JsonProperty("value") T value) { this.type = type; this.value = value; } public synchronized void setAction(AutomationAction action) { this.action = action; } @JsonIgnore public AutomationAction getAction() { return action; } } public static class Threshold { public final ThresholdAggregation aggregation; public final String fieldName; public final long value; @JsonCreator public Threshold(@JsonProperty("aggregation") ThresholdAggregation aggregation, @JsonProperty("fieldName") String fieldName, @JsonProperty("value") long value) { this.aggregation = aggregation; this.fieldName = fieldName; this.value = value; } } public static class ScenarioStep { private static final Threshold DEFAULT_THRESHOLD = new Threshold(ThresholdAggregation.count, null, 0); public final String collection; public final Threshold threshold; @JsonIgnore public final Predicate<Event> filterPredicate; @JsonProperty private final String filter; @JsonCreator public ScenarioStep(@JsonProperty("collection") String collection, @JsonProperty("filter") String filterExpression, @JsonProperty("threshold") Threshold threshold) { this.collection = collection; this.filter = filterExpression; this.threshold = threshold == null ? DEFAULT_THRESHOLD : threshold; if(filterExpression == null || filterExpression.isEmpty()) { filterPredicate = (event) -> true; } else { try { filterPredicate = ExpressionCompiler.compile(filterExpression); } catch (UnsupportedOperationException e) { throw new RakamException("Unable to compile filter expression", HttpResponseStatus.NOT_IMPLEMENTED); } } } } }