com.espertech.esper.epl.expression.ExprTimePeriodImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.espertech.esper.epl.expression.ExprTimePeriodImpl.java

Source

/*
 * *************************************************************************************
 *  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.expression;

import com.espertech.esper.client.EventBean;
import com.espertech.esper.epl.datetime.eval.TimePeriod;
import com.espertech.esper.util.JavaClassHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayDeque;

/**
 * Expression representing a time period.
 * <p>
 * Child nodes to this expression carry the actual parts and must return a numeric value.
 */
public class ExprTimePeriodImpl extends ExprNodeBase implements ExprEvaluator, ExprTimePeriod {
    private static final Log log = LogFactory.getLog(ExprTimePeriodImpl.class);

    private final boolean hasYear;
    private final boolean hasMonth;
    private final boolean hasWeek;
    private final boolean hasDay;
    private final boolean hasHour;
    private final boolean hasMinute;
    private final boolean hasSecond;
    private final boolean hasMillisecond;
    private boolean hasVariable;
    private transient ExprEvaluator[] evaluators;
    private transient TimePeriodAdder[] adders;
    private static final long serialVersionUID = -7229827032500659319L;

    /**
     * Ctor.
     * @param hasDay true if the expression has that part, false if not
     * @param hasHour true if the expression has that part, false if not
     * @param hasMinute true if the expression has that part, false if not
     * @param hasSecond true if the expression has that part, false if not
     * @param hasMillisecond true if the expression has that part, false if not
     */
    public ExprTimePeriodImpl(boolean hasYear, boolean hasMonth, boolean hasWeek, boolean hasDay, boolean hasHour,
            boolean hasMinute, boolean hasSecond, boolean hasMillisecond) {
        this.hasYear = hasYear;
        this.hasMonth = hasMonth;
        this.hasWeek = hasWeek;
        this.hasDay = hasDay;
        this.hasHour = hasHour;
        this.hasMinute = hasMinute;
        this.hasSecond = hasSecond;
        this.hasMillisecond = hasMillisecond;
    }

    public ExprEvaluator getExprEvaluator() {
        return this;
    }

    /**
     * Indicator whether the time period has a day part child expression.
     * @return true for part present, false for not present
     */
    public boolean isHasDay() {
        return hasDay;
    }

    /**
     * Indicator whether the time period has a hour part child expression.
     * @return true for part present, false for not present
     */
    public boolean isHasHour() {
        return hasHour;
    }

    /**
     * Indicator whether the time period has a minute part child expression.
     * @return true for part present, false for not present
     */
    public boolean isHasMinute() {
        return hasMinute;
    }

    /**
     * Indicator whether the time period has a second part child expression.
     * @return true for part present, false for not present
     */
    public boolean isHasSecond() {
        return hasSecond;
    }

    /**
     * Indicator whether the time period has a millisecond part child expression.
     * @return true for part present, false for not present
     */
    public boolean isHasMillisecond() {
        return hasMillisecond;
    }

    /**
     * Indicator whether the time period has a year part child expression.
     * @return true for part present, false for not present
     */
    public boolean isHasYear() {
        return hasYear;
    }

    /**
     * Indicator whether the time period has a month part child expression.
     * @return true for part present, false for not present
     */
    public boolean isHasMonth() {
        return hasMonth;
    }

    /**
     * Indicator whether the time period has a week part child expression.
     * @return true for part present, false for not present
     */
    public boolean isHasWeek() {
        return hasWeek;
    }

    /**
     * Indicator whether the time period has a variable in any of the child expressions.
     * @return true for variable present, false for not present
     */
    public boolean hasVariable() {
        return hasVariable;
    }

    public void validate(ExprValidationContext validationContext) throws ExprValidationException {
        evaluators = ExprNodeUtility.getEvaluators(this.getChildNodes());
        for (ExprNode childNode : this.getChildNodes()) {
            validate(childNode);
        }

        ArrayDeque<TimePeriodAdder> list = new ArrayDeque<TimePeriodAdder>();
        if (hasYear) {
            list.add(new TimePeriodAdderYear());
        }
        if (hasMonth) {
            list.add(new TimePeriodAdderMonth());
        }
        if (hasWeek) {
            list.add(new TimePeriodAdderWeek());
        }
        if (hasDay) {
            list.add(new TimePeriodAdderDay());
        }
        if (hasHour) {
            list.add(new TimePeriodAdderHour());
        }
        if (hasMinute) {
            list.add(new TimePeriodAdderMinute());
        }
        if (hasSecond) {
            list.add(new TimePeriodAdderSecond());
        }
        if (hasMillisecond) {
            list.add(new TimePeriodAdderMSec());
        }
        adders = list.toArray(new TimePeriodAdder[list.size()]);
    }

    private void validate(ExprNode expression) throws ExprValidationException {
        if (expression == null) {
            return;
        }
        Class returnType = expression.getExprEvaluator().getType();
        if (!JavaClassHelper.isNumeric(returnType)) {
            throw new ExprValidationException("Time period expression requires a numeric parameter type");
        }
        if (expression instanceof ExprVariableNode) {
            hasVariable = true;
        }
    }

    public Object evaluate(EventBean[] eventsPerStream, boolean isNewData,
            ExprEvaluatorContext exprEvaluatorContext) {
        double seconds = 0;
        for (int i = 0; i < adders.length; i++) {
            Double result = eval(evaluators[i], eventsPerStream, exprEvaluatorContext);
            if (result == null) {
                logWarn(i);
                return null;
            }
            seconds += adders[i].compute(result);
        }
        return seconds;
    }

    private void logWarn(int ctr) {
        log.warn("Time period expression returned a null value for expression '"
                + this.getChildNodes()[ctr].toExpressionString() + "'");
    }

    public Class getType() {
        return Double.class;
    }

    public boolean isConstantResult() {
        for (ExprNode child : getChildNodes()) {
            if (!child.isConstantResult()) {
                return false;
            }
        }
        return true;
    }

    public String toExpressionString() {
        StringBuilder buf = new StringBuilder();
        int exprCtr = 0;
        if (hasYear) {
            buf.append(getChildNodes()[exprCtr++].toExpressionString());
            buf.append(" years ");
        }
        if (hasMonth) {
            buf.append(getChildNodes()[exprCtr++].toExpressionString());
            buf.append(" months ");
        }
        if (hasWeek) {
            buf.append(getChildNodes()[exprCtr++].toExpressionString());
            buf.append(" weeks ");
        }
        if (hasDay) {
            buf.append(getChildNodes()[exprCtr++].toExpressionString());
            buf.append(" days ");
        }
        if (hasHour) {
            buf.append(getChildNodes()[exprCtr++].toExpressionString());
            buf.append(" hours ");
        }
        if (hasMinute) {
            buf.append(getChildNodes()[exprCtr++].toExpressionString());
            buf.append(" minutes ");
        }
        if (hasSecond) {
            buf.append(getChildNodes()[exprCtr++].toExpressionString());
            buf.append(" seconds ");
        }
        if (hasMillisecond) {
            buf.append(getChildNodes()[exprCtr].toExpressionString());
            buf.append(" milliseconds ");
        }
        return buf.toString();
    }

    public boolean equalsNode(ExprNode node) {
        if (!(node instanceof ExprTimePeriodImpl)) {
            return false;
        }
        ExprTimePeriodImpl other = (ExprTimePeriodImpl) node;

        if (hasYear != other.hasYear) {
            return false;
        }
        if (hasMonth != other.hasMonth) {
            return false;
        }
        if (hasWeek != other.hasWeek) {
            return false;
        }
        if (hasDay != other.hasDay) {
            return false;
        }
        if (hasHour != other.hasHour) {
            return false;
        }
        if (hasMinute != other.hasMinute) {
            return false;
        }
        if (hasSecond != other.hasSecond) {
            return false;
        }
        return (hasMillisecond == other.hasMillisecond);
    }

    private Double eval(ExprEvaluator expr, EventBean[] events, ExprEvaluatorContext exprEvaluatorContext) {
        Object value = expr.evaluate(events, true, exprEvaluatorContext);
        if (value == null) {
            return null;
        }
        if (value instanceof BigDecimal) {
            return ((Number) value).doubleValue();
        }
        if (value instanceof BigInteger) {
            return ((Number) value).doubleValue();
        }
        return ((Number) value).doubleValue();
    }

    public TimePeriod evaluateGetTimePeriod(EventBean[] eventsPerStream, boolean newData,
            ExprEvaluatorContext context) {
        int exprCtr = 0;

        Integer year = null;
        if (hasYear) {
            year = getInt(evaluators[exprCtr++].evaluate(eventsPerStream, newData, context));
        }

        Integer month = null;
        if (hasMonth) {
            month = getInt(evaluators[exprCtr++].evaluate(eventsPerStream, newData, context));
        }

        Integer week = null;
        if (hasWeek) {
            week = getInt(evaluators[exprCtr++].evaluate(eventsPerStream, newData, context));
        }

        Integer day = null;
        if (hasDay) {
            day = getInt(evaluators[exprCtr++].evaluate(eventsPerStream, newData, context));
        }

        Integer hours = null;
        if (hasHour) {
            hours = getInt(evaluators[exprCtr++].evaluate(eventsPerStream, newData, context));
        }

        Integer minutes = null;
        if (hasMinute) {
            minutes = getInt(evaluators[exprCtr++].evaluate(eventsPerStream, newData, context));
        }

        Integer seconds = null;
        if (hasSecond) {
            seconds = getInt(evaluators[exprCtr++].evaluate(eventsPerStream, newData, context));
        }

        Integer milliseconds = null;
        if (hasMillisecond) {
            milliseconds = getInt(evaluators[exprCtr++].evaluate(eventsPerStream, newData, context));
        }
        return new TimePeriod(year, month, week, day, hours, minutes, seconds, milliseconds);
    }

    private Integer getInt(Object evaluated) {
        if (evaluated == null) {
            return null;
        }
        return ((Number) evaluated).intValue();
    }

    public static interface TimePeriodAdder {
        public double compute(Double value);
    }

    public static class TimePeriodAdderYear implements TimePeriodAdder {
        private static final double MULTIPLIER = 365 * 24 * 60 * 60;

        public double compute(Double value) {
            return value * MULTIPLIER;
        }
    }

    public static class TimePeriodAdderMonth implements TimePeriodAdder {
        private static final double MULTIPLIER = 30 * 24 * 60 * 60;

        public double compute(Double value) {
            return value * MULTIPLIER;
        }
    }

    public static class TimePeriodAdderWeek implements TimePeriodAdder {
        private static final double MULTIPLIER = 7 * 24 * 60 * 60;

        public double compute(Double value) {
            return value * MULTIPLIER;
        }
    }

    public static class TimePeriodAdderDay implements TimePeriodAdder {
        private static final double MULTIPLIER = 24 * 60 * 60;

        public double compute(Double value) {
            return value * MULTIPLIER;
        }
    }

    public static class TimePeriodAdderHour implements TimePeriodAdder {
        private static final double MULTIPLIER = 60 * 60;

        public double compute(Double value) {
            return value * MULTIPLIER;
        }
    }

    public static class TimePeriodAdderMinute implements TimePeriodAdder {
        private static final double MULTIPLIER = 60;

        public double compute(Double value) {
            return value * MULTIPLIER;
        }
    }

    public static class TimePeriodAdderSecond implements TimePeriodAdder {
        public double compute(Double value) {
            return value;
        }
    }

    public static class TimePeriodAdderMSec implements TimePeriodAdder {
        public double compute(Double value) {
            return value / 1000d;
        }
    }
}