mirror of https://github.com/apache/nifi.git
NIFI-206: Build appropriate AnyAttribute, AllAttributes, AnyMatchingAttribute, etc. evaluators in the buildExpressionEvaluator method rather than building at evaluation time. This way, embedded expressions are also wrapped appropriately.
This commit is contained in:
parent
bfe39c0b82
commit
fed987e778
|
@ -636,32 +636,7 @@ public class Query {
|
||||||
throw new IllegalStateException("A Query cannot be evaluated more than once");
|
throw new IllegalStateException("A Query cannot be evaluated more than once");
|
||||||
}
|
}
|
||||||
|
|
||||||
Evaluator<?> chosenEvaluator = evaluator;
|
return evaluator.evaluate(attributes);
|
||||||
final Evaluator<?> rootEvaluator = getRootSubjectEvaluator(evaluator);
|
|
||||||
if (rootEvaluator != null) {
|
|
||||||
if (rootEvaluator instanceof MultiAttributeEvaluator) {
|
|
||||||
if (evaluator.getResultType() != ResultType.BOOLEAN) {
|
|
||||||
throw new AttributeExpressionLanguageParsingException("Found Multi-Attribute function but return type is " + evaluator.getResultType() + ", not " + ResultType.BOOLEAN + ", for query: " + query);
|
|
||||||
}
|
|
||||||
|
|
||||||
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:
|
|
||||||
chosenEvaluator = new AllAttributesEvaluator((BooleanEvaluator) evaluator, multiAttrEval);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return chosenEvaluator.evaluate(attributes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tree getTree() {
|
Tree getTree() {
|
||||||
|
@ -843,8 +818,10 @@ public class Query {
|
||||||
if (tree.getChildCount() == 0) {
|
if (tree.getChildCount() == 0) {
|
||||||
throw new AttributeExpressionLanguageParsingException("EXPRESSION tree node has no children");
|
throw new AttributeExpressionLanguageParsingException("EXPRESSION tree node has no children");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Evaluator<?> evaluator;
|
||||||
if (tree.getChildCount() == 1) {
|
if (tree.getChildCount() == 1) {
|
||||||
return buildEvaluator(tree.getChild(0));
|
evaluator = buildEvaluator(tree.getChild(0));
|
||||||
} else {
|
} else {
|
||||||
// we can chain together functions in the form of:
|
// we can chain together functions in the form of:
|
||||||
// ${x:trim():substring(1,2):trim()}
|
// ${x:trim():substring(1,2):trim()}
|
||||||
|
@ -852,8 +829,35 @@ public class Query {
|
||||||
// subject is the function to its left (the first trim()), and its subject is the value of
|
// 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
|
// 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.
|
// tree from the right-most child going left-ward.
|
||||||
return buildFunctionExpressionEvaluator(tree, 0);
|
evaluator = buildFunctionExpressionEvaluator(tree, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Evaluator<?> chosenEvaluator = evaluator;
|
||||||
|
final Evaluator<?> rootEvaluator = getRootSubjectEvaluator(evaluator);
|
||||||
|
if (rootEvaluator != null) {
|
||||||
|
if (rootEvaluator instanceof MultiAttributeEvaluator) {
|
||||||
|
if (evaluator.getResultType() != ResultType.BOOLEAN) {
|
||||||
|
throw new AttributeExpressionLanguageParsingException("Found Multi-Attribute function but return type is " + evaluator.getResultType() + ", not " + ResultType.BOOLEAN + ", for query: " + tree.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
chosenEvaluator = new AllAttributesEvaluator((BooleanEvaluator) evaluator, multiAttrEval);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chosenEvaluator;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Evaluator<?> buildFunctionExpressionEvaluator(final Tree tree, final int offset) {
|
private static Evaluator<?> buildFunctionExpressionEvaluator(final Tree tree, final int offset) {
|
||||||
|
|
|
@ -1047,6 +1047,16 @@ public class TestQuery {
|
||||||
assertEquals(ResultType.NUMBER, Query.getResultType("${header.size:toNumber()}"));
|
assertEquals(ResultType.NUMBER, Query.getResultType("${header.size:toNumber()}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAnyAttributeEmbedded() {
|
||||||
|
final Map<String, String> attributes = new HashMap<>();
|
||||||
|
attributes.put("a1", "test1");
|
||||||
|
attributes.put("b2", "2test");
|
||||||
|
attributes.put("c3", "3test3");
|
||||||
|
|
||||||
|
final String query = "${a1:equals('test1'):and( ${anyAttribute('a1','b2','c3'):contains('2')})}";
|
||||||
|
verifyEquals(query, attributes, true);
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyEquals(final String expression, final Map<String, String> attributes, final Object expectedResult) {
|
private void verifyEquals(final String expression, final Map<String, String> attributes, final Object expectedResult) {
|
||||||
Query.validateExpression(expression, false);
|
Query.validateExpression(expression, false);
|
||||||
|
|
Loading…
Reference in New Issue