com.espertech.esper.epl.script.ExprNodeScript Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of esper Show documentation
Show all versions of esper Show documentation
Complex event processing and event series analysis component
/*
***************************************************************************************
* 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.script;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.client.hook.EPLScriptContext;
import com.espertech.esper.epl.core.EngineImportException;
import com.espertech.esper.epl.core.EngineImportService;
import com.espertech.esper.epl.expression.core.*;
import com.espertech.esper.epl.script.jsr223.ExpressionScriptCompiledJSR223;
import com.espertech.esper.epl.script.jsr223.JSR223Helper;
import com.espertech.esper.epl.script.mvel.ExpressionScriptCompiledMVEL;
import com.espertech.esper.epl.script.mvel.MVELHelper;
import com.espertech.esper.epl.spec.ExpressionScriptCompiled;
import com.espertech.esper.epl.spec.ExpressionScriptProvided;
import com.espertech.esper.event.EventTypeUtility;
import com.espertech.esper.util.JavaClassHelper;
import javax.script.CompiledScript;
import java.io.StringWriter;
import java.util.*;
public class ExprNodeScript extends ExprNodeBase implements ExprNodeInnerNodeProvider {
private static final long serialVersionUID = 2661218104424440161L;
public static final String CONTEXT_BINDING_NAME = "epl";
private final String defaultDialect;
private final ExpressionScriptProvided script;
private final List parameters;
private transient ExprNodeScriptEvaluator evaluator;
public ExprNodeScript(String defaultDialect, ExpressionScriptProvided script, List parameters) {
this.defaultDialect = defaultDialect;
this.script = script;
this.parameters = parameters;
}
public List getAdditionalNodes() {
return parameters;
}
public ExprNodeScriptEvaluator getExprEvaluator() {
return evaluator;
}
public List getParameters() {
return parameters;
}
public String getEventTypeNameAnnotation() {
return script.getOptionalEventTypeName();
}
public void toPrecedenceFreeEPL(StringWriter writer) {
writer.append(script.getName());
ExprNodeUtility.toExpressionStringIncludeParen(parameters, writer);
}
public ExprPrecedenceEnum getPrecedence() {
return ExprPrecedenceEnum.UNARY;
}
public ExpressionScriptProvided getScript() {
return script;
}
public boolean isConstantResult() {
return false;
}
public boolean equalsNode(ExprNode node, boolean ignoreStreamPrefix) {
if (this == node) return true;
if (node == null || getClass() != node.getClass()) return false;
ExprNodeScript that = (ExprNodeScript) node;
if (script != null ? !script.equals(that.script) : that.script != null) return false;
return ExprNodeUtility.deepEquals(parameters, that.parameters);
}
public ExprNode validate(ExprValidationContext validationContext) throws ExprValidationException {
if (evaluator != null) {
return null;
}
if (script.getParameterNames().size() != parameters.size()) {
throw new ExprValidationException("Invalid number of parameters for script '" + script.getName() + "', expected " + script.getParameterNames().size() + " parameters but received " + parameters.size() + " parameters");
}
// validate all expression parameters
List validatedParameters = new ArrayList();
for (ExprNode expr : parameters) {
validatedParameters.add(ExprNodeUtility.getValidatedSubtree(ExprNodeOrigin.SCRIPTPARAMS, expr, validationContext));
}
// set up map of input parameter names and evaluators
String[] inputParamNames = new String[script.getParameterNames().size()];
ExprEvaluator[] evaluators = new ExprEvaluator[script.getParameterNames().size()];
for (int i = 0; i < script.getParameterNames().size(); i++) {
inputParamNames[i] = script.getParameterNames().get(i);
evaluators[i] = validatedParameters.get(i).getExprEvaluator();
}
// Compile script
if (script.getCompiled() == null) {
compileScript(evaluators, validationContext.getEngineImportService());
}
// Determine declared return type
Class declaredReturnType = getDeclaredReturnType(script.getOptionalReturnTypeName(), validationContext);
if (script.isOptionalReturnTypeIsArray() && declaredReturnType != null) {
declaredReturnType = JavaClassHelper.getArrayType(declaredReturnType);
}
Class returnType;
if (script.getCompiled().getKnownReturnType() == null && script.getOptionalReturnTypeName() == null) {
returnType = Object.class;
} else if (script.getCompiled().getKnownReturnType() != null) {
if (declaredReturnType == null) {
returnType = script.getCompiled().getKnownReturnType();
} else {
Class knownReturnType = script.getCompiled().getKnownReturnType();
if (declaredReturnType.isArray() && knownReturnType.isArray()) {
// we are fine
} else if (!JavaClassHelper.isAssignmentCompatible(knownReturnType, declaredReturnType)) {
throw new ExprValidationException("Return type and declared type not compatible for script '" + script.getName() + "', known return type is " + knownReturnType.getName() + " versus declared return type " + declaredReturnType.getName());
}
returnType = declaredReturnType;
}
} else {
returnType = declaredReturnType;
}
if (returnType == null) {
returnType = Object.class;
}
EventType eventTypeCollection = null;
if (script.getOptionalEventTypeName() != null) {
if (returnType.isArray() && returnType.getComponentType() == EventBean.class) {
eventTypeCollection = EventTypeUtility.requireEventType("Script", script.getName(), validationContext.getEventAdapterService(), script.getOptionalEventTypeName());
} else {
throw new ExprValidationException(EventTypeUtility.disallowedAtTypeMessage());
}
}
// Prepare evaluator - this sets the evaluator
prepareEvaluator(validationContext.getStatementName(), inputParamNames, evaluators, returnType, eventTypeCollection);
return null;
}
private void compileScript(ExprEvaluator[] evaluators, EngineImportService engineImportService)
throws ExprValidationException {
String dialect = script.getOptionalDialect() == null ? defaultDialect : script.getOptionalDialect();
ExpressionScriptCompiled compiled;
if (dialect.toLowerCase(Locale.ENGLISH).trim().equals("mvel")) {
Map mvelInputParamTypes = new HashMap();
for (int i = 0; i < script.getParameterNames().size(); i++) {
String mvelParamName = script.getParameterNames().get(i);
mvelInputParamTypes.put(mvelParamName, evaluators[i].getType());
}
mvelInputParamTypes.put(CONTEXT_BINDING_NAME, EPLScriptContext.class);
compiled = MVELHelper.compile(script.getName(), script.getExpression(), mvelInputParamTypes, engineImportService);
} else {
CompiledScript compiledScript = JSR223Helper.verifyCompileScript(script, dialect);
compiled = new ExpressionScriptCompiledJSR223(compiledScript);
}
script.setCompiled(compiled);
}
private void prepareEvaluator(String statementName, String[] inputParamNames, ExprEvaluator[] evaluators, Class returnType, EventType eventTypeCollection) {
if (script.getCompiled() instanceof ExpressionScriptCompiledMVEL) {
ExpressionScriptCompiledMVEL mvel = (ExpressionScriptCompiledMVEL) script.getCompiled();
evaluator = new ExprNodeScriptEvalMVEL(script.getName(), statementName, inputParamNames, evaluators, returnType, eventTypeCollection, mvel.getCompiled());
} else {
ExpressionScriptCompiledJSR223 jsr223 = (ExpressionScriptCompiledJSR223) script.getCompiled();
evaluator = new ExprNodeScriptEvalJSR223(script.getName(), statementName, inputParamNames, evaluators, returnType, eventTypeCollection, jsr223.getCompiled());
}
}
private Class getDeclaredReturnType(String returnTypeName, ExprValidationContext validationContext)
throws ExprValidationException {
if (returnTypeName == null) {
return null;
}
if (returnTypeName.equals("void")) {
return null;
}
Class returnType = JavaClassHelper.getClassForSimpleName(returnTypeName, validationContext.getEngineImportService().getClassForNameProvider());
if (returnType != null) {
return returnType;
}
if (returnTypeName.equals("EventBean")) {
return EventBean.class;
}
try {
return validationContext.getEngineImportService().resolveClass(returnTypeName, false);
} catch (EngineImportException e1) {
throw new ExprValidationException("Failed to resolve return type '" + returnTypeName + "' specified for script '" + script.getName() + "'");
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy