http://git-wip-us.apache.org/repos/asf/nifi/blob/5cd8e93b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java ---------------------------------------------------------------------- diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java index 4b1ce59..fe2c060 100644 --- a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java @@ -16,209 +16,21 @@ */ package org.apache.nifi.attribute.expression.language; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer; -import org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser; -import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.DateEvaluator; +import org.antlr.runtime.tree.Tree; +import org.apache.nifi.attribute.expression.language.compile.CompiledExpression; +import org.apache.nifi.attribute.expression.language.compile.ExpressionCompiler; import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; -import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.cast.BooleanCastEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.cast.DateCastEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.cast.DecimalCastEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.cast.NumberCastEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.cast.StringCastEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.cast.WholeNumberCastEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.AndEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.AppendEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.AttributeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ContainsEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.DivideEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.EndsWithEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.EqualsEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.EqualsIgnoreCaseEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.CharSequenceTranslatorEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.FindEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.FormatEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.FromRadixEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.GetDelimitedFieldEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.GetStateVariableEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.GreaterThanEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.GreaterThanOrEqualEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.HostnameEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.IPEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.IfElseEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.InEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.IndexOfEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.IsEmptyEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.IsNullEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.JsonPathEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.LastIndexOfEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.LengthEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.LessThanEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.LessThanOrEqualEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.MatchesEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.MathEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.MinusEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ModEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.MultiplyEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.NotEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.NotNullEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.NowEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.NumberToDateEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.OneUpSequenceEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.OrEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.PlusEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.PrependEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.RandomNumberGeneratorEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ReplaceAllEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ReplaceEmptyEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ReplaceEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ReplaceFirstEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ReplaceNullEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.StartsWithEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.StringToDateEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.SubstringAfterEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.SubstringAfterLastEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.SubstringBeforeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.SubstringBeforeLastEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.SubstringEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ToLowerEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ToRadixEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ToStringEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ToUpperEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.TrimEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.UrlDecodeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.UrlEncodeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.Base64DecodeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.Base64EncodeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.UuidEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.literals.BooleanLiteralEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.literals.DecimalLiteralEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.literals.StringLiteralEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.literals.ToLiteralEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.literals.WholeNumberLiteralEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.reduce.CountEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.reduce.JoinEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.reduce.ReduceEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.selection.AllAttributesEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.selection.AnyAttributeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.selection.DelineatedAttributeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.selection.IteratingEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.selection.MultiAttributeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.selection.MultiMatchAttributeEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.selection.MultiNamedAttributeEvaluator; -import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException; import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageParsingException; import org.apache.nifi.expression.AttributeExpression.ResultType; import org.apache.nifi.expression.AttributeValueDecorator; -import org.apache.nifi.flowfile.FlowFile; import org.apache.nifi.processor.exception.ProcessException; -import org.antlr.runtime.ANTLRStringStream; -import org.antlr.runtime.CharStream; -import org.antlr.runtime.CommonTokenStream; -import org.antlr.runtime.tree.Tree; - -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.FROM_RADIX; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.IF_ELSE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.MATH; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ALL_ATTRIBUTES; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ALL_DELINEATED_VALUES; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ALL_MATCHING_ATTRIBUTES; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.AND; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ANY_ATTRIBUTE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ANY_DELINEATED_VALUE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ANY_MATCHING_ATTRIBUTE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.APPEND; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ATTRIBUTE_REFERENCE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ATTR_NAME; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.CONTAINS; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.DECIMAL; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.IN; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.COUNT; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.DIVIDE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ENDS_WITH; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.EQUALS; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.EQUALS_IGNORE_CASE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.EXPRESSION; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.FALSE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.FIND; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.FORMAT; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.GET_DELIMITED_FIELD; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.GET_STATE_VALUE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.GREATER_THAN; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.GREATER_THAN_OR_EQUAL; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.HOSTNAME; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.INDEX_OF; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.IP; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.IS_EMPTY; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.IS_NULL; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.JOIN; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.JSON_PATH; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.LAST_INDEX_OF; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.LENGTH; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.LESS_THAN; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.LESS_THAN_OR_EQUAL; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.MATCHES; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.MINUS; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.MOD; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.MULTIPLY; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.MULTI_ATTRIBUTE_REFERENCE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.NEXT_INT; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.NOT; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.NOT_NULL; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.NOW; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_DECIMAL; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.WHOLE_NUMBER; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.OR; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.PLUS; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.PREPEND; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.REPLACE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.RANDOM; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.REPLACE_ALL; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.REPLACE_EMPTY; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.REPLACE_FIRST; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.REPLACE_NULL; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.STARTS_WITH; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.STRING_LITERAL; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.SUBSTRING; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.SUBSTRING_AFTER; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.SUBSTRING_AFTER_LAST; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.SUBSTRING_BEFORE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.SUBSTRING_BEFORE_LAST; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_DATE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_LITERAL; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_LOWER; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_NUMBER; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_RADIX; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_STRING; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_UPPER; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TRIM; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TRUE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.URL_DECODE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.URL_ENCODE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.BASE64_DECODE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.BASE64_ENCODE; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ESCAPE_JSON; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ESCAPE_CSV; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ESCAPE_HTML3; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ESCAPE_HTML4; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ESCAPE_XML; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UNESCAPE_JSON; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UNESCAPE_CSV; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UNESCAPE_HTML3; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UNESCAPE_HTML4; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UNESCAPE_XML; -import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.UUID; - -import org.apache.nifi.attribute.expression.language.evaluation.selection.MappingEvaluator; /** * Class used for creating and evaluating NiFi Expression Language. Once a Query @@ -413,18 +225,6 @@ public class Query { return Query.prepare(rawValue).evaluateExpressions(valueLookup, decorator); } - private static Evaluator<?> getRootSubjectEvaluator(final Evaluator<?> evaluator) { - if (evaluator == null) { - return null; - } - - final Evaluator<?> subject = evaluator.getSubjectEvaluator(); - if (subject == null) { - return evaluator; - } - - return getRootSubjectEvaluator(subject); - } /** * Un-escapes ${...} patterns that were escaped @@ -436,28 +236,11 @@ public class Query { return value.replaceAll("\\$\\$(?=\\$*\\{.*?\\})", "\\$"); } - public static Query fromTree(final Tree tree, final String text) { - return new Query(text, tree, buildEvaluator(tree)); + final ExpressionCompiler compiler = new ExpressionCompiler(); + return new Query(text, tree, compiler.buildEvaluator(tree)); } - public static Tree compileTree(final String query) throws AttributeExpressionLanguageParsingException { - try { - final CommonTokenStream lexerTokenStream = createTokenStream(query); - final AttributeExpressionParser parser = new AttributeExpressionParser(lexerTokenStream); - final Tree ast = (Tree) parser.query().getTree(); - final Tree tree = ast.getChild(0); - - // ensure that we are able to build the evaluators, so that we validate syntax - final Evaluator<?> evaluator = buildEvaluator(tree); - verifyMappingEvaluatorReduced(evaluator); - return tree; - } catch (final AttributeExpressionLanguageParsingException e) { - throw e; - } catch (final Exception e) { - throw new AttributeExpressionLanguageParsingException(e); - } - } public static PreparedQuery prepare(final String query) throws AttributeExpressionLanguageParsingException { if (query == null) { @@ -470,9 +253,11 @@ public class Query { return new EmptyPreparedQuery(query.replace("$$", "$")); } + final ExpressionCompiler compiler = new ExpressionCompiler(); + try { final List<String> substrings = new ArrayList<>(); - final Map<String, Tree> trees = new HashMap<>(); + final Map<String, CompiledExpression> compiledExpressions = new HashMap<>(); int lastIndex = 0; for (final Range range : ranges) { @@ -483,7 +268,10 @@ public class Query { final String treeText = query.substring(range.getStart(), range.getEnd() + 1).replace("$$", "$"); substrings.add(treeText); - trees.put(treeText, Query.compileTree(treeText)); + + final CompiledExpression compiledExpression = compiler.compile(treeText); + + compiledExpressions.put(treeText, compiledExpression); lastIndex = range.getEnd() + 1; } @@ -493,7 +281,7 @@ public class Query { substrings.add(treeText); } - return new StandardPreparedQuery(substrings, trees); + return new StandardPreparedQuery(substrings, compiledExpressions); } catch (final AttributeExpressionLanguageParsingException e) { return new InvalidPreparedQuery(query, e.getMessage()); } @@ -501,15 +289,10 @@ public class Query { public static Query compile(final String query) throws AttributeExpressionLanguageParsingException { try { - final CommonTokenStream lexerTokenStream = createTokenStream(query); - final AttributeExpressionParser parser = new AttributeExpressionParser(lexerTokenStream); - final Tree ast = (Tree) parser.query().getTree(); - final Tree tree = ast.getChild(0); + final ExpressionCompiler compiler = new ExpressionCompiler(); + final CompiledExpression compiledExpression = compiler.compile(query); - final Evaluator<?> evaluator = buildEvaluator(tree); - verifyMappingEvaluatorReduced(evaluator); - - return new Query(query, tree, evaluator); + return new Query(compiledExpression.getExpression(), compiledExpression.getTree(), compiledExpression.getRootEvaluator()); } catch (final AttributeExpressionLanguageParsingException e) { throw e; } catch (final Exception e) { @@ -517,57 +300,6 @@ public class Query { } } - private static void verifyMappingEvaluatorReduced(final Evaluator<?> evaluator) { - final Evaluator<?> rightMostEvaluator; - if (evaluator instanceof IteratingEvaluator) { - rightMostEvaluator = ((IteratingEvaluator<?>) evaluator).getLogicEvaluator(); - } else { - rightMostEvaluator = evaluator; - } - - Evaluator<?> eval = rightMostEvaluator.getSubjectEvaluator(); - Evaluator<?> lastEval = rightMostEvaluator; - while (eval != null) { - if (eval instanceof ReduceEvaluator) { - throw new AttributeExpressionLanguageParsingException("Expression attempts to call function '" + lastEval.getToken() + "' on the result of '" + eval.getToken() + - "'. This is not allowed. Instead, use \"${literal( ${<embedded expression>} ):" + lastEval.getToken() + "(...)}\""); - } - - lastEval = eval; - eval = eval.getSubjectEvaluator(); - } - - // if the result type of the evaluator is BOOLEAN, then it will always - // be reduced when evaluator. - final ResultType resultType = evaluator.getResultType(); - if (resultType == ResultType.BOOLEAN) { - return; - } - - final Evaluator<?> rootEvaluator = getRootSubjectEvaluator(evaluator); - if (rootEvaluator != null && rootEvaluator instanceof MultiAttributeEvaluator) { - final MultiAttributeEvaluator multiAttrEval = (MultiAttributeEvaluator) rootEvaluator; - switch (multiAttrEval.getEvaluationType()) { - case ALL_ATTRIBUTES: - case ALL_MATCHING_ATTRIBUTES: - case ALL_DELINEATED_VALUES: { - if (!(evaluator instanceof ReduceEvaluator)) { - throw new AttributeExpressionLanguageParsingException("Cannot evaluate expression because it attempts to reference multiple attributes but does not use a reducing function"); - } - break; - } - default: - throw new AttributeExpressionLanguageParsingException("Cannot evaluate expression because it attempts to reference multiple attributes but does not use a reducing function"); - } - } - } - - private static CommonTokenStream createTokenStream(final String expression) throws AttributeExpressionLanguageParsingException { - final CharStream input = new ANTLRStringStream(expression); - final AttributeExpressionLexer lexer = new AttributeExpressionLexer(input); - return new CommonTokenStream(lexer); - } - public ResultType getResultType() { return evaluator.getResultType(); } @@ -598,789 +330,7 @@ public class Query { return "Query [" + query + "]"; } - private static Evaluator<String> newStringLiteralEvaluator(final String literalValue) { - if (literalValue == null || literalValue.length() < 2) { - return new StringLiteralEvaluator(literalValue); - } - - final List<Range> ranges = extractExpressionRanges(literalValue); - if (ranges.isEmpty()) { - return new StringLiteralEvaluator(literalValue); - } - - final List<Evaluator<?>> evaluators = new ArrayList<>(); - - int lastIndex = 0; - for (final Range range : ranges) { - if (range.getStart() > lastIndex) { - evaluators.add(newStringLiteralEvaluator(literalValue.substring(lastIndex, range.getStart()))); - } - - final String treeText = literalValue.substring(range.getStart(), range.getEnd() + 1); - evaluators.add(buildEvaluator(compileTree(treeText))); - lastIndex = range.getEnd() + 1; - } - - final Range lastRange = ranges.get(ranges.size() - 1); - if (lastRange.getEnd() + 1 < literalValue.length()) { - final String treeText = literalValue.substring(lastRange.getEnd() + 1); - evaluators.add(newStringLiteralEvaluator(treeText)); - } - - if (evaluators.size() == 1) { - return toStringEvaluator(evaluators.get(0)); - } - - Evaluator<String> lastEvaluator = toStringEvaluator(evaluators.get(0)); - for (int i = 1; i < evaluators.size(); i++) { - lastEvaluator = new AppendEvaluator(lastEvaluator, toStringEvaluator(evaluators.get(i))); - } - - return lastEvaluator; - } - - private static Evaluator<?> buildEvaluator(final Tree tree) { - switch (tree.getType()) { - case EXPRESSION: { - return buildExpressionEvaluator(tree); - } - case ATTRIBUTE_REFERENCE: { - final Evaluator<?> childEvaluator = buildEvaluator(tree.getChild(0)); - if (childEvaluator instanceof MultiAttributeEvaluator) { - return childEvaluator; - } - return new AttributeEvaluator(toStringEvaluator(childEvaluator)); - } - case MULTI_ATTRIBUTE_REFERENCE: { - - final Tree functionTypeTree = tree.getChild(0); - final int multiAttrType = functionTypeTree.getType(); - if (multiAttrType == ANY_DELINEATED_VALUE || multiAttrType == ALL_DELINEATED_VALUES) { - final Evaluator<String> delineatedValueEvaluator = toStringEvaluator(buildEvaluator(tree.getChild(1))); - final Evaluator<String> delimiterEvaluator = toStringEvaluator(buildEvaluator(tree.getChild(2))); - - return new DelineatedAttributeEvaluator(delineatedValueEvaluator, delimiterEvaluator, multiAttrType); - } - - final List<String> attributeNames = new ArrayList<>(); - for (int i = 1; i < tree.getChildCount(); i++) { // skip the first child because that's the name of the multi-attribute function - attributeNames.add(newStringLiteralEvaluator(tree.getChild(i).getText()).evaluate(null).getValue()); - } - - switch (multiAttrType) { - case ALL_ATTRIBUTES: - for (final String attributeName : attributeNames) { - try { - FlowFile.KeyValidator.validateKey(attributeName); - } catch (final IllegalArgumentException iae) { - throw new AttributeExpressionLanguageParsingException("Invalid Attribute Name: " + attributeName + ". " + iae.getMessage()); - } - } - - return new MultiNamedAttributeEvaluator(attributeNames, ALL_ATTRIBUTES); - case ALL_MATCHING_ATTRIBUTES: - return new MultiMatchAttributeEvaluator(attributeNames, ALL_MATCHING_ATTRIBUTES); - case ANY_ATTRIBUTE: - for (final String attributeName : attributeNames) { - try { - FlowFile.KeyValidator.validateKey(attributeName); - } catch (final IllegalArgumentException iae) { - throw new AttributeExpressionLanguageParsingException("Invalid Attribute Name: " + attributeName + ". " + iae.getMessage()); - } - } - - return new MultiNamedAttributeEvaluator(attributeNames, ANY_ATTRIBUTE); - case ANY_MATCHING_ATTRIBUTE: - return new MultiMatchAttributeEvaluator(attributeNames, ANY_MATCHING_ATTRIBUTE); - default: - throw new AssertionError("Illegal Multi-Attribute Reference: " + functionTypeTree.toString()); - } - } - case ATTR_NAME: { - return newStringLiteralEvaluator(tree.getChild(0).getText()); - } - case WHOLE_NUMBER: { - return new WholeNumberLiteralEvaluator(tree.getText()); - } - case STRING_LITERAL: { - return newStringLiteralEvaluator(tree.getText()); - } - case DECIMAL: { - return new DecimalLiteralEvaluator(tree.getText()); - } - case TRUE: - case FALSE: - return buildBooleanEvaluator(tree); - case UUID: { - return new UuidEvaluator(); - } - case NOW: { - return new NowEvaluator(); - } - case TO_LITERAL: { - final Evaluator<?> argEvaluator = buildEvaluator(tree.getChild(0)); - return new ToLiteralEvaluator(argEvaluator); - } - case IP: { - try { - return new IPEvaluator(); - } catch (final UnknownHostException e) { - throw new AttributeExpressionLanguageException(e); - } - } - case HOSTNAME: { - if (tree.getChildCount() == 0) { - try { - return new HostnameEvaluator(false); - } catch (final UnknownHostException e) { - throw new AttributeExpressionLanguageException(e); - } - } else if (tree.getChildCount() == 1) { - final Tree childTree = tree.getChild(0); - try { - switch (childTree.getType()) { - case TRUE: - return new HostnameEvaluator(true); - case FALSE: - return new HostnameEvaluator(false); - default: - throw new AttributeExpressionLanguageParsingException("Call to hostname() must take 0 or 1 (boolean) parameter"); - } - } catch (final UnknownHostException e) { - throw new AttributeExpressionLanguageException(e); - } - } else { - throw new AttributeExpressionLanguageParsingException("Call to hostname() must take 0 or 1 (boolean) parameter"); - } - } - case NEXT_INT: { - return new OneUpSequenceEvaluator(); - } - case RANDOM: { - return new RandomNumberGeneratorEvaluator(); - } - case MATH: { - if (tree.getChildCount() == 1) { - return addToken(new MathEvaluator(null, toStringEvaluator(buildEvaluator(tree.getChild(0))), null), "math"); - } else { - throw new AttributeExpressionLanguageParsingException("Call to math() as the subject must take exactly 1 parameter"); - } - } - case GET_STATE_VALUE: { - final Tree childTree = tree.getChild(0); - final Evaluator<?> argEvaluator = buildEvaluator(childTree); - final Evaluator<String> stringEvaluator = toStringEvaluator(argEvaluator); - return new GetStateVariableEvaluator(stringEvaluator); - } - default: - throw new AttributeExpressionLanguageParsingException("Unexpected token: " + tree.toString()); - } - } - - private static <T> Evaluator<T> addToken(final Evaluator<T> evaluator, final String token) { - evaluator.setToken(token); - return evaluator; - } - - private static Evaluator<Boolean> buildBooleanEvaluator(final Tree tree) { - switch (tree.getType()) { - case TRUE: - return addToken(new BooleanLiteralEvaluator(true), "true"); - case FALSE: - return addToken(new BooleanLiteralEvaluator(false), "true"); - } - throw new AttributeExpressionLanguageParsingException("Cannot build Boolean evaluator from tree " + tree.toString()); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - private static Evaluator<?> buildExpressionEvaluator(final Tree tree) { - if (tree.getChildCount() == 0) { - throw new AttributeExpressionLanguageParsingException("EXPRESSION tree node has no children"); - } - - final Evaluator<?> evaluator; - if (tree.getChildCount() == 1) { - evaluator = buildEvaluator(tree.getChild(0)); - } else { - // we can chain together functions in the form of: - // ${x:trim():substring(1,2):trim()} - // in this case, the subject of the right-most function is the function to its left; its - // subject is the function to its left (the first trim()), and its subject is the value of - // the 'x' attribute. We accomplish this logic by iterating over all of the children of the - // tree from the right-most child going left-ward. - evaluator = buildFunctionExpressionEvaluator(tree, 0); - } - - Evaluator<?> chosenEvaluator = evaluator; - final Evaluator<?> rootEvaluator = getRootSubjectEvaluator(evaluator); - if (rootEvaluator != null) { - if (rootEvaluator instanceof MultiAttributeEvaluator) { - final MultiAttributeEvaluator multiAttrEval = (MultiAttributeEvaluator) rootEvaluator; - - switch (multiAttrEval.getEvaluationType()) { - case ANY_ATTRIBUTE: - case ANY_MATCHING_ATTRIBUTE: - case ANY_DELINEATED_VALUE: - chosenEvaluator = new AnyAttributeEvaluator((BooleanEvaluator) evaluator, multiAttrEval); - break; - case ALL_ATTRIBUTES: - case ALL_MATCHING_ATTRIBUTES: - case ALL_DELINEATED_VALUES: { - final ResultType resultType = evaluator.getResultType(); - if (resultType == ResultType.BOOLEAN) { - chosenEvaluator = new AllAttributesEvaluator((BooleanEvaluator) evaluator, multiAttrEval); - } else if (evaluator instanceof ReduceEvaluator) { - chosenEvaluator = new MappingEvaluator((ReduceEvaluator) evaluator, multiAttrEval); - } else { - throw new AttributeExpressionLanguageException("Cannot evaluate Expression because it attempts to reference multiple attributes but does not use a reducing function"); - } - break; - } - } - - switch (multiAttrEval.getEvaluationType()) { - case ANY_ATTRIBUTE: - chosenEvaluator.setToken("anyAttribute"); - break; - case ANY_MATCHING_ATTRIBUTE: - chosenEvaluator.setToken("anyMatchingAttribute"); - break; - case ANY_DELINEATED_VALUE: - chosenEvaluator.setToken("anyDelineatedValue"); - break; - case ALL_ATTRIBUTES: - chosenEvaluator.setToken("allAttributes"); - break; - case ALL_MATCHING_ATTRIBUTES: - chosenEvaluator.setToken("allMatchingAttributes"); - break; - case ALL_DELINEATED_VALUES: - chosenEvaluator.setToken("allDelineatedValues"); - break; - } - } - } - - return chosenEvaluator; - } - - private static Evaluator<?> buildFunctionExpressionEvaluator(final Tree tree, final int offset) { - if (tree.getChildCount() == 0) { - throw new AttributeExpressionLanguageParsingException("EXPRESSION tree node has no children"); - } - final int firstChildIndex = tree.getChildCount() - offset - 1; - if (firstChildIndex == 0) { - return buildEvaluator(tree.getChild(0)); - } - final Tree functionTree = tree.getChild(firstChildIndex); - final Evaluator<?> subjectEvaluator = buildFunctionExpressionEvaluator(tree, offset + 1); - - final Tree functionNameTree = functionTree.getChild(0); - final List<Evaluator<?>> argEvaluators = new ArrayList<>(); - for (int i = 1; i < functionTree.getChildCount(); i++) { - argEvaluators.add(buildEvaluator(functionTree.getChild(i))); - } - return buildFunctionEvaluator(functionNameTree, subjectEvaluator, argEvaluators); - } - - private static List<Evaluator<?>> verifyArgCount(final List<Evaluator<?>> args, final int count, final String functionName) { - if (args.size() != count) { - throw new AttributeExpressionLanguageParsingException(functionName + "() function takes " + count + " arguments"); - } - return args; - } - - private static Evaluator<String> toStringEvaluator(final Evaluator<?> evaluator) { - return toStringEvaluator(evaluator, null); - } - - private static Evaluator<String> toStringEvaluator(final Evaluator<?> evaluator, final String location) { - if (evaluator.getResultType() == ResultType.STRING) { - return (StringEvaluator) evaluator; - } - - return addToken(new StringCastEvaluator(evaluator), evaluator.getToken()); - } - - @SuppressWarnings("unchecked") - private static Evaluator<Boolean> toBooleanEvaluator(final Evaluator<?> evaluator, final String location) { - switch (evaluator.getResultType()) { - case BOOLEAN: - return (Evaluator<Boolean>) evaluator; - case STRING: - return addToken(new BooleanCastEvaluator((StringEvaluator) evaluator), evaluator.getToken()); - default: - throw new AttributeExpressionLanguageParsingException("Cannot implicitly convert Data Type " + evaluator.getResultType() + " to " + ResultType.BOOLEAN - + (location == null ? "" : " at location [" + location + "]")); - } - - } - - private static Evaluator<Boolean> toBooleanEvaluator(final Evaluator<?> evaluator) { - return toBooleanEvaluator(evaluator, null); - } - - private static Evaluator<Long> toWholeNumberEvaluator(final Evaluator<?> evaluator) { - return toWholeNumberEvaluator(evaluator, null); - } - - @SuppressWarnings("unchecked") - private static Evaluator<Long> toWholeNumberEvaluator(final Evaluator<?> evaluator, final String location) { - switch (evaluator.getResultType()) { - case WHOLE_NUMBER: - return (Evaluator<Long>) evaluator; - case STRING: - case DATE: - case DECIMAL: - case NUMBER: - return addToken(new WholeNumberCastEvaluator(evaluator), evaluator.getToken()); - default: - throw new AttributeExpressionLanguageParsingException("Cannot implicitly convert Data Type " + evaluator.getResultType() + " to " + ResultType.WHOLE_NUMBER - + (location == null ? "" : " at location [" + location + "]")); - } - } - - private static Evaluator<Double> toDecimalEvaluator(final Evaluator<?> evaluator) { - return toDecimalEvaluator(evaluator, null); - } - - @SuppressWarnings("unchecked") - private static Evaluator<Double> toDecimalEvaluator(final Evaluator<?> evaluator, final String location) { - switch (evaluator.getResultType()) { - case DECIMAL: - return (Evaluator<Double>) evaluator; - case WHOLE_NUMBER: - case STRING: - case DATE: - case NUMBER: - return addToken(new DecimalCastEvaluator(evaluator), evaluator.getToken()); - default: - throw new AttributeExpressionLanguageParsingException("Cannot implicitly convert Data Type " + evaluator.getResultType() + " to " + ResultType.DECIMAL - + (location == null ? "" : " at location [" + location + "]")); - } - } - - private static Evaluator<Number> toNumberEvaluator(final Evaluator<?> evaluator) { - return toNumberEvaluator(evaluator, null); - } - - @SuppressWarnings("unchecked") - private static Evaluator<Number> toNumberEvaluator(final Evaluator<?> evaluator, final String location) { - switch (evaluator.getResultType()) { - case NUMBER: - return (Evaluator<Number>) evaluator; - case STRING: - case DATE: - case DECIMAL: - case WHOLE_NUMBER: - return addToken(new NumberCastEvaluator(evaluator), evaluator.getToken()); - default: - throw new AttributeExpressionLanguageParsingException("Cannot implicitly convert Data Type " + evaluator.getResultType() + " to " + ResultType.WHOLE_NUMBER - + (location == null ? "" : " at location [" + location + "]")); - } - } - - private static DateEvaluator toDateEvaluator(final Evaluator<?> evaluator) { - return toDateEvaluator(evaluator, null); - } - - private static DateEvaluator toDateEvaluator(final Evaluator<?> evaluator, final String location) { - if (evaluator.getResultType() == ResultType.DATE) { - return (DateEvaluator) evaluator; - } - - return new DateCastEvaluator(evaluator); - } - - private static Evaluator<?> buildFunctionEvaluator(final Tree tree, final Evaluator<?> subjectEvaluator, final List<Evaluator<?>> argEvaluators) { - switch (tree.getType()) { - case TRIM: { - verifyArgCount(argEvaluators, 0, "trim"); - return addToken(new TrimEvaluator(toStringEvaluator(subjectEvaluator)), "trim"); - } - case TO_STRING: { - verifyArgCount(argEvaluators, 0, "toString"); - return addToken(new ToStringEvaluator(subjectEvaluator), "toString"); - } - case TO_LOWER: { - verifyArgCount(argEvaluators, 0, "toLower"); - return addToken(new ToLowerEvaluator(toStringEvaluator(subjectEvaluator)), "toLower"); - } - case TO_UPPER: { - verifyArgCount(argEvaluators, 0, "toUpper"); - return addToken(new ToUpperEvaluator(toStringEvaluator(subjectEvaluator)), "toUpper"); - } - case URL_ENCODE: { - verifyArgCount(argEvaluators, 0, "urlEncode"); - return addToken(new UrlEncodeEvaluator(toStringEvaluator(subjectEvaluator)), "urlEncode"); - } - case URL_DECODE: { - verifyArgCount(argEvaluators, 0, "urlDecode"); - return addToken(new UrlDecodeEvaluator(toStringEvaluator(subjectEvaluator)), "urlDecode"); - } - case BASE64_ENCODE: { - verifyArgCount(argEvaluators, 0, "base64Encode"); - return addToken(new Base64EncodeEvaluator(toStringEvaluator(subjectEvaluator)), "base64Encode"); - } - case BASE64_DECODE: { - verifyArgCount(argEvaluators, 0, "base64Decode"); - return addToken(new Base64DecodeEvaluator(toStringEvaluator(subjectEvaluator)), "base64Decode"); - } - case ESCAPE_CSV: { - verifyArgCount(argEvaluators, 0, "escapeCsv"); - return addToken(CharSequenceTranslatorEvaluator.csvEscapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); - } - case ESCAPE_HTML3: { - verifyArgCount(argEvaluators, 0, "escapeHtml3"); - return addToken(CharSequenceTranslatorEvaluator.html3EscapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); - } - case ESCAPE_HTML4: { - verifyArgCount(argEvaluators, 0, "escapeHtml4"); - return addToken(CharSequenceTranslatorEvaluator.html4EscapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); - } - case ESCAPE_JSON: { - verifyArgCount(argEvaluators, 0, "escapeJson"); - return addToken(CharSequenceTranslatorEvaluator.jsonEscapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); - } - case ESCAPE_XML: { - verifyArgCount(argEvaluators, 0, "escapeXml"); - return addToken(CharSequenceTranslatorEvaluator.xmlEscapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); - } - case UNESCAPE_CSV: { - verifyArgCount(argEvaluators, 0, "unescapeCsv"); - return addToken(CharSequenceTranslatorEvaluator.csvUnescapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); - } - case UNESCAPE_HTML3: { - verifyArgCount(argEvaluators, 0, "unescapeHtml3"); - return addToken(CharSequenceTranslatorEvaluator.html3UnescapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); - } - case UNESCAPE_HTML4: { - verifyArgCount(argEvaluators, 0, "unescapeHtml4"); - return addToken(CharSequenceTranslatorEvaluator.html4UnescapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); - } - case UNESCAPE_JSON: { - verifyArgCount(argEvaluators, 0, "unescapeJson"); - return addToken(CharSequenceTranslatorEvaluator.jsonUnescapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); - } - case UNESCAPE_XML: { - verifyArgCount(argEvaluators, 0, "unescapeXml"); - return addToken(CharSequenceTranslatorEvaluator.xmlUnescapeEvaluator(toStringEvaluator(subjectEvaluator)), "escapeJson"); - } - case SUBSTRING_BEFORE: { - verifyArgCount(argEvaluators, 1, "substringBefore"); - return addToken(new SubstringBeforeEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to substringBefore")), "substringBefore"); - } - case SUBSTRING_BEFORE_LAST: { - verifyArgCount(argEvaluators, 1, "substringBeforeLast"); - return addToken(new SubstringBeforeLastEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to substringBeforeLast")), "substringBeforeLast"); - } - case SUBSTRING_AFTER: { - verifyArgCount(argEvaluators, 1, "substringAfter"); - return addToken(new SubstringAfterEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to substringAfter")), "substringAfter"); - } - case SUBSTRING_AFTER_LAST: { - verifyArgCount(argEvaluators, 1, "substringAfterLast"); - return addToken(new SubstringAfterLastEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to substringAfterLast")), "substringAfterLast"); - } - case REPLACE_NULL: { - verifyArgCount(argEvaluators, 1, "replaceNull"); - return addToken(new ReplaceNullEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to replaceNull")), "replaceNull"); - } - case REPLACE_EMPTY: { - verifyArgCount(argEvaluators, 1, "replaceEmtpy"); - return addToken(new ReplaceEmptyEvaluator(toStringEvaluator(subjectEvaluator), toStringEvaluator(argEvaluators.get(0), "first argument to replaceEmpty")), "replaceEmpty"); - } - case REPLACE: { - verifyArgCount(argEvaluators, 2, "replace"); - return addToken(new ReplaceEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to replace"), - toStringEvaluator(argEvaluators.get(1), "second argument to replace")), "replace"); - } - case REPLACE_FIRST: { - verifyArgCount(argEvaluators, 2, "replaceFirst"); - return addToken(new ReplaceFirstEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to replaceFirst"), - toStringEvaluator(argEvaluators.get(1), "second argument to replaceFirst")), "replaceFirst"); - } - case REPLACE_ALL: { - verifyArgCount(argEvaluators, 2, "replaceAll"); - return addToken(new ReplaceAllEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to replaceAll"), - toStringEvaluator(argEvaluators.get(1), "second argument to replaceAll")), "replaceAll"); - } - case APPEND: { - verifyArgCount(argEvaluators, 1, "append"); - return addToken(new AppendEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to append")), "append"); - } - case PREPEND: { - verifyArgCount(argEvaluators, 1, "prepend"); - return addToken(new PrependEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to prepend")), "prepend"); - } - case SUBSTRING: { - final int numArgs = argEvaluators.size(); - if (numArgs == 1) { - return addToken(new SubstringEvaluator(toStringEvaluator(subjectEvaluator), - toWholeNumberEvaluator(argEvaluators.get(0), "first argument to substring")), "substring"); - } else if (numArgs == 2) { - return addToken(new SubstringEvaluator(toStringEvaluator(subjectEvaluator), - toWholeNumberEvaluator(argEvaluators.get(0), "first argument to substring"), - toWholeNumberEvaluator(argEvaluators.get(1), "second argument to substring")), "substring"); - } else { - throw new AttributeExpressionLanguageParsingException("substring() function can take either 1 or 2 arguments but cannot take " + numArgs + " arguments"); - } - } - case JOIN: { - verifyArgCount(argEvaluators, 1, "join"); - return addToken(new JoinEvaluator(toStringEvaluator(subjectEvaluator), toStringEvaluator(argEvaluators.get(0))), "join"); - } - case COUNT: { - verifyArgCount(argEvaluators, 0, "count"); - return addToken(new CountEvaluator(subjectEvaluator), "count"); - } - case IS_NULL: { - verifyArgCount(argEvaluators, 0, "isNull"); - return addToken(new IsNullEvaluator(toStringEvaluator(subjectEvaluator)), "isNull"); - } - case IS_EMPTY: { - verifyArgCount(argEvaluators, 0, "isEmpty"); - return addToken(new IsEmptyEvaluator(toStringEvaluator(subjectEvaluator)), "isEmpty"); - } - case NOT_NULL: { - verifyArgCount(argEvaluators, 0, "notNull"); - return addToken(new NotNullEvaluator(toStringEvaluator(subjectEvaluator)), "notNull"); - } - case STARTS_WITH: { - verifyArgCount(argEvaluators, 1, "startsWith"); - return addToken(new StartsWithEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to startsWith")), "startsWith"); - } - case ENDS_WITH: { - verifyArgCount(argEvaluators, 1, "endsWith"); - return addToken(new EndsWithEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to endsWith")), "endsWith"); - } - case CONTAINS: { - verifyArgCount(argEvaluators, 1, "contains"); - return addToken(new ContainsEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to contains")), "contains"); - } - case IN: { - List<Evaluator<String>> list = new ArrayList<Evaluator<String>>(); - for(int i = 0; i < argEvaluators.size(); i++) { - list.add(toStringEvaluator(argEvaluators.get(i), i + "th argument to in")); - } - return addToken(new InEvaluator(toStringEvaluator(subjectEvaluator), list), "in"); - } - case FIND: { - verifyArgCount(argEvaluators, 1, "find"); - return addToken(new FindEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to find")), "find"); - } - case MATCHES: { - verifyArgCount(argEvaluators, 1, "matches"); - return addToken(new MatchesEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to matches")), "matches"); - } - case EQUALS: { - verifyArgCount(argEvaluators, 1, "equals"); - return addToken(new EqualsEvaluator(subjectEvaluator, argEvaluators.get(0)), "equals"); - } - case EQUALS_IGNORE_CASE: { - verifyArgCount(argEvaluators, 1, "equalsIgnoreCase"); - return addToken(new EqualsIgnoreCaseEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to equalsIgnoreCase")), "equalsIgnoreCase"); - } - case GREATER_THAN: { - verifyArgCount(argEvaluators, 1, "gt"); - return addToken(new GreaterThanEvaluator(toNumberEvaluator(subjectEvaluator), - toNumberEvaluator(argEvaluators.get(0), "first argument to gt")), "gt"); - } - case GREATER_THAN_OR_EQUAL: { - verifyArgCount(argEvaluators, 1, "ge"); - return addToken(new GreaterThanOrEqualEvaluator(toNumberEvaluator(subjectEvaluator), - toNumberEvaluator(argEvaluators.get(0), "first argument to ge")), "ge"); - } - case LESS_THAN: { - verifyArgCount(argEvaluators, 1, "lt"); - return addToken(new LessThanEvaluator(toNumberEvaluator(subjectEvaluator), - toNumberEvaluator(argEvaluators.get(0), "first argument to lt")), "lt"); - } - case LESS_THAN_OR_EQUAL: { - verifyArgCount(argEvaluators, 1, "le"); - return addToken(new LessThanOrEqualEvaluator(toNumberEvaluator(subjectEvaluator), - toNumberEvaluator(argEvaluators.get(0), "first argument to le")), "le"); - } - case LENGTH: { - verifyArgCount(argEvaluators, 0, "length"); - return addToken(new LengthEvaluator(toStringEvaluator(subjectEvaluator)), "length"); - } - case TO_DATE: { - if (argEvaluators.isEmpty()) { - return addToken(new NumberToDateEvaluator(toWholeNumberEvaluator(subjectEvaluator)), "toDate"); - } else if (subjectEvaluator.getResultType() == ResultType.STRING && argEvaluators.size() == 1) { - return addToken(new StringToDateEvaluator(toStringEvaluator(subjectEvaluator), toStringEvaluator(argEvaluators.get(0)), null), "toDate"); - } else if (subjectEvaluator.getResultType() == ResultType.STRING && argEvaluators.size() == 2) { - return addToken(new StringToDateEvaluator(toStringEvaluator(subjectEvaluator), toStringEvaluator(argEvaluators.get(0)), toStringEvaluator(argEvaluators.get(1))), "toDate"); - } else { - return addToken(new NumberToDateEvaluator(toWholeNumberEvaluator(subjectEvaluator)), "toDate"); - } - } - case TO_NUMBER: { - verifyArgCount(argEvaluators, 0, "toNumber"); - switch (subjectEvaluator.getResultType()) { - case STRING: - case WHOLE_NUMBER: - case DECIMAL: - case NUMBER: - case DATE: - return addToken(toWholeNumberEvaluator(subjectEvaluator), "toNumber"); - default: - throw new AttributeExpressionLanguageParsingException(subjectEvaluator + " returns type " + subjectEvaluator.getResultType() + " but expected to get " + ResultType.STRING + - ", " + ResultType.DECIMAL + ", or " + ResultType.DATE); - } - } - case TO_DECIMAL: { - verifyArgCount(argEvaluators, 0, "toDecimal"); - switch (subjectEvaluator.getResultType()) { - case WHOLE_NUMBER: - case DECIMAL: - case STRING: - case NUMBER: - case DATE: - return addToken(toDecimalEvaluator(subjectEvaluator), "toDecimal"); - default: - throw new AttributeExpressionLanguageParsingException(subjectEvaluator + " returns type " + subjectEvaluator.getResultType() + " but expected to get " + ResultType.STRING + - ", " + ResultType.WHOLE_NUMBER + ", or " + ResultType.DATE); - } - } - case TO_RADIX: { - if (argEvaluators.size() == 1) { - return addToken(new ToRadixEvaluator(toWholeNumberEvaluator(subjectEvaluator), - toWholeNumberEvaluator(argEvaluators.get(0))), "toRadix"); - } else { - return addToken(new ToRadixEvaluator(toWholeNumberEvaluator(subjectEvaluator), - toWholeNumberEvaluator(argEvaluators.get(0)), toWholeNumberEvaluator(argEvaluators.get(1))), "toRadix"); - } - } - case FROM_RADIX: { - return addToken(new FromRadixEvaluator(toStringEvaluator(subjectEvaluator), - toWholeNumberEvaluator(argEvaluators.get(0))), "fromRadix"); - } - case MOD: { - return addToken(new ModEvaluator(toNumberEvaluator(subjectEvaluator), toNumberEvaluator(argEvaluators.get(0))), "mod"); - } - case PLUS: { - return addToken(new PlusEvaluator(toNumberEvaluator(subjectEvaluator), toNumberEvaluator(argEvaluators.get(0))), "plus"); - } - case MINUS: { - return addToken(new MinusEvaluator(toNumberEvaluator(subjectEvaluator), toNumberEvaluator(argEvaluators.get(0))), "minus"); - } - case MULTIPLY: { - return addToken(new MultiplyEvaluator(toNumberEvaluator(subjectEvaluator), toNumberEvaluator(argEvaluators.get(0))), "multiply"); - } - case DIVIDE: { - return addToken(new DivideEvaluator(toNumberEvaluator(subjectEvaluator), toNumberEvaluator(argEvaluators.get(0))), "divide"); - } - case MATH: { - if (argEvaluators.size() == 1) { - return addToken(new MathEvaluator(toNumberEvaluator(subjectEvaluator), toStringEvaluator(argEvaluators.get(0)), null), "math"); - } else if (argEvaluators.size() == 2){ - return addToken(new MathEvaluator(toNumberEvaluator(subjectEvaluator), toStringEvaluator(argEvaluators.get(0)), toNumberEvaluator(argEvaluators.get(1))), "math"); - } else { - throw new AttributeExpressionLanguageParsingException("math() function takes 1 or 2 arguments"); - } - } - case RANDOM : { - return addToken(new RandomNumberGeneratorEvaluator(), "random"); - } - case INDEX_OF: { - verifyArgCount(argEvaluators, 1, "indexOf"); - return addToken(new IndexOfEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to indexOf")), "indexOf"); - } - case LAST_INDEX_OF: { - verifyArgCount(argEvaluators, 1, "lastIndexOf"); - return addToken(new LastIndexOfEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to lastIndexOf")), "lastIndexOf"); - } - case FORMAT: { - if(argEvaluators.size() == 1) { - return addToken(new FormatEvaluator(toDateEvaluator(subjectEvaluator), toStringEvaluator(argEvaluators.get(0), "first argument of format"), null), "format"); - } else if (argEvaluators.size() == 2) { - return addToken(new FormatEvaluator(toDateEvaluator(subjectEvaluator), toStringEvaluator(argEvaluators.get(0)), toStringEvaluator(argEvaluators.get(1))), "format"); - } else { - throw new AttributeExpressionLanguageParsingException("format() function takes 1 or 2 arguments"); - } - } - case OR: { - return addToken(new OrEvaluator(toBooleanEvaluator(subjectEvaluator), toBooleanEvaluator(argEvaluators.get(0))), "or"); - } - case AND: { - return addToken(new AndEvaluator(toBooleanEvaluator(subjectEvaluator), toBooleanEvaluator(argEvaluators.get(0))), "and"); - } - case NOT: { - return addToken(new NotEvaluator(toBooleanEvaluator(subjectEvaluator)), "not"); - } - case GET_DELIMITED_FIELD: { - if (argEvaluators.size() == 1) { - // Only a single argument - the index to return. - return addToken(new GetDelimitedFieldEvaluator(toStringEvaluator(subjectEvaluator), - toWholeNumberEvaluator(argEvaluators.get(0), "first argument of getDelimitedField")), "getDelimitedField"); - } else if (argEvaluators.size() == 2) { - // two arguments - index and delimiter. - return addToken(new GetDelimitedFieldEvaluator(toStringEvaluator(subjectEvaluator), - toWholeNumberEvaluator(argEvaluators.get(0), "first argument of getDelimitedField"), - toStringEvaluator(argEvaluators.get(1), "second argument of getDelimitedField")), - "getDelimitedField"); - } else if (argEvaluators.size() == 3) { - // 3 arguments - index, delimiter, quote char. - return addToken(new GetDelimitedFieldEvaluator(toStringEvaluator(subjectEvaluator), - toWholeNumberEvaluator(argEvaluators.get(0), "first argument of getDelimitedField"), - toStringEvaluator(argEvaluators.get(1), "second argument of getDelimitedField"), - toStringEvaluator(argEvaluators.get(2), "third argument of getDelimitedField")), - "getDelimitedField"); - } else if (argEvaluators.size() == 4) { - // 4 arguments - index, delimiter, quote char, escape char - return addToken(new GetDelimitedFieldEvaluator(toStringEvaluator(subjectEvaluator), - toWholeNumberEvaluator(argEvaluators.get(0), "first argument of getDelimitedField"), - toStringEvaluator(argEvaluators.get(1), "second argument of getDelimitedField"), - toStringEvaluator(argEvaluators.get(2), "third argument of getDelimitedField"), - toStringEvaluator(argEvaluators.get(3), "fourth argument of getDelimitedField")), - "getDelimitedField"); - } else { - // 5 arguments - index, delimiter, quote char, escape char, strip escape/quote chars flag - return addToken(new GetDelimitedFieldEvaluator(toStringEvaluator(subjectEvaluator), - toWholeNumberEvaluator(argEvaluators.get(0), "first argument of getDelimitedField"), - toStringEvaluator(argEvaluators.get(1), "second argument of getDelimitedField"), - toStringEvaluator(argEvaluators.get(2), "third argument of getDelimitedField"), - toStringEvaluator(argEvaluators.get(3), "fourth argument of getDelimitedField"), - toBooleanEvaluator(argEvaluators.get(4), "fifth argument of getDelimitedField")), - "getDelimitedField"); - } - } - case JSON_PATH: { - verifyArgCount(argEvaluators, 1, "jsonPath"); - return addToken(new JsonPathEvaluator(toStringEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "first argument to jsonPath")), "jsonPath"); - } - case IF_ELSE: { - verifyArgCount(argEvaluators, 2, "ifElse"); - return addToken(new IfElseEvaluator(toBooleanEvaluator(subjectEvaluator), - toStringEvaluator(argEvaluators.get(0), "argument to return if true"), - toStringEvaluator(argEvaluators.get(1), "argument to return if false")), "ifElse"); - } - default: - throw new AttributeExpressionLanguageParsingException("Expected a Function-type expression but got " + tree.toString()); - } - } public static class Range {
http://git-wip-us.apache.org/repos/asf/nifi/blob/5cd8e93b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/StandardPreparedQuery.java ---------------------------------------------------------------------- diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/StandardPreparedQuery.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/StandardPreparedQuery.java index 9f12c92..cdf5a2d 100644 --- a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/StandardPreparedQuery.java +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/StandardPreparedQuery.java @@ -16,36 +16,45 @@ */ package org.apache.nifi.attribute.expression.language; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import org.apache.nifi.attribute.expression.language.compile.CompiledExpression; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.literals.StringLiteralEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.selection.AllAttributesEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.selection.AnyAttributeEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.selection.AttributeEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.selection.MappingEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.selection.MultiAttributeEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.selection.MultiMatchAttributeEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.selection.MultiNamedAttributeEvaluator; import org.apache.nifi.expression.AttributeValueDecorator; import org.apache.nifi.processor.exception.ProcessException; -import org.antlr.runtime.tree.Tree; - public class StandardPreparedQuery implements PreparedQuery { private final List<String> queryStrings; - private final Map<String, Tree> trees; + private final Map<String, CompiledExpression> expressions; + private volatile VariableImpact variableImpact; - public StandardPreparedQuery(final List<String> queryStrings, final Map<String, Tree> trees) { - this.queryStrings = new ArrayList<>(queryStrings); - this.trees = new HashMap<>(trees); + public StandardPreparedQuery(final List<String> queryStrings, final Map<String, CompiledExpression> expressions) { + this.queryStrings = queryStrings; + this.expressions = expressions; } - @Override public String evaluateExpressions(final Map<String, String> valMap, final AttributeValueDecorator decorator, final Map<String, String> stateVariables) throws ProcessException { final StringBuilder sb = new StringBuilder(); for (final String val : queryStrings) { - final Tree tree = trees.get(val); - if (tree == null) { + final CompiledExpression expression = expressions.get(val); + if (expression == null) { sb.append(val); } else { - final String evaluated = Query.evaluateExpression(tree, val, valMap, decorator, stateVariables); + final String evaluated = Query.evaluateExpression(expression.getTree(), val, valMap, decorator, stateVariables); if (evaluated != null) { sb.append(evaluated); } @@ -62,6 +71,56 @@ public class StandardPreparedQuery implements PreparedQuery { @Override public boolean isExpressionLanguagePresent() { - return !trees.isEmpty(); + return !expressions.isEmpty(); + } + + @Override + public VariableImpact getVariableImpact() { + final VariableImpact existing = this.variableImpact; + if (existing != null) { + return existing; + } + + final Set<String> variables = new HashSet<>(); + + for (final CompiledExpression expression : expressions.values()) { + for (final Evaluator<?> evaluator : expression.getAllEvaluators()) { + if (evaluator instanceof AttributeEvaluator) { + final AttributeEvaluator attributeEval = (AttributeEvaluator) evaluator; + final Evaluator<String> nameEval = attributeEval.getNameEvaluator(); + + if (nameEval instanceof StringLiteralEvaluator) { + final String referencedVar = nameEval.evaluate(Collections.emptyMap()).getValue(); + variables.add(referencedVar); + } + } else if (evaluator instanceof AllAttributesEvaluator) { + final AllAttributesEvaluator allAttrsEval = (AllAttributesEvaluator) evaluator; + final MultiAttributeEvaluator iteratingEval = allAttrsEval.getVariableIteratingEvaluator(); + if (iteratingEval instanceof MultiNamedAttributeEvaluator) { + variables.addAll(((MultiNamedAttributeEvaluator) iteratingEval).getAttributeNames()); + } else if (iteratingEval instanceof MultiMatchAttributeEvaluator) { + return VariableImpact.ALWAYS_IMPACTED; + } + } else if (evaluator instanceof AnyAttributeEvaluator) { + final AnyAttributeEvaluator allAttrsEval = (AnyAttributeEvaluator) evaluator; + final MultiAttributeEvaluator iteratingEval = allAttrsEval.getVariableIteratingEvaluator(); + if (iteratingEval instanceof MultiNamedAttributeEvaluator) { + variables.addAll(((MultiNamedAttributeEvaluator) iteratingEval).getAttributeNames()); + } else if (iteratingEval instanceof MultiMatchAttributeEvaluator) { + return VariableImpact.ALWAYS_IMPACTED; + } + } else if (evaluator instanceof MappingEvaluator) { + final MappingEvaluator<?> allAttrsEval = (MappingEvaluator<?>) evaluator; + final MultiAttributeEvaluator iteratingEval = allAttrsEval.getVariableIteratingEvaluator(); + if (iteratingEval instanceof MultiNamedAttributeEvaluator) { + variables.addAll(((MultiNamedAttributeEvaluator) iteratingEval).getAttributeNames()); + } + } + } + } + + final VariableImpact impact = new NamedVariableImpact(variables); + this.variableImpact = impact; + return impact; } } http://git-wip-us.apache.org/repos/asf/nifi/blob/5cd8e93b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/ValueLookup.java ---------------------------------------------------------------------- diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/ValueLookup.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/ValueLookup.java index 5b0cdda..06c1877 100644 --- a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/ValueLookup.java +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/ValueLookup.java @@ -49,6 +49,7 @@ final class ValueLookup implements Map<String, String> { * @param flowFile the flowFile to pull attributes from; may be null * @param additionalMaps the maps to pull values from; may be null or empty */ + @SuppressWarnings("unchecked") ValueLookup(final VariableRegistry registry, final FlowFile flowFile, final Map<String, String>... additionalMaps) { for (final Map<String, String> map : additionalMaps) { if (map != null && !map.isEmpty()) { http://git-wip-us.apache.org/repos/asf/nifi/blob/5cd8e93b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/VariableImpact.java ---------------------------------------------------------------------- diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/VariableImpact.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/VariableImpact.java new file mode 100644 index 0000000..4a66c87 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/VariableImpact.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.attribute.expression.language; + +public interface VariableImpact { + boolean isImpacted(String variableName); + + public static final VariableImpact NEVER_IMPACTED = var -> false; + + public static final VariableImpact ALWAYS_IMPACTED = var -> true; +} http://git-wip-us.apache.org/repos/asf/nifi/blob/5cd8e93b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/compile/CompiledExpression.java ---------------------------------------------------------------------- diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/compile/CompiledExpression.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/compile/CompiledExpression.java new file mode 100644 index 0000000..d234445 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/compile/CompiledExpression.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.nifi.attribute.expression.language.compile; + +import java.util.Set; + +import org.antlr.runtime.tree.Tree; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; + +public class CompiledExpression { + private final Evaluator<?> rootEvaluator; + private final Tree tree; + private final String expression; + private final Set<Evaluator<?>> allEvaluators; + + public CompiledExpression(final String expression, final Evaluator<?> rootEvaluator, final Tree tree, final Set<Evaluator<?>> allEvaluators) { + this.rootEvaluator = rootEvaluator; + this.tree = tree; + this.expression = expression; + this.allEvaluators = allEvaluators; + } + + public Evaluator<?> getRootEvaluator() { + return rootEvaluator; + } + + public Tree getTree() { + return tree; + } + + public String getExpression() { + return expression; + } + + public Set<Evaluator<?>> getAllEvaluators() { + return allEvaluators; + } +}
