in nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/compile/ExpressionCompiler.java [1136:1294]
public Evaluator<?> buildEvaluator(final Tree tree) {
switch (tree.getType()) {
case EXPRESSION: {
return buildExpressionEvaluator(tree);
}
case PARAMETER_REFERENCE: {
final String parameterName = tree.getChild(0).getText();
final ParameterEvaluator parameterEvaluator = new ParameterEvaluator(parameterName);
evaluators.add(parameterEvaluator);
return parameterEvaluator;
}
case ATTRIBUTE_REFERENCE: {
final Evaluator<?> childEvaluator = buildEvaluator(tree.getChild(0));
if (childEvaluator instanceof MultiAttributeEvaluator) {
return childEvaluator;
}
final AttributeEvaluator eval = new AttributeEvaluator(toStringEvaluator(childEvaluator));
evaluators.add(eval);
return eval;
}
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)));
final String token = (multiAttrType == ANY_DELINEATED_VALUE) ? "anyDelineatedValue" : "allDelineatedValues";
return addToken(new DelineatedAttributeEvaluator(delineatedValueEvaluator, delimiterEvaluator, multiAttrType), token);
}
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(new StandardEvaluationContext(Collections.emptyMap())).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 addToken(new MultiNamedAttributeEvaluator(attributeNames, ALL_ATTRIBUTES), "allAttributes");
case ALL_MATCHING_ATTRIBUTES:
return addToken(new MultiMatchAttributeEvaluator(attributeNames, ALL_MATCHING_ATTRIBUTES), "allMatchingAttributes");
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 addToken(new MultiNamedAttributeEvaluator(attributeNames, ANY_ATTRIBUTE), "anyAttribute");
case ANY_MATCHING_ATTRIBUTE:
return addToken(new MultiMatchAttributeEvaluator(attributeNames, ANY_MATCHING_ATTRIBUTE), "anyMatchingAttribute");
default:
throw new AssertionError("Illegal Multi-Attribute Reference: " + functionTypeTree.toString());
}
}
case ATTR_NAME: {
return newStringLiteralEvaluator(tree.getChild(0).getText());
}
case WHOLE_NUMBER: {
return addToken(new WholeNumberLiteralEvaluator(tree.getText()), "wholeNumber");
}
case STRING_LITERAL: {
return newStringLiteralEvaluator(tree.getText());
}
case DECIMAL: {
return addToken(new DecimalLiteralEvaluator(tree.getText()), "decimal");
}
case TRUE:
case FALSE:
return buildBooleanEvaluator(tree);
case NULL:
return newStringLiteralEvaluator(null);
case UUID: {
return addToken(new UuidEvaluator(), "uuid");
}
case NOW: {
return addToken(new NowEvaluator(), "now");
}
case TO_LITERAL: {
final Evaluator<?> argEvaluator = buildEvaluator(tree.getChild(0));
return addToken(new ToLiteralEvaluator(argEvaluator), "toLiteral");
}
case IP: {
try {
return addToken(new IPEvaluator(), "ip");
} catch (final UnknownHostException e) {
throw new AttributeExpressionLanguageException(e);
}
}
case THREAD:
return addToken(new ThreadEvaluator(), "thread");
case HOSTNAME: {
if (tree.getChildCount() == 0) {
try {
return addToken(new HostnameEvaluator(false), "hostname");
} 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 addToken(new HostnameEvaluator(true), "hostname");
case FALSE:
return addToken(new HostnameEvaluator(false), "hostname");
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 addToken(new OneUpSequenceEvaluator(), "nextInt");
}
case RANDOM: {
return addToken(new RandomNumberGeneratorEvaluator(), "random");
}
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);
final GetStateVariableEvaluator eval = new GetStateVariableEvaluator(stringEvaluator);
evaluators.add(eval);
return eval;
}
case GET_URI: {
List<Evaluator<String>> uriArgs = Stream.iterate(0, i -> i + 1)
.limit(tree.getChildCount())
.map(num -> toStringEvaluator(buildEvaluator(tree.getChild(num))))
.collect(Collectors.toList());
return addToken(new GetUriEvaluator(uriArgs), "getUri");
}
default:
throw new AttributeExpressionLanguageParsingException("Unexpected token: " + tree.toString());
}
}