use of org.apache.nifi.expression.AttributeExpression.ResultType in project nifi by apache.
the class ExpressionCompiler method verifyMappingEvaluatorReduced.
private 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");
}
}
}
use of org.apache.nifi.expression.AttributeExpression.ResultType in project nifi by apache.
the class StandardValidators method createAttributeExpressionLanguageValidator.
public static Validator createAttributeExpressionLanguageValidator(final ResultType expectedResultType, final boolean allowExtraCharacters) {
return new Validator() {
@Override
public ValidationResult validate(final String subject, final String input, final ValidationContext context) {
final String syntaxError = context.newExpressionLanguageCompiler().validateExpression(input, allowExtraCharacters);
if (syntaxError != null) {
return new ValidationResult.Builder().subject(subject).input(input).valid(false).explanation(syntaxError).build();
}
final ResultType resultType = allowExtraCharacters ? ResultType.STRING : context.newExpressionLanguageCompiler().getResultType(input);
if (!resultType.equals(expectedResultType)) {
return new ValidationResult.Builder().subject(subject).input(input).valid(false).explanation("Expected Attribute Query to return type " + expectedResultType + " but query returns type " + resultType).build();
}
return new ValidationResult.Builder().subject(subject).input(input).valid(true).build();
}
};
}
use of org.apache.nifi.expression.AttributeExpression.ResultType in project nifi by apache.
the class RouteText method customValidate.
@Override
protected Collection<ValidationResult> customValidate(ValidationContext validationContext) {
Collection<ValidationResult> results = new ArrayList<>(super.customValidate(validationContext));
boolean dynamicProperty = false;
final String matchStrategy = validationContext.getProperty(MATCH_STRATEGY).getValue();
final boolean compileRegex = matchStrategy.equals(matchesRegularExpressionValue) || matchStrategy.equals(containsRegularExpressionValue);
final boolean requiresExpression = matchStrategy.equalsIgnoreCase(satisfiesExpression);
Validator validator = null;
if (compileRegex) {
validator = StandardValidators.createRegexValidator(0, Integer.MAX_VALUE, true);
}
Map<PropertyDescriptor, String> allProperties = validationContext.getProperties();
for (final PropertyDescriptor descriptor : allProperties.keySet()) {
if (descriptor.isDynamic()) {
dynamicProperty = true;
final String propValue = validationContext.getProperty(descriptor).getValue();
if (compileRegex) {
ValidationResult validationResult = validator.validate(descriptor.getName(), propValue, validationContext);
if (validationResult != null) {
results.add(validationResult);
}
} else if (requiresExpression) {
try {
final ResultType resultType = validationContext.newExpressionLanguageCompiler().compile(propValue).getResultType();
if (resultType != ResultType.BOOLEAN) {
results.add(new ValidationResult.Builder().valid(false).input(propValue).subject(descriptor.getName()).explanation("expression returns type of " + resultType.name() + " but is required to return a Boolean value").build());
}
} catch (final IllegalArgumentException iae) {
results.add(new ValidationResult.Builder().valid(false).input(propValue).subject(descriptor.getName()).explanation("input is not a valid Expression Language expression").build());
}
}
}
}
if (!dynamicProperty) {
results.add(new ValidationResult.Builder().subject("Dynamic Properties").explanation("In order to route text there must be dynamic properties to match against").valid(false).build());
}
return results;
}
use of org.apache.nifi.expression.AttributeExpression.ResultType in project nifi by apache.
the class ExpressionCompiler method buildExpressionEvaluator.
@SuppressWarnings({ "rawtypes", "unchecked" })
private 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;
}
}
evaluators.add(chosenEvaluator);
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;
}
use of org.apache.nifi.expression.AttributeExpression.ResultType in project nifi by apache.
the class UpdateAttributeModelFactory method createCondition.
public Condition createCondition(final ConditionDTO dto) {
if (dto == null) {
throw new IllegalArgumentException("Condition must be specified.");
}
if (dto.getExpression() == null) {
throw new IllegalArgumentException("Conditions: Expression must be specified.");
}
// validate the condition's expression
final StandardExpressionLanguageCompiler elCompiler = new StandardExpressionLanguageCompiler();
final String syntaxError = elCompiler.validateExpression(dto.getExpression(), false);
if (syntaxError != null) {
throw new IllegalArgumentException(syntaxError);
}
final ResultType resultType = elCompiler.getResultType(dto.getExpression());
if (!ResultType.BOOLEAN.equals(resultType)) {
throw new IllegalArgumentException("Return type of condition is " + resultType + " but expected type BOOLEAN");
}
final Condition condition = new Condition();
condition.setId(dto.getId());
condition.setExpression(dto.getExpression());
return condition;
}
Aggregations