/* *************************************************************************************** * Copyright (C) 2006 EsperTech, Inc. All rights reserved. * * http://www.espertech.com/esper * * 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.eval; import com.espertech.esper.client.EventBean; import com.espertech.esper.client.EventPropertyGetter; import com.espertech.esper.client.EventType; import com.espertech.esper.epl.datetime.calop.CalendarOp; import com.espertech.esper.epl.datetime.interval.IntervalOp; import com.espertech.esper.epl.datetime.reformatop.ReformatOp; import com.espertech.esper.epl.expression.core.ExprEvaluatorContext; import com.espertech.esper.epl.expression.dot.ExprDotEval; import com.espertech.esper.epl.expression.dot.ExprDotEvalVisitor; import com.espertech.esper.epl.expression.time.TimeAbacus; import com.espertech.esper.epl.rettype.EPType; import com.espertech.esper.epl.rettype.EPTypeHelper; import com.espertech.esper.util.JavaClassHelper; import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.TimeZone; public class ExprDotEvalDT implements ExprDotEval { private final EPType returnType; private final DTLocalEvaluator evaluator; public ExprDotEvalDT(List<CalendarOp> calendarOps, TimeZone timeZone, TimeAbacus timeAbacus, ReformatOp reformatOp, IntervalOp intervalOp, Class inputType, EventType inputEventType) { this.evaluator = getEvaluator(calendarOps, timeZone, timeAbacus, inputType, inputEventType, reformatOp, intervalOp); if (intervalOp != null) { returnType = EPTypeHelper.singleValue(Boolean.class); } else if (reformatOp != null) { returnType = EPTypeHelper.singleValue(reformatOp.getReturnType()); } else { // only calendar ops if (inputEventType != null) { returnType = EPTypeHelper.singleValue(inputEventType.getPropertyType(inputEventType.getStartTimestampPropertyName())); } else { returnType = EPTypeHelper.singleValue(inputType); } } } public EPType getTypeInfo() { return returnType; } public void visit(ExprDotEvalVisitor visitor) { visitor.visitDateTime(); } public DTLocalEvaluator getEvaluator(List<CalendarOp> calendarOps, TimeZone timeZone, TimeAbacus timeAbacus, Class inputType, EventType inputEventType, ReformatOp reformatOp, IntervalOp intervalOp) { if (inputEventType == null) { if (reformatOp != null) { if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, Calendar.class)) { if (calendarOps.isEmpty()) { return new DTLocalEvaluatorCalReformat(reformatOp); } return new DTLocalEvaluatorCalOpsReformat(calendarOps, reformatOp); } else if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, Date.class)) { if (calendarOps.isEmpty()) { return new DTLocalEvaluatorDateReformat(reformatOp); } return new DTLocalEvaluatorDateOpsReformat(calendarOps, reformatOp, timeZone); } else if (JavaClassHelper.getBoxedType(inputType) == Long.class) { if (calendarOps.isEmpty()) { return new DTLocalEvaluatorLongReformat(reformatOp); } return new DTLocalEvaluatorLongOpsReformat(calendarOps, reformatOp, timeZone, timeAbacus); } else if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, LocalDateTime.class)) { if (calendarOps.isEmpty()) { return new DTLocalEvaluatorLocalDateTimeReformat(reformatOp); } return new DTLocalEvaluatorLocalDateTimeOpsReformat(calendarOps, reformatOp); } else if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, ZonedDateTime.class)) { if (calendarOps.isEmpty()) { return new DTLocalEvaluatorZonedDateTimeReformat(reformatOp); } return new DTLocalEvaluatorZonedDateTimeOpsReformat(calendarOps, reformatOp); } } else if (intervalOp != null) { if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, Calendar.class)) { if (calendarOps.isEmpty()) { return new DTLocalEvaluatorCalInterval(intervalOp); } return new DTLocalEvaluatorCalOpsInterval(calendarOps, intervalOp, timeZone); } else if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, Date.class)) { if (calendarOps.isEmpty()) { return new DTLocalEvaluatorDateInterval(intervalOp); } return new DTLocalEvaluatorDateOpsInterval(calendarOps, intervalOp, timeZone); } else if (JavaClassHelper.getBoxedType(inputType) == Long.class) { if (calendarOps.isEmpty()) { return new DTLocalEvaluatorLongInterval(intervalOp); } return new DTLocalEvaluatorLongOpsInterval(calendarOps, intervalOp, timeZone, timeAbacus); } else if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, LocalDateTime.class)) { if (calendarOps.isEmpty()) { return new DTLocalEvaluatorLDTInterval(intervalOp, timeZone); } return new DTLocalEvaluatorLocalDateTimeOpsInterval(calendarOps, intervalOp, timeZone); } else if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, ZonedDateTime.class)) { if (calendarOps.isEmpty()) { return new DTLocalEvaluatorZDTInterval(intervalOp); } return new DTLocalEvaluatorZonedDateTimeOpsInterval(calendarOps, intervalOp); } } else { // only calendar ops, nothing else if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, Calendar.class)) { return new DTLocalEvaluatorCalOpsCal(calendarOps); } else if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, Date.class)) { return new DTLocalEvaluatorCalOpsDate(calendarOps, timeZone); } else if (JavaClassHelper.getBoxedType(inputType) == Long.class) { return new DTLocalEvaluatorCalOpsLong(calendarOps, timeZone, timeAbacus); } else if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, LocalDateTime.class)) { return new DTLocalEvaluatorCalOpsLocalDateTime(calendarOps); } else if (JavaClassHelper.isSubclassOrImplementsInterface(inputType, ZonedDateTime.class)) { return new DTLocalEvaluatorCalOpsZonedDateTime(calendarOps); } } throw new IllegalArgumentException("Invalid input type '" + inputType + "'"); } EventPropertyGetter getter = inputEventType.getGetter(inputEventType.getStartTimestampPropertyName()); Class getterResultType = inputEventType.getPropertyType(inputEventType.getStartTimestampPropertyName()); if (reformatOp != null) { DTLocalEvaluator inner = getEvaluator(calendarOps, timeZone, timeAbacus, getterResultType, null, reformatOp, null); return new DTLocalEvaluatorBeanReformat(getter, inner); } if (intervalOp == null) { // only calendar ops DTLocalEvaluator inner = getEvaluator(calendarOps, timeZone, timeAbacus, getterResultType, null, null, null); return new DTLocalEvaluatorBeanCalOps(getter, inner); } // have interval ops but no end timestamp if (inputEventType.getEndTimestampPropertyName() == null) { DTLocalEvaluator inner = getEvaluator(calendarOps, timeZone, timeAbacus, getterResultType, null, null, intervalOp); return new DTLocalEvaluatorBeanIntervalNoEndTS(getter, inner); } // interval ops and have end timestamp EventPropertyGetter getterEndTimestamp = inputEventType.getGetter(inputEventType.getEndTimestampPropertyName()); DTLocalEvaluatorIntervalComp inner = (DTLocalEvaluatorIntervalComp) getEvaluator(calendarOps, timeZone, timeAbacus, getterResultType, null, null, intervalOp); return new DTLocalEvaluatorBeanIntervalWithEnd(getter, getterEndTimestamp, inner); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { if (target == null) { return null; } return evaluator.evaluate(target, eventsPerStream, isNewData, exprEvaluatorContext); } protected static void evaluateCalOps(List<CalendarOp> calendarOps, Calendar cal, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { for (CalendarOp calendarOp : calendarOps) { calendarOp.evaluate(cal, eventsPerStream, isNewData, exprEvaluatorContext); } } protected static LocalDateTime evaluateCalOps(List<CalendarOp> calendarOps, LocalDateTime ldt, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { for (CalendarOp calendarOp : calendarOps) { ldt = calendarOp.evaluate(ldt, eventsPerStream, isNewData, exprEvaluatorContext); } return ldt; } protected static ZonedDateTime evaluateCalOps(List<CalendarOp> calendarOps, ZonedDateTime zdt, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { for (CalendarOp calendarOp : calendarOps) { zdt = calendarOp.evaluate(zdt, eventsPerStream, isNewData, exprEvaluatorContext); } return zdt; } private static interface DTLocalEvaluator { public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext); } private abstract static class DTLocalEvaluatorReformatBase implements DTLocalEvaluator { protected final ReformatOp reformatOp; protected DTLocalEvaluatorReformatBase(ReformatOp reformatOp) { this.reformatOp = reformatOp; } } private abstract static class DTLocalEvaluatorCalopReformatBase implements DTLocalEvaluator { protected final List<CalendarOp> calendarOps; protected final ReformatOp reformatOp; protected DTLocalEvaluatorCalopReformatBase(List<CalendarOp> calendarOps, ReformatOp reformatOp) { this.calendarOps = calendarOps; this.reformatOp = reformatOp; } } private static class DTLocalEvaluatorCalReformat extends DTLocalEvaluatorReformatBase { private DTLocalEvaluatorCalReformat(ReformatOp reformatOp) { super(reformatOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { return reformatOp.evaluate((Calendar) target, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorCalOpsReformat extends DTLocalEvaluatorCalopReformatBase { private DTLocalEvaluatorCalOpsReformat(List<CalendarOp> calendarOps, ReformatOp reformatOp) { super(calendarOps, reformatOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Calendar cal = (Calendar) ((Calendar) target).clone(); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); return reformatOp.evaluate(cal, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorDateReformat extends DTLocalEvaluatorReformatBase { private DTLocalEvaluatorDateReformat(ReformatOp reformatOp) { super(reformatOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { return reformatOp.evaluate((Date) target, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorLocalDateTimeReformat extends DTLocalEvaluatorReformatBase { private DTLocalEvaluatorLocalDateTimeReformat(ReformatOp reformatOp) { super(reformatOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { return reformatOp.evaluate((LocalDateTime) target, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorZonedDateTimeReformat extends DTLocalEvaluatorReformatBase { private DTLocalEvaluatorZonedDateTimeReformat(ReformatOp reformatOp) { super(reformatOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { return reformatOp.evaluate((ZonedDateTime) target, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorDateOpsReformat extends DTLocalEvaluatorCalopReformatBase { private final TimeZone timeZone; private DTLocalEvaluatorDateOpsReformat(List<CalendarOp> calendarOps, ReformatOp reformatOp, TimeZone timeZone) { super(calendarOps, reformatOp); this.timeZone = timeZone; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Calendar cal = Calendar.getInstance(timeZone); cal.setTimeInMillis(((Date) target).getTime()); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); return reformatOp.evaluate(cal, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorLongReformat extends DTLocalEvaluatorReformatBase { private DTLocalEvaluatorLongReformat(ReformatOp reformatOp) { super(reformatOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { return reformatOp.evaluate((Long) target, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorLongOpsReformat extends DTLocalEvaluatorCalopReformatBase { private final TimeZone timeZone; private final TimeAbacus timeAbacus; private DTLocalEvaluatorLongOpsReformat(List<CalendarOp> calendarOps, ReformatOp reformatOp, TimeZone timeZone, TimeAbacus timeAbacus) { super(calendarOps, reformatOp); this.timeZone = timeZone; this.timeAbacus = timeAbacus; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Calendar cal = Calendar.getInstance(timeZone); timeAbacus.calendarSet((Long) target, cal); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); return reformatOp.evaluate(cal, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorLocalDateTimeOpsReformat extends DTLocalEvaluatorCalopReformatBase { private DTLocalEvaluatorLocalDateTimeOpsReformat(List<CalendarOp> calendarOps, ReformatOp reformatOp) { super(calendarOps, reformatOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { LocalDateTime ldt = (LocalDateTime) target; ldt = evaluateCalOps(calendarOps, ldt, eventsPerStream, isNewData, exprEvaluatorContext); return reformatOp.evaluate(ldt, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorZonedDateTimeOpsReformat extends DTLocalEvaluatorCalopReformatBase { private DTLocalEvaluatorZonedDateTimeOpsReformat(List<CalendarOp> calendarOps, ReformatOp reformatOp) { super(calendarOps, reformatOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { ZonedDateTime zdt = (ZonedDateTime) target; zdt = evaluateCalOps(calendarOps, zdt, eventsPerStream, isNewData, exprEvaluatorContext); return reformatOp.evaluate(zdt, eventsPerStream, isNewData, exprEvaluatorContext); } } /** * Interval methods. */ private interface DTLocalEvaluatorIntervalComp { public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext); } private abstract static class DTLocalEvaluatorIntervalBase implements DTLocalEvaluator, DTLocalEvaluatorIntervalComp { protected final IntervalOp intervalOp; protected DTLocalEvaluatorIntervalBase(IntervalOp intervalOp) { this.intervalOp = intervalOp; } } private abstract static class DTLocalEvaluatorCalOpsIntervalBase implements DTLocalEvaluator, DTLocalEvaluatorIntervalComp { protected final List<CalendarOp> calendarOps; protected final IntervalOp intervalOp; protected DTLocalEvaluatorCalOpsIntervalBase(List<CalendarOp> calendarOps, IntervalOp intervalOp) { this.calendarOps = calendarOps; this.intervalOp = intervalOp; } } private static class DTLocalEvaluatorCalInterval extends DTLocalEvaluatorIntervalBase { private DTLocalEvaluatorCalInterval(IntervalOp intervalOp) { super(intervalOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long time = ((Calendar) target).getTimeInMillis(); return intervalOp.evaluate(time, time, eventsPerStream, isNewData, exprEvaluatorContext); } public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long start = ((Calendar) startTimestamp).getTimeInMillis(); long end = ((Calendar) endTimestamp).getTimeInMillis(); return intervalOp.evaluate(start, end, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorLDTInterval extends DTLocalEvaluatorIntervalBase { private final TimeZone timeZone; public DTLocalEvaluatorLDTInterval(IntervalOp intervalOp, TimeZone timeZone) { super(intervalOp); this.timeZone = timeZone; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long time = DatetimeLongCoercerLocalDateTime.coerce((LocalDateTime) target, timeZone); return intervalOp.evaluate(time, time, eventsPerStream, isNewData, exprEvaluatorContext); } public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long start = DatetimeLongCoercerLocalDateTime.coerce((LocalDateTime) startTimestamp, timeZone); long end = DatetimeLongCoercerLocalDateTime.coerce((LocalDateTime) endTimestamp, timeZone); return intervalOp.evaluate(start, end, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorZDTInterval extends DTLocalEvaluatorIntervalBase { public DTLocalEvaluatorZDTInterval(IntervalOp intervalOp) { super(intervalOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long time = DatetimeLongCoercerZonedDateTime.coerce((ZonedDateTime) target); return intervalOp.evaluate(time, time, eventsPerStream, isNewData, exprEvaluatorContext); } public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long start = DatetimeLongCoercerZonedDateTime.coerce((ZonedDateTime) startTimestamp); long end = DatetimeLongCoercerZonedDateTime.coerce((ZonedDateTime) endTimestamp); return intervalOp.evaluate(start, end, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorCalOpsInterval extends DTLocalEvaluatorCalOpsIntervalBase { private final TimeZone timeZone; private DTLocalEvaluatorCalOpsInterval(List<CalendarOp> calendarOps, IntervalOp intervalOp, TimeZone timeZone) { super(calendarOps, intervalOp); this.timeZone = timeZone; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Calendar cal = (Calendar) ((Calendar) target).clone(); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); long time = cal.getTimeInMillis(); return intervalOp.evaluate(time, time, eventsPerStream, isNewData, exprEvaluatorContext); } public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long startLong = ((Calendar) startTimestamp).getTimeInMillis(); long endLong = ((Calendar) endTimestamp).getTimeInMillis(); Calendar cal = Calendar.getInstance(timeZone); cal.setTimeInMillis(startLong); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); long startTime = cal.getTimeInMillis(); long endTime = startTime + (endLong - startLong); return intervalOp.evaluate(startTime, endTime, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorDateInterval extends DTLocalEvaluatorIntervalBase { private DTLocalEvaluatorDateInterval(IntervalOp intervalOp) { super(intervalOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long time = ((Date) target).getTime(); return intervalOp.evaluate(time, time, eventsPerStream, isNewData, exprEvaluatorContext); } public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long start = ((Date) startTimestamp).getTime(); long end = ((Date) endTimestamp).getTime(); return intervalOp.evaluate(start, end, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorDateOpsInterval extends DTLocalEvaluatorCalOpsIntervalBase { private final TimeZone timeZone; private DTLocalEvaluatorDateOpsInterval(List<CalendarOp> calendarOps, IntervalOp intervalOp, TimeZone timeZone) { super(calendarOps, intervalOp); this.timeZone = timeZone; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Calendar cal = Calendar.getInstance(timeZone); cal.setTimeInMillis(((Date) target).getTime()); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); long time = cal.getTimeInMillis(); return intervalOp.evaluate(time, time, eventsPerStream, isNewData, exprEvaluatorContext); } public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long startLong = ((Date) startTimestamp).getTime(); long endLong = ((Date) endTimestamp).getTime(); Calendar cal = Calendar.getInstance(timeZone); cal.setTimeInMillis(startLong); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); long startTime = cal.getTimeInMillis(); long endTime = startTime + (endLong - startLong); return intervalOp.evaluate(startTime, endTime, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorLongInterval extends DTLocalEvaluatorIntervalBase { private DTLocalEvaluatorLongInterval(IntervalOp intervalOp) { super(intervalOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long time = (Long) target; return intervalOp.evaluate(time, time, eventsPerStream, isNewData, exprEvaluatorContext); } public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long startTime = (Long) startTimestamp; long endTime = (Long) endTimestamp; return intervalOp.evaluate(startTime, endTime, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorLongOpsInterval extends DTLocalEvaluatorCalOpsIntervalBase { private final TimeZone timeZone; private final TimeAbacus timeAbacus; private DTLocalEvaluatorLongOpsInterval(List<CalendarOp> calendarOps, IntervalOp intervalOp, TimeZone timeZone, TimeAbacus timeAbacus) { super(calendarOps, intervalOp); this.timeZone = timeZone; this.timeAbacus = timeAbacus; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Calendar cal = Calendar.getInstance(timeZone); long startRemainder = timeAbacus.calendarSet((Long) target, cal); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); long time = timeAbacus.calendarGet(cal, startRemainder); return intervalOp.evaluate(time, time, eventsPerStream, isNewData, exprEvaluatorContext); } public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { long startLong = (Long) startTimestamp; long endLong = (Long) endTimestamp; Calendar cal = Calendar.getInstance(timeZone); long startRemainder = timeAbacus.calendarSet(startLong, cal); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); long startTime = timeAbacus.calendarGet(cal, startRemainder); long endTime = startTime + (endLong - startLong); return intervalOp.evaluate(startTime, endTime, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorLocalDateTimeOpsInterval extends DTLocalEvaluatorCalOpsIntervalBase { private final TimeZone timeZone; private DTLocalEvaluatorLocalDateTimeOpsInterval(List<CalendarOp> calendarOps, IntervalOp intervalOp, TimeZone timeZone) { super(calendarOps, intervalOp); this.timeZone = timeZone; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { LocalDateTime ldt = (LocalDateTime) target; ldt = evaluateCalOps(calendarOps, ldt, eventsPerStream, isNewData, exprEvaluatorContext); long time = DatetimeLongCoercerLocalDateTime.coerce(ldt, timeZone); return intervalOp.evaluate(time, time, eventsPerStream, isNewData, exprEvaluatorContext); } public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { LocalDateTime start = (LocalDateTime) startTimestamp; LocalDateTime end = (LocalDateTime) endTimestamp; long deltaMSec = DatetimeLongCoercerLocalDateTime.coerce(end, timeZone) - DatetimeLongCoercerLocalDateTime.coerce(start, timeZone); start = evaluateCalOps(calendarOps, start, eventsPerStream, isNewData, exprEvaluatorContext); long startLong = DatetimeLongCoercerLocalDateTime.coerce(start, timeZone); long endTime = startLong + deltaMSec; return intervalOp.evaluate(startLong, endTime, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorZonedDateTimeOpsInterval extends DTLocalEvaluatorCalOpsIntervalBase { private DTLocalEvaluatorZonedDateTimeOpsInterval(List<CalendarOp> calendarOps, IntervalOp intervalOp) { super(calendarOps, intervalOp); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { ZonedDateTime zdt = (ZonedDateTime) target; zdt = evaluateCalOps(calendarOps, zdt, eventsPerStream, isNewData, exprEvaluatorContext); long time = DatetimeLongCoercerZonedDateTime.coerce(zdt); return intervalOp.evaluate(time, time, eventsPerStream, isNewData, exprEvaluatorContext); } public Object evaluate(Object startTimestamp, Object endTimestamp, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { ZonedDateTime start = (ZonedDateTime) startTimestamp; ZonedDateTime end = (ZonedDateTime) endTimestamp; long deltaMSec = DatetimeLongCoercerZonedDateTime.coerce(end) - DatetimeLongCoercerZonedDateTime.coerce(start); start = evaluateCalOps(calendarOps, start, eventsPerStream, isNewData, exprEvaluatorContext); long startLong = DatetimeLongCoercerZonedDateTime.coerce(start); long endTime = startLong + deltaMSec; return intervalOp.evaluate(startLong, endTime, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorBeanReformat implements DTLocalEvaluator { private final EventPropertyGetter getter; private final DTLocalEvaluator inner; private DTLocalEvaluatorBeanReformat(EventPropertyGetter getter, DTLocalEvaluator inner) { this.getter = getter; this.inner = inner; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Object timestamp = getter.get((EventBean) target); if (timestamp == null) { return null; } return inner.evaluate(timestamp, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorBeanIntervalNoEndTS implements DTLocalEvaluator { private final EventPropertyGetter getter; private final DTLocalEvaluator inner; private DTLocalEvaluatorBeanIntervalNoEndTS(EventPropertyGetter getter, DTLocalEvaluator inner) { this.getter = getter; this.inner = inner; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Object timestamp = getter.get((EventBean) target); if (timestamp == null) { return null; } return inner.evaluate(timestamp, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorBeanIntervalWithEnd implements DTLocalEvaluator { private final EventPropertyGetter getterStartTimestamp; private final EventPropertyGetter getterEndTimestamp; private final DTLocalEvaluatorIntervalComp inner; private DTLocalEvaluatorBeanIntervalWithEnd(EventPropertyGetter getterStartTimestamp, EventPropertyGetter getterEndTimestamp, DTLocalEvaluatorIntervalComp inner) { this.getterStartTimestamp = getterStartTimestamp; this.getterEndTimestamp = getterEndTimestamp; this.inner = inner; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Object startTimestamp = getterStartTimestamp.get((EventBean) target); if (startTimestamp == null) { return null; } Object endTimestamp = getterEndTimestamp.get((EventBean) target); if (endTimestamp == null) { return null; } return inner.evaluate(startTimestamp, endTimestamp, eventsPerStream, isNewData, exprEvaluatorContext); } } private abstract class DTLocalEvaluatorCalOpsCalBase { protected final List<CalendarOp> calendarOps; private DTLocalEvaluatorCalOpsCalBase(List<CalendarOp> calendarOps) { this.calendarOps = calendarOps; } } private class DTLocalEvaluatorCalOpsLong extends DTLocalEvaluatorCalOpsCalBase implements DTLocalEvaluator { private final TimeZone timeZone; private final TimeAbacus timeAbacus; private DTLocalEvaluatorCalOpsLong(List<CalendarOp> calendarOps, TimeZone timeZone, TimeAbacus timeAbacus) { super(calendarOps); this.timeZone = timeZone; this.timeAbacus = timeAbacus; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Long longValue = (Long) target; Calendar cal = Calendar.getInstance(timeZone); long remainder = timeAbacus.calendarSet(longValue, cal); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); return timeAbacus.calendarGet(cal, remainder); } } private class DTLocalEvaluatorCalOpsDate extends DTLocalEvaluatorCalOpsCalBase implements DTLocalEvaluator { private final TimeZone timeZone; private DTLocalEvaluatorCalOpsDate(List<CalendarOp> calendarOps, TimeZone timeZone) { super(calendarOps); this.timeZone = timeZone; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Date dateValue = (Date) target; Calendar cal = Calendar.getInstance(timeZone); cal.setTimeInMillis(dateValue.getTime()); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); return cal.getTime(); } } private class DTLocalEvaluatorCalOpsCal extends DTLocalEvaluatorCalOpsCalBase implements DTLocalEvaluator { private DTLocalEvaluatorCalOpsCal(List<CalendarOp> calendarOps) { super(calendarOps); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Calendar calValue = (Calendar) target; Calendar cal = (Calendar) calValue.clone(); evaluateCalOps(calendarOps, cal, eventsPerStream, isNewData, exprEvaluatorContext); return cal; } } private class DTLocalEvaluatorCalOpsLocalDateTime extends DTLocalEvaluatorCalOpsCalBase implements DTLocalEvaluator { public DTLocalEvaluatorCalOpsLocalDateTime(List<CalendarOp> calendarOps) { super(calendarOps); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { LocalDateTime ldt = (LocalDateTime) target; return evaluateCalOps(calendarOps, ldt, eventsPerStream, isNewData, exprEvaluatorContext); } } private class DTLocalEvaluatorCalOpsZonedDateTime extends DTLocalEvaluatorCalOpsCalBase implements DTLocalEvaluator { private DTLocalEvaluatorCalOpsZonedDateTime(List<CalendarOp> calendarOps) { super(calendarOps); } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { ZonedDateTime zdt = (ZonedDateTime) target; return evaluateCalOps(calendarOps, zdt, eventsPerStream, isNewData, exprEvaluatorContext); } } private static class DTLocalEvaluatorBeanCalOps implements DTLocalEvaluator { private final EventPropertyGetter getter; private final DTLocalEvaluator inner; private DTLocalEvaluatorBeanCalOps(EventPropertyGetter getter, DTLocalEvaluator inner) { this.getter = getter; this.inner = inner; } public Object evaluate(Object target, EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) { Object timestamp = getter.get((EventBean) target); if (timestamp == null) { return null; } return inner.evaluate(timestamp, eventsPerStream, isNewData, exprEvaluatorContext); } } }