Package com.espertech.esper.epl.declexpr

Source Code of com.espertech.esper.epl.declexpr.ExprDeclaredNodeImpl

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

import com.espertech.esper.client.EventType;
import com.espertech.esper.client.annotation.Audit;
import com.espertech.esper.client.annotation.AuditEnum;
import com.espertech.esper.epl.core.StreamTypeService;
import com.espertech.esper.epl.core.StreamTypeServiceImpl;
import com.espertech.esper.epl.expression.*;
import com.espertech.esper.epl.spec.ExpressionDeclItem;
import com.espertech.esper.util.SerializableObjectCopier;

import java.util.ArrayList;
import java.util.List;

/**
* Expression instance as declared elsewhere.
*/
public class ExprDeclaredNodeImpl extends ExprNodeBase implements ExprDeclaredNode
{
    private static final long serialVersionUID = 9140100131374697808L;

    private final ExpressionDeclItem prototype;
    private List<ExprNode> chainParameters;
    private transient ExprEvaluator exprEvaluator;
    private ExprNode expressionBodyCopy;

    public ExprDeclaredNodeImpl(ExpressionDeclItem prototype, List<ExprNode> chainParameters) {
        this.prototype = prototype;
        this.chainParameters = chainParameters;

        // copy expression - we do it at this time and not later
        try {
             expressionBodyCopy = (ExprNode) SerializableObjectCopier.copy(prototype.getInner());
        } catch (Exception e) {
            throw new RuntimeException("Internal error providing expression tree: " + e.getMessage(), e);
        }
    }

    /**
     * Received indication of the streams and types available before sub-selects are started and expression validation occurs.
     */
    public void setSubselectOuterStreamNames(String[] outerStreamNames,
                                             EventType[] outerEventTypesSelect,
                                             String[] outerEventTypeNames,
                                             String engineURI,
                                             ExprSubselectNode subselect,
                                             String subexpressionStreamName,
                                             EventType subselectStreamType,
                                             String subselecteventTypeName)
        throws ExprValidationException
    {
        checkParameterCount();

        // determine stream ids for each parameter
        int[] streamParameters = new int[chainParameters.size()];
        for (int param = 0; param < chainParameters.size(); param++) {
            if (!(chainParameters.get(param) instanceof ExprIdentNode)) {
                throw new ExprValidationException("Sub-selects in an expression declaration require passing only stream names as parameters");
            }
            String parameterName = ((ExprIdentNode) chainParameters.get(param)).getUnresolvedPropertyName();
            int streamId = -1;
            for (int i =0; i < outerStreamNames.length; i++) {
                if (parameterName.equals(outerStreamNames[i])) {
                    streamId  = i;
                    break;
                }
            }
            if (streamId == -1) {
                throw new ExprValidationException("Invalid parameter to expression declaration, parameter " + param + " is not the name of a stream in the query");
            }
            streamParameters[param] = streamId;
        }

        // compile a new StreamTypeService for use in validating that particular subselect
        EventType[] eventTypes = new EventType[chainParameters.size() + 1];
        String[] streamNames = new String[chainParameters.size() + 1];
        eventTypes[0] = subselectStreamType;
        streamNames[0] = subexpressionStreamName;
        for (int i = 0; i < streamParameters.length; i++) {
            eventTypes[i+1] = outerEventTypesSelect[streamParameters[i]];
            streamNames[i+1] = prototype.getParametersNames().get(i);
        }

        StreamTypeServiceImpl availableTypes = new StreamTypeServiceImpl(eventTypes, streamNames, new boolean[eventTypes.length], engineURI, false);
        availableTypes.setRequireStreamNames(true);

        // apply
        subselect.setFilterSubqueryStreamTypes(availableTypes);
    }

    public void validate(ExprValidationContext validationContext) throws ExprValidationException
    {
        if (exprEvaluator != null) {
            return; // already evaluated
        }

        if (!this.getChildNodes().isEmpty()) {
            throw new IllegalStateException("Execution node has its own child nodes");
        }

        // validate chain
        List<ExprNode> validated = new ArrayList<ExprNode>();
        for (ExprNode expr : chainParameters) {
            validated.add(ExprNodeUtil.getValidatedSubtree(expr, validationContext));
        }
        chainParameters = validated;

        // validate parameter count
        checkParameterCount();

        // create context for expression body
        EventType[] eventTypes = new EventType[prototype.getParametersNames().size()];
        String[] streamNames = new String[prototype.getParametersNames().size()];
        boolean[] isIStreamOnly = new boolean[prototype.getParametersNames().size()];
        int[] streamsIdsPerStream = new int[prototype.getParametersNames().size()];
        boolean allStreamIdsMatch = true;

        for (int i = 0; i < prototype.getParametersNames().size(); i++) {
            ExprNode parameter = chainParameters.get(i);
            if (!(parameter instanceof ExprStreamUnderlyingNode)) {
                throw new ExprValidationException("Expression '" + prototype.getName() + "' requires a stream name as a parameter");
            }
            ExprStreamUnderlyingNode und = (ExprStreamUnderlyingNode) parameter;
            eventTypes[i] = validationContext.getStreamTypeService().getEventTypes()[und.getStreamId()];
            isIStreamOnly[i] = validationContext.getStreamTypeService().getIStreamOnly()[und.getStreamId()];
            streamNames[i] = prototype.getParametersNames().get(i);
            streamsIdsPerStream[i] = und.getStreamId();

            if (und.getStreamId() != i) {
                allStreamIdsMatch = false;
            }
        }

        StreamTypeService streamTypeService = validationContext.getStreamTypeService();
        StreamTypeServiceImpl copyTypes = new StreamTypeServiceImpl(eventTypes, streamNames, isIStreamOnly, streamTypeService.getEngineURIQualifier(), streamTypeService.isOnDemandStreams());
        copyTypes.setRequireStreamNames(true);

        // validate expression body in this context
        try {
            ExprValidationContext expressionBodyContext = new ExprValidationContext(copyTypes, validationContext);
            expressionBodyCopy = ExprNodeUtil.getValidatedSubtree(expressionBodyCopy, expressionBodyContext);
        }
        catch (ExprValidationException ex) {
            String message = "Error validating expression declaration '" + prototype.getName() + "': " + ex.getMessage();
            throw new ExprValidationException(message, ex);
        }

        // add child node
        this.addChildNode(expressionBodyCopy);

        // analyze child node
        ExprNodeSummaryVisitor summaryVisitor = new ExprNodeSummaryVisitor();
        expressionBodyCopy.accept(summaryVisitor);
        boolean isCache;
        if (summaryVisitor.isHasAggregation() || summaryVisitor.isHasPreviousPrior()) {
            isCache = false;
        }
        else {
            isCache = true;
        }

        // determine a suitable evaluation
        if (expressionBodyCopy.isConstantResult()) {
            // pre-evaluated
            exprEvaluator = new ExprDeclaredEvalConstant(expressionBodyCopy.getExprEvaluator().getType(), expressionBodyCopy.getExprEvaluator().evaluate(null, true, null));
        }
        else if (prototype.getParametersNames().isEmpty() ||
                (allStreamIdsMatch && prototype.getParametersNames().size() == streamTypeService.getEventTypes().length)) {
            exprEvaluator = new ExprDeclaredEvalNoRewrite(expressionBodyCopy.getExprEvaluator(), prototype, isCache);
        }
        else {
            exprEvaluator = new ExprDeclaredEvalRewrite(expressionBodyCopy.getExprEvaluator(), prototype, isCache, streamsIdsPerStream);
        }

        Audit audit = AuditEnum.EXPRDEF.getAudit(validationContext.getAnnotations());
        if (audit != null) {
            exprEvaluator = (ExprEvaluator) ExprEvaluatorProxy.newInstance(validationContext.getStatementName(), prototype.getName(), exprEvaluator);
        }
    }

    public boolean isConstantResult()
    {
        return false;
    }

    public boolean equalsNode(ExprNode node)
    {
        if (!(node instanceof ExprDeclaredNodeImpl))
        {
            return false;
        }

        ExprDeclaredNodeImpl otherExprCaseNode = (ExprDeclaredNodeImpl) node;
        return expressionBodyCopy.equalsNode(otherExprCaseNode.getExpressionBodyCopy());
    }

    public void accept(ExprNodeVisitor visitor) {
        super.accept(visitor);
        if (this.getChildNodes().isEmpty()) {
            expressionBodyCopy.accept(visitor);
        }
    }

    public void accept(ExprNodeVisitorWithParent visitor) {
        super.accept(visitor);
        if (this.getChildNodes().isEmpty()) {
            expressionBodyCopy.accept(visitor);
        }
    }

    public void acceptChildnodes(ExprNodeVisitorWithParent visitor, ExprNode parent) {
        super.acceptChildnodes(visitor, parent);
        if (this.getChildNodes().isEmpty()) {
            expressionBodyCopy.accept(visitor);
        }
    }

    public ExprNode getExpressionBodyCopy() {
        return expressionBodyCopy;
    }

    public ExpressionDeclItem getPrototype() {
        return prototype;
    }

    public List<ExprNode> getChainParameters() {
        return chainParameters;
    }

    public ExprEvaluator getExprEvaluator() {
        return exprEvaluator;
    }

    private void checkParameterCount() throws ExprValidationException {
        if (chainParameters.size() != prototype.getParametersNames().size()) {
            throw new ExprValidationException("Parameter count mismatches for declared expression '" + prototype.getName() + "', expected " +
                prototype.getParametersNames().size() + " parameters but received " + chainParameters.size() + " parameters");
        }
    }

    public String toExpressionString()
    {
        StringBuffer buf = new StringBuffer();
        buf.append(prototype.getName() + "(");
        String delimiter = "";
        for (ExprNode parameter : chainParameters) {
            buf.append(delimiter);
            buf.append(parameter.toExpressionString());
            delimiter = ", ";
        }
        buf.append(")");
        return buf.toString();
    }
}
TOP

Related Classes of com.espertech.esper.epl.declexpr.ExprDeclaredNodeImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.