/* *************************************************************************************** * 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.parse; import com.espertech.esper.client.ConfigurationPlugInAggregationMultiFunction; import com.espertech.esper.collection.Pair; import com.espertech.esper.epl.core.EngineImportService; import com.espertech.esper.epl.expression.baseagg.ExprAggregateNodeBase; import com.espertech.esper.epl.expression.core.ExprChainedSpec; import com.espertech.esper.epl.expression.core.ExprNode; import com.espertech.esper.epl.expression.dot.ExprDotNode; import com.espertech.esper.epl.expression.dot.ExprDotNodeImpl; import com.espertech.esper.epl.expression.table.*; import com.espertech.esper.epl.spec.StatementSpecRaw; import com.espertech.esper.epl.table.mgmt.TableMetadata; import com.espertech.esper.epl.table.mgmt.TableService; import com.espertech.esper.plugin.PlugInAggregationMultiFunctionFactory; import com.espertech.esper.util.LazyAllocatedMap; import java.util.*; public class ASTTableExprHelper { public static void addTableExpressionReference(StatementSpecRaw statementSpec, ExprTableAccessNode tableNode) { if (statementSpec.getTableExpressions() == null) { statementSpec.setTableExpressions(new HashSet<ExprTableAccessNode>()); } statementSpec.getTableExpressions().add(tableNode); } public static void addTableExpressionReference(StatementSpecRaw statementSpec, Set<ExprTableAccessNode> tableNodes) { if (tableNodes == null || tableNodes.isEmpty()) { return; } if (statementSpec.getTableExpressions() == null) { statementSpec.setTableExpressions(new HashSet<ExprTableAccessNode>()); } statementSpec.getTableExpressions().addAll(tableNodes); } public static Pair<ExprTableAccessNode, ExprDotNode> checkTableNameGetExprForSubproperty(TableService tableService, String tableName, String subproperty) { TableMetadata metadata = tableService.getTableMetadata(tableName); if (metadata == null) { return null; } int index = ASTUtil.unescapedIndexOfDot(subproperty); if (index == -1) { if (metadata.getKeyTypes().length > 0) { return null; } ExprTableAccessNodeSubprop tableNode = new ExprTableAccessNodeSubprop(tableName, subproperty); return new Pair<ExprTableAccessNode, ExprDotNode>(tableNode, null); } // we have a nested subproperty such as "tablename.subproperty.abc" List<ExprChainedSpec> chainedSpecs = new ArrayList<ExprChainedSpec>(1); chainedSpecs.add(new ExprChainedSpec(subproperty.substring(index + 1), Collections.<ExprNode>emptyList(), true)); ExprTableAccessNodeSubprop tableNode = new ExprTableAccessNodeSubprop(tableName, subproperty.substring(0, index)); ExprDotNode dotNode = new ExprDotNodeImpl(chainedSpecs, false, false); dotNode.addChildNode(tableNode); return new Pair<ExprTableAccessNode, ExprDotNode>(tableNode, dotNode); } /** * Resolve "table" and "table.property" when nested-property, not chainable * * @param tableService tables * @param propertyName property name * @return table access node */ public static ExprTableAccessNode checkTableNameGetExprForProperty(TableService tableService, String propertyName) { // handle "var_name" alone, without chained, like an simple event property int index = ASTUtil.unescapedIndexOfDot(propertyName); if (index == -1) { if (tableService.getTableMetadata(propertyName) != null) { return new ExprTableAccessNodeTopLevel(propertyName); } return null; } // handle "var_name.column", without chained, like a nested event property String tableName = ASTUtil.unescapeDot(propertyName.substring(0, index)); if (tableService.getTableMetadata(tableName) == null) { return null; } // it is a tables's subproperty String sub = propertyName.substring(index + 1, propertyName.length()); return new ExprTableAccessNodeSubprop(tableName, sub); } public static Pair<ExprTableAccessNode, List<ExprChainedSpec>> checkTableNameGetLibFunc( TableService tableService, EngineImportService engineImportService, LazyAllocatedMap<ConfigurationPlugInAggregationMultiFunction, PlugInAggregationMultiFunctionFactory> plugInAggregations, String engineURI, String classIdent, List<ExprChainedSpec> chain) { int index = ASTUtil.unescapedIndexOfDot(classIdent); // handle special case "table.keys()" function if (index == -1) { if (tableService.getTableMetadata(classIdent) == null) { return null; // not a table } String funcName = chain.get(1).getName(); if (funcName.toLowerCase(Locale.ENGLISH).equals("keys")) { List<ExprChainedSpec> subchain = chain.subList(2, chain.size()); ExprTableAccessNodeKeys node = new ExprTableAccessNodeKeys(classIdent); return new Pair<ExprTableAccessNode, List<ExprChainedSpec>>(node, subchain); } else { throw ASTWalkException.from("Invalid use of variable '" + classIdent + "', unrecognized use of function '" + funcName + "', expected 'keys()'"); } } // Handle "table.property" (without the variable[...] syntax since this is ungrouped use) String tableName = ASTUtil.unescapeDot(classIdent.substring(0, index)); if (tableService.getTableMetadata(tableName) == null) { return null; } // this is a table access expression String sub = classIdent.substring(index + 1, classIdent.length()); return handleTable(engineImportService, plugInAggregations, engineURI, tableName, sub, chain); } public static Pair<ExprTableAccessNode, List<ExprChainedSpec>> getTableExprChainable( EngineImportService engineImportService, LazyAllocatedMap<ConfigurationPlugInAggregationMultiFunction, PlugInAggregationMultiFunctionFactory> plugInAggregations, String engineURI, String tableName, List<ExprChainedSpec> chain) { // handle just "variable[...].sub" String subpropName = chain.get(0).getName(); if (chain.size() == 1) { chain.remove(0); ExprTableAccessNodeSubprop tableNode = new ExprTableAccessNodeSubprop(tableName, subpropName); return new Pair<ExprTableAccessNode, List<ExprChainedSpec>>(tableNode, chain); } // we have a chain "variable[...].sub.xyz" return handleTable(engineImportService, plugInAggregations, engineURI, tableName, subpropName, chain); } private static Pair<ExprTableAccessNode, List<ExprChainedSpec>> handleTable( EngineImportService engineImportService, LazyAllocatedMap<ConfigurationPlugInAggregationMultiFunction, PlugInAggregationMultiFunctionFactory> plugInAggregations, String engineURI, String tableName, String sub, List<ExprChainedSpec> chain) { ExprTableAccessNode node = new ExprTableAccessNodeSubprop(tableName, sub); List<ExprChainedSpec> subchain = chain.subList(1, chain.size()); String candidateAccessor = subchain.get(0).getName(); ExprAggregateNodeBase exprNode = (ExprAggregateNodeBase) ASTAggregationHelper.tryResolveAsAggregation(engineImportService, false, candidateAccessor, plugInAggregations, engineURI); if (exprNode != null) { node = new ExprTableAccessNodeSubpropAccessor(tableName, sub, exprNode); exprNode.addChildNodes(subchain.get(0).getParameters()); subchain.remove(0); } return new Pair<ExprTableAccessNode, List<ExprChainedSpec>>(node, subchain); } }