/* * ************************************************************************************* * Copyright (C) 2008 EsperTech, Inc. All rights reserved. * * http://esper.codehaus.org * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * * ************************************************************************************* */ package com.espertech.esper.epl.datetime.interval; import com.espertech.esper.client.EventBean; import com.espertech.esper.epl.datetime.eval.DatetimeMethodEnum; import com.espertech.esper.epl.expression.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.List; public class IntervalComputerFactory { public static IntervalComputer make(DatetimeMethodEnum method, List<ExprNode> expressions) throws ExprValidationException { ExprOptionalConstant[] parameters = getParameters(expressions); if (method == DatetimeMethodEnum.BEFORE) { if (parameters.length == 0) { return new IntervalComputerBeforeNoParam(); } IntervalStartEndParameterPair pair = IntervalStartEndParameterPair.fromParamsWithLongMaxEnd(parameters); if (pair.isConstant()) { return new IntervalComputerConstantBefore(pair); } return new IntervalComputerBeforeWithDeltaExpr(pair); } else if (method == DatetimeMethodEnum.AFTER) { if (parameters.length == 0) { return new IntervalComputerAfterNoParam(); } IntervalStartEndParameterPair pair = IntervalStartEndParameterPair.fromParamsWithLongMaxEnd(parameters); if (pair.isConstant()) { return new IntervalComputerConstantAfter(pair); } return new IntervalComputerAfterWithDeltaExpr(pair); } else if (method == DatetimeMethodEnum.COINCIDES) { if (parameters.length == 0) { return new IntervalComputerCoincidesNoParam(); } IntervalStartEndParameterPair pair = IntervalStartEndParameterPair.fromParamsWithSameEnd(parameters); if (pair.isConstant()) { return new IntervalComputerConstantCoincides(pair); } return new IntervalComputerCoincidesWithDeltaExpr(pair); } else if (method == DatetimeMethodEnum.DURING || method == DatetimeMethodEnum.INCLUDES) { if (parameters.length == 0) { if (method == DatetimeMethodEnum.DURING) { return new IntervalComputerDuringNoParam(); } return new IntervalComputerIncludesNoParam(); } if (parameters.length == 1) { return new IntervalComputerDuringAndIncludesThreshold(method == DatetimeMethodEnum.DURING, parameters[0].getEvaluator()); } if (parameters.length == 2) { return new IntervalComputerDuringAndIncludesMinMax(method == DatetimeMethodEnum.DURING, parameters[0].getEvaluator(), parameters[1].getEvaluator()); } return new IntervalComputerDuringMinMaxStartEnd(method == DatetimeMethodEnum.DURING, parameters); } else if (method == DatetimeMethodEnum.FINISHES) { if (parameters.length == 0) { return new IntervalComputerFinishesNoParam(); } validateConstantThreshold("finishes", parameters[0]); return new IntervalComputerFinishesThreshold(parameters[0].getEvaluator()); } else if (method == DatetimeMethodEnum.FINISHEDBY) { if (parameters.length == 0) { return new IntervalComputerFinishedByNoParam(); } validateConstantThreshold("finishedby", parameters[0]); return new IntervalComputerFinishedByThreshold(parameters[0].getEvaluator()); } else if (method == DatetimeMethodEnum.MEETS) { if (parameters.length == 0) { return new IntervalComputerMeetsNoParam(); } validateConstantThreshold("meets", parameters[0]); return new IntervalComputerMeetsThreshold(parameters[0].getEvaluator()); } else if (method == DatetimeMethodEnum.METBY) { if (parameters.length == 0) { return new IntervalComputerMetByNoParam(); } validateConstantThreshold("metBy", parameters[0]); return new IntervalComputerMetByThreshold(parameters[0].getEvaluator()); } else if (method == DatetimeMethodEnum.OVERLAPS || method == DatetimeMethodEnum.OVERLAPPEDBY) { if (parameters.length == 0) { if (method == DatetimeMethodEnum.OVERLAPS) { return new IntervalComputerOverlapsNoParam(); } return new IntervalComputerOverlappedByNoParam(); } if (parameters.length == 1) { return new IntervalComputerOverlapsAndByThreshold(method == DatetimeMethodEnum.OVERLAPS, parameters[0].getEvaluator()); } return new IntervalComputerOverlapsAndByMinMax(method == DatetimeMethodEnum.OVERLAPS, parameters[0].getEvaluator(), parameters[1].getEvaluator()); } else if (method == DatetimeMethodEnum.STARTS) { if (parameters.length == 0) { return new IntervalComputerStartsNoParam(); } validateConstantThreshold("starts", parameters[0]); return new IntervalComputerStartsThreshold(parameters[0].getEvaluator()); } else if (method == DatetimeMethodEnum.STARTEDBY) { if (parameters.length == 0) { return new IntervalComputerStartedByNoParam(); } validateConstantThreshold("startedBy", parameters[0]); return new IntervalComputerStartedByThreshold(parameters[0].getEvaluator()); } throw new IllegalArgumentException("Unknown datetime method '" + method + "'"); } private static void validateConstantThreshold(String method, ExprOptionalConstant param) throws ExprValidationException { if (param.getOptionalConstant() != null && (param.getOptionalConstant()).longValue() < 0) { throw new ExprValidationException("The " + method + " date-time method does not allow negative threshold value"); } } private static ExprOptionalConstant[] getParameters(List<ExprNode> expressions) { ExprOptionalConstant[] parameters = new ExprOptionalConstant[expressions.size() - 1]; for (int i = 1; i < expressions.size(); i++) { parameters[i - 1] = getExprOrConstant(expressions.get(i)); } return parameters; } private static ExprOptionalConstant getExprOrConstant(ExprNode exprNode) { if (exprNode instanceof ExprTimePeriod) { Long constant = null; if (exprNode.isConstantResult()) { double sec = (Double) exprNode.getExprEvaluator().evaluate(null, true, null); constant = (long)(sec * 1000L); } return new ExprOptionalConstant(exprNode.getExprEvaluator(), constant); } else if (ExprNodeUtility.isConstantValueExpr(exprNode)) { ExprConstantNode constantNode = (ExprConstantNode) exprNode; return new ExprOptionalConstant(constantNode.getExprEvaluator(), ((Number)constantNode.getValue()).longValue()); } else { return new ExprOptionalConstant(exprNode.getExprEvaluator(), null); } } /** * After. */ public static class IntervalComputerConstantAfter extends IntervalComputerConstantBase implements IntervalComputer { public IntervalComputerConstantAfter(IntervalStartEndParameterPair pair) { super(pair, true); } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return computeInternal(leftStart, leftEnd, rightStart, rightEnd, start, end); } public static Boolean computeInternal(long leftStart, long leftEnd, long rightStart, long rightEnd, long start, long end) { long delta = leftStart - rightEnd; return start <= delta && delta <= end; } } public static class IntervalComputerAfterWithDeltaExpr extends IntervalComputerExprBase { public IntervalComputerAfterWithDeltaExpr(IntervalStartEndParameterPair pair) { super(pair); } public boolean compute(long leftStartTs, long leftEnd, long rightStartTs, long rightEnd, long start, long end) { return IntervalComputerConstantAfter.computeInternal(leftStartTs, leftEnd, rightStartTs, rightEnd, start, end); } } public static class IntervalComputerAfterNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return leftStart > rightEnd; } } /** * Before. */ public static class IntervalComputerConstantBefore extends IntervalComputerConstantBase implements IntervalComputer { public IntervalComputerConstantBefore(IntervalStartEndParameterPair pair) { super(pair, true); } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return computeInternal(leftStart, leftEnd, rightStart, start, end); } public static Boolean computeInternal(long left, long leftEnd, long right, long start, long end) { long delta = right - leftEnd; return start <= delta && delta <= end; } } public static class IntervalComputerBeforeWithDeltaExpr extends IntervalComputerExprBase { public IntervalComputerBeforeWithDeltaExpr(IntervalStartEndParameterPair pair) { super(pair); } public boolean compute(long leftStartTs, long leftEnd, long rightStartTs, long rightEnd, long start, long end) { return IntervalComputerConstantBefore.computeInternal(leftStartTs, leftEnd, rightStartTs, start, end); } } public static class IntervalComputerBeforeNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return leftEnd < rightStart; } } /** * Coincides. */ public static class IntervalComputerConstantCoincides implements IntervalComputer { protected final long start; protected final long end; public IntervalComputerConstantCoincides(IntervalStartEndParameterPair pair) throws ExprValidationException { start = pair.getStart().getOptionalConstant(); end = pair.getEnd().getOptionalConstant(); if (start < 0 || end < 0) { throw new ExprValidationException("The coincides date-time method does not allow negative start and end values"); } } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return computeInternal(leftStart, leftEnd, rightStart, rightEnd, start, end); } public static Boolean computeInternal(long left, long leftEnd, long right, long rightEnd, long startThreshold, long endThreshold) { return Math.abs(left - right) <= startThreshold && Math.abs(leftEnd - rightEnd) <= endThreshold; } } public static class IntervalComputerCoincidesWithDeltaExpr implements IntervalComputer { private static final Log log = LogFactory.getLog(IntervalComputerCoincidesWithDeltaExpr.class); private final ExprEvaluator start; private final ExprEvaluator finish; public IntervalComputerCoincidesWithDeltaExpr(IntervalStartEndParameterPair pair) { this.start = pair.getStart().getEvaluator(); this.finish = pair.getEnd().getEvaluator(); } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object startValue = start.evaluate(eventsPerStream, newData, context); if (startValue == null) { return null; } Object endValue = finish.evaluate(eventsPerStream, newData, context); if (endValue == null) { return null; } long start = IntervalComputerExprBase.toLong(startValue); long end = IntervalComputerExprBase.toLong(endValue); if (start < 0 || end < 0) { log.warn("The coincides date-time method does not allow negative start and end values"); return null; } return IntervalComputerConstantCoincides.computeInternal(leftStart, leftEnd, rightStart, rightEnd, start, end); } } public static class IntervalComputerCoincidesNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return leftStart == rightStart && leftEnd == rightEnd; } } /** * During And Includes. */ public static class IntervalComputerDuringNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return rightStart < leftStart && leftEnd < rightEnd; } } public static class IntervalComputerIncludesNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return leftStart < rightStart && rightEnd < leftEnd; } } public static class IntervalComputerDuringAndIncludesThreshold implements IntervalComputer { private final boolean during; private final ExprEvaluator threshold; public IntervalComputerDuringAndIncludesThreshold(boolean during, ExprEvaluator threshold) { this.during = during; this.threshold = threshold; } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object thresholdValue = threshold.evaluate(eventsPerStream, newData, context); if (thresholdValue == null) { return null; } long threshold = IntervalComputerExprBase.toLong(thresholdValue); if (during) { long deltaStart = leftStart - rightStart; if (deltaStart <= 0 || deltaStart > threshold) { return false; } long deltaEnd = rightEnd - leftEnd; return !(deltaEnd <= 0 || deltaEnd > threshold); } else { long deltaStart = rightStart - leftStart; if (deltaStart <= 0 || deltaStart > threshold) { return false; } long deltaEnd = leftEnd - rightEnd; return !(deltaEnd <= 0 || deltaEnd > threshold); } } } public static class IntervalComputerDuringAndIncludesMinMax implements IntervalComputer { private final boolean during; private final ExprEvaluator minEval; private final ExprEvaluator maxEval; public IntervalComputerDuringAndIncludesMinMax(boolean during, ExprEvaluator minEval, ExprEvaluator maxEval) { this.during = during; this.minEval = minEval; this.maxEval = maxEval; } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object minObject = minEval.evaluate(eventsPerStream, newData, context); if (minObject == null) { return null; } long min = IntervalComputerExprBase.toLong(minObject); Object maxObject = maxEval.evaluate(eventsPerStream, newData, context); if (maxObject == null) { return null; } long max = IntervalComputerExprBase.toLong(maxObject); if (during) { return computeInternalDuring(leftStart, leftEnd, rightStart, rightEnd, min, max, min, max); } else { return computeInternalIncludes(leftStart, leftEnd, rightStart, rightEnd, min, max, min, max); } } public static boolean computeInternalDuring(long left, long leftEnd, long right, long rightEnd, long startMin, long startMax, long endMin, long endMax) { if (startMin <= 0) { startMin = 1; } long deltaStart = left - right; if (deltaStart < startMin || deltaStart > startMax) { return false; } long deltaEnd = rightEnd - leftEnd; return !(deltaEnd < endMin || deltaEnd > endMax); } public static boolean computeInternalIncludes(long left, long leftEnd, long right, long rightEnd, long startMin, long startMax, long endMin, long endMax) { if (startMin <= 0) { startMin = 1; } long deltaStart = right - left; if (deltaStart < startMin || deltaStart > startMax) { return false; } long deltaEnd = leftEnd - rightEnd; return !(deltaEnd < endMin || deltaEnd > endMax); } } public static class IntervalComputerDuringMinMaxStartEnd implements IntervalComputer { private final boolean during; private final ExprEvaluator minStartEval; private final ExprEvaluator maxStartEval; private final ExprEvaluator minEndEval; private final ExprEvaluator maxEndEval; public IntervalComputerDuringMinMaxStartEnd(boolean during, ExprOptionalConstant[] parameters) { this.during = during; minStartEval = parameters[0].getEvaluator(); maxStartEval = parameters[1].getEvaluator(); minEndEval = parameters[2].getEvaluator(); maxEndEval = parameters[3].getEvaluator(); } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object minStartObject = minStartEval.evaluate(eventsPerStream, newData, context); if (minStartObject == null) { return null; } Object maxStartObject = maxStartEval.evaluate(eventsPerStream, newData, context); if (maxStartObject == null) { return null; } Object minEndObject = minEndEval.evaluate(eventsPerStream, newData, context); if (minEndObject == null) { return null; } Object maxEndObject = maxEndEval.evaluate(eventsPerStream, newData, context); if (maxEndObject == null) { return null; } long minStart = IntervalComputerExprBase.toLong(minStartObject); long maxStart = IntervalComputerExprBase.toLong(maxStartObject); long minEnd = IntervalComputerExprBase.toLong(minEndObject); long maxEnd = IntervalComputerExprBase.toLong(maxEndObject); if (during) { return IntervalComputerDuringAndIncludesMinMax.computeInternalDuring(leftStart, leftEnd, rightStart, rightEnd, minStart, maxStart, minEnd, maxEnd); } else { return IntervalComputerDuringAndIncludesMinMax.computeInternalIncludes(leftStart, leftEnd, rightStart, rightEnd, minStart, maxStart, minEnd, maxEnd); } } } /** * Finishes. */ public static class IntervalComputerFinishesNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return rightStart < leftStart && (leftEnd == rightEnd); } } public static class IntervalComputerFinishesThreshold implements IntervalComputer { private static final Log log = LogFactory.getLog(IntervalComputerFinishesThreshold.class); private final ExprEvaluator threshold; public IntervalComputerFinishesThreshold(ExprEvaluator threshold) { this.threshold = threshold; } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object thresholdValue = threshold.evaluate(eventsPerStream, newData, context); if (thresholdValue == null) { return null; } long threshold = IntervalComputerExprBase.toLong(thresholdValue); if (threshold < 0) { log.warn("The 'finishes' date-time method does not allow negative threshold"); return null; } if (rightStart >= leftStart) { return false; } long delta = Math.abs(leftEnd - rightEnd); return delta <= threshold; } } /** * Finishes-By. */ public static class IntervalComputerFinishedByNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return leftStart < rightStart && (leftEnd == rightEnd); } } public static class IntervalComputerFinishedByThreshold implements IntervalComputer { private static final Log log = LogFactory.getLog(IntervalComputerFinishedByThreshold.class); private final ExprEvaluator threshold; public IntervalComputerFinishedByThreshold(ExprEvaluator threshold) { this.threshold = threshold; } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object thresholdValue = threshold.evaluate(eventsPerStream, newData, context); if (thresholdValue == null) { return null; } long threshold = IntervalComputerExprBase.toLong(thresholdValue); if (threshold < 0) { log.warn("The 'finishes' date-time method does not allow negative threshold"); return null; } if (leftStart >= rightStart) { return false; } long delta = Math.abs(leftEnd - rightEnd); return delta <= threshold; } } /** * Meets. */ public static class IntervalComputerMeetsNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return leftEnd == rightStart; } } public static class IntervalComputerMeetsThreshold implements IntervalComputer { private static final Log log = LogFactory.getLog(IntervalComputerMeetsThreshold.class); private final ExprEvaluator threshold; public IntervalComputerMeetsThreshold(ExprEvaluator threshold) { this.threshold = threshold; } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object thresholdValue = threshold.evaluate(eventsPerStream, newData, context); if (thresholdValue == null) { return null; } long threshold = IntervalComputerExprBase.toLong(thresholdValue); if (threshold < 0) { log.warn("The 'finishes' date-time method does not allow negative threshold"); return null; } long delta = Math.abs(rightStart - leftEnd); return delta <= threshold; } } /** * Met-By. */ public static class IntervalComputerMetByNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return rightEnd == leftStart; } } public static class IntervalComputerMetByThreshold implements IntervalComputer { private static final Log log = LogFactory.getLog(IntervalComputerMetByThreshold.class); private final ExprEvaluator threshold; public IntervalComputerMetByThreshold(ExprEvaluator threshold) { this.threshold = threshold; } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object thresholdValue = threshold.evaluate(eventsPerStream, newData, context); if (thresholdValue == null) { return null; } long threshold = IntervalComputerExprBase.toLong(thresholdValue); if (threshold < 0) { log.warn("The 'finishes' date-time method does not allow negative threshold"); return null; } long delta = Math.abs(leftStart - rightEnd); return delta <= threshold; } } /** * Overlaps. */ public static class IntervalComputerOverlapsNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return (leftStart < rightStart) && (rightStart < leftEnd) && (leftEnd < rightEnd); } } public static class IntervalComputerOverlapsAndByThreshold implements IntervalComputer { private final boolean overlaps; private final ExprEvaluator threshold; public IntervalComputerOverlapsAndByThreshold(boolean overlaps, ExprEvaluator threshold) { this.overlaps = overlaps; this.threshold = threshold; } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object thresholdValue = threshold.evaluate(eventsPerStream, newData, context); if (thresholdValue == null) { return null; } long threshold = IntervalComputerExprBase.toLong(thresholdValue); if (overlaps) { return computeInternalOverlaps(leftStart, leftEnd, rightStart, rightEnd, 0, threshold); } else { return computeInternalOverlaps(rightStart, rightEnd, leftStart, leftEnd, 0, threshold); } } public static boolean computeInternalOverlaps(long left, long leftEnd, long right, long rightEnd, long min, long max) { boolean match = ((left < right) && (right < leftEnd) && (leftEnd < rightEnd)); if (!match) { return false; } long delta = leftEnd - right; return min <= delta && delta <= max; } } public static class IntervalComputerOverlapsAndByMinMax implements IntervalComputer { private final boolean overlaps; private final ExprEvaluator minEval; private final ExprEvaluator maxEval; public IntervalComputerOverlapsAndByMinMax(boolean overlaps, ExprEvaluator minEval, ExprEvaluator maxEval) { this.overlaps = overlaps; this.minEval = minEval; this.maxEval = maxEval; } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object minValue = minEval.evaluate(eventsPerStream, newData, context); if (minValue == null) { return null; } Object maxValue = maxEval.evaluate(eventsPerStream, newData, context); if (maxValue == null) { return null; } long minThreshold = IntervalComputerExprBase.toLong(minValue); long maxThreshold = IntervalComputerExprBase.toLong(maxValue); if (overlaps) { return IntervalComputerOverlapsAndByThreshold.computeInternalOverlaps(leftStart, leftEnd, rightStart, rightEnd, minThreshold, maxThreshold); } else { return IntervalComputerOverlapsAndByThreshold.computeInternalOverlaps(rightStart, rightEnd, leftStart, leftEnd, minThreshold, maxThreshold); } } } /** * OverlappedBy. */ public static class IntervalComputerOverlappedByNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return (rightStart < leftStart) && (leftStart < rightEnd) && (rightEnd < leftEnd); } } /** * Starts. */ public static class IntervalComputerStartsNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return (leftStart == rightStart) && (leftEnd < rightEnd); } } public static class IntervalComputerStartsThreshold implements IntervalComputer { private static final Log log = LogFactory.getLog(IntervalComputerStartsThreshold.class); private final ExprEvaluator threshold; public IntervalComputerStartsThreshold(ExprEvaluator threshold) { this.threshold = threshold; } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object thresholdValue = threshold.evaluate(eventsPerStream, newData, context); if (thresholdValue == null) { return null; } long threshold = IntervalComputerExprBase.toLong(thresholdValue); if (threshold < 0) { log.warn("The 'finishes' date-time method does not allow negative threshold"); return null; } long delta = Math.abs(leftStart - rightStart); return delta <= threshold && (leftEnd < rightEnd); } } /** * Started-by. */ public static class IntervalComputerStartedByNoParam implements IntervalComputer { public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { return (leftStart == rightStart) && (leftEnd > rightEnd); } } public static class IntervalComputerStartedByThreshold implements IntervalComputer { private static final Log log = LogFactory.getLog(IntervalComputerStartedByThreshold.class); private final ExprEvaluator threshold; public IntervalComputerStartedByThreshold(ExprEvaluator threshold) { this.threshold = threshold; } public Boolean compute(long leftStart, long leftEnd, long rightStart, long rightEnd, EventBean[] eventsPerStream, boolean newData, ExprEvaluatorContext context) { Object thresholdValue = threshold.evaluate(eventsPerStream, newData, context); if (thresholdValue == null) { return null; } long threshold = IntervalComputerExprBase.toLong(thresholdValue); if (threshold < 0) { log.warn("The 'finishes' date-time method does not allow negative threshold"); return null; } long delta = Math.abs(leftStart - rightStart); return delta <= threshold && (leftEnd > rightEnd); } } }