/* *************************************************************************************** * 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.util; import com.espertech.esper.client.EPException; import com.espertech.esper.client.EPServiceProvider; import com.espertech.esper.client.EPStatement; import com.espertech.esper.client.EventBean; import com.espertech.esper.client.annotation.*; import com.espertech.esper.collection.Pair; import com.espertech.esper.core.service.EPAdministratorSPI; import com.espertech.esper.core.service.EPServiceProviderSPI; import com.espertech.esper.core.support.SupportEventAdapterService; import com.espertech.esper.epl.core.StreamTypeService; import com.espertech.esper.epl.core.StreamTypeServiceImpl; import com.espertech.esper.epl.expression.core.*; import com.espertech.esper.event.bean.BeanEventType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.annotation.Annotation; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.function.BiConsumer; public class StatementSelectionUtil { private static Logger log = LoggerFactory.getLogger(StatementSelectionUtil.class); private static final BeanEventType STATEMENT_META_EVENT_TYPE; static { STATEMENT_META_EVENT_TYPE = (BeanEventType) SupportEventAdapterService.getService().addBeanType("StatementRow", StatementRow.class, true, true, true); } public static void applyExpressionToStatements(EPServiceProviderSPI engine, String filter, BiConsumer<EPServiceProvider, EPStatement> consumer) { // compile filter ExprNode filterExpr = null; boolean isUseFilter = false; if ((filter != null) && (filter.trim().length() != 0)) { isUseFilter = true; Pair<ExprNode, String> statementExprNode = compileValidateStatementFilterExpr(engine, filter); if (statementExprNode.getSecond() == null) { filterExpr = statementExprNode.getFirst(); } } String[] statementNames = engine.getEPAdministrator().getStatementNames(); for (String statementName : statementNames) { EPStatement epStmt = engine.getEPAdministrator().getStatement(statementName); if (epStmt == null) { continue; } if (isUseFilter) { if (filterExpr != null) { if (!evaluateStatement(filterExpr, epStmt)) { continue; } } else { boolean match = false; String searchString = filter.toLowerCase(Locale.ENGLISH); if ((epStmt.getName() != null) && (epStmt.getName().toLowerCase(Locale.ENGLISH).contains(searchString))) { match = true; } if (!match) { if ((epStmt.getText() != null) && (epStmt.getText().toLowerCase(Locale.ENGLISH).contains(searchString))) { match = true; } if ((epStmt.getState() != null) && (epStmt.getState().toString().toLowerCase(Locale.ENGLISH).contains(searchString))) { match = true; } } if (!match) { continue; } } } consumer.accept(engine, epStmt); } } public static boolean evaluateStatement(ExprNode expression, EPStatement stmt) { if (expression == null) { return true; } ExprEvaluator evaluator = expression.getExprEvaluator(); if (JavaClassHelper.getBoxedType(evaluator.getType()) != Boolean.class) { throw new EPException("Invalid expression, expected a boolean return type for expression and received '" + JavaClassHelper.getClassNameFullyQualPretty(evaluator.getType()) + "' for expression '" + ExprNodeUtility.toExpressionStringMinPrecedenceSafe(expression) + "'"); } try { StatementRow row = getRow(stmt); EventBean rowBean = SupportEventAdapterService.getService().adapterForTypedBean(row, STATEMENT_META_EVENT_TYPE); Boolean pass = (Boolean) evaluator.evaluate(new EventBean[]{rowBean}, true, null); return !((pass == null) || (!pass)); } catch (Exception ex) { log.error("Unexpected exception filtering statements by expression, skipping statement: " + ex.getMessage(), ex); } return false; } public static Pair<ExprNode, String> compileValidateStatementFilterExpr(EPServiceProviderSPI engine, String filterExpression) { ExprNode exprNode; try { EPAdministratorSPI spi = (EPAdministratorSPI) engine.getEPAdministrator(); exprNode = spi.compileExpression(filterExpression); } catch (Exception ex) { return new Pair<ExprNode, String>(null, "Error compiling expression: " + ex.getMessage()); } try { StreamTypeService streamTypeService = new StreamTypeServiceImpl(STATEMENT_META_EVENT_TYPE, null, true, engine.getURI()); exprNode = ExprNodeUtility.getValidatedSubtree(ExprNodeOrigin.SCRIPTPARAMS, exprNode, new ExprValidationContext(streamTypeService, engine.getEngineImportService(), null, null, engine.getTimeProvider(), null, null, null, engine.getEventAdapterService(), "no-name-assigned", -1, null, null, true, false, false, false, null, true)); } catch (Exception ex) { return new Pair<ExprNode, String>(null, "Error validating expression: " + ex.getMessage()); } return new Pair<ExprNode, String>(exprNode, null); } // Predefined properties available: // - name (string) // - description (string) // - epl (string) // - each tag individually (string) // - priority // - drop (boolean) // - hint (string) private static StatementRow getRow(EPStatement statement) { String description = null; String hint = null; String hintDelimiter = ""; int priority = 0; Map<String, String> tags = null; boolean drop = false; Annotation[] annotations = statement.getAnnotations(); for (Annotation anno : annotations) { if (anno instanceof Hint) { if (hint == null) { hint = ""; } hint += hintDelimiter + ((Hint) anno).value(); hintDelimiter = ","; } else if (anno instanceof Tag) { Tag tag = (Tag) anno; if (tags == null) { tags = new HashMap<String, String>(); } tags.put(tag.name(), tag.value()); } else if (anno instanceof Priority) { Priority tag = (Priority) anno; priority = tag.value(); } else if (anno instanceof Drop) { drop = true; } else if (anno instanceof Description) { description = ((Description) anno).value(); } } String name = statement.getName(); String text = statement.getText(); String state = statement.getState().toString(); Object userObject = statement.getUserObject(); return new StatementRow( name, text, state, userObject, description, hint, priority, drop, tags ); } public static class StatementRow { private String name; private String epl; private String state; private Object userObject; private String description; private String hint; private int priority; private Boolean drop; private Map<String, String> tag; public StatementRow(String name, String epl, String state, Object userObject, String description, String hint, int priority, Boolean drop, Map<String, String> tag) { this.name = name; this.epl = epl; this.state = state; this.userObject = userObject; this.description = description; this.hint = hint; this.priority = priority; this.drop = drop; this.tag = tag; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEpl() { return epl; } public void setEpl(String epl) { this.epl = epl; } public String getState() { return state; } public void setState(String state) { this.state = state; } public Object getUserObject() { return userObject; } public void setUserObject(Object userObject) { this.userObject = userObject; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getHint() { return hint; } public void setHint(String hint) { this.hint = hint; } public int getPriority() { return priority; } public void setPriority(int priority) { this.priority = priority; } public Boolean isDrop() { return drop; } public Boolean getDrop() { return drop; } public void setDrop(Boolean drop) { this.drop = drop; } public Map<String, String> getTag() { return tag; } public void setTag(Map<String, String> tag) { this.tag = tag; } } }