use of org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException 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.attribute.expression.language.exception.AttributeExpressionLanguageException in project nifi by apache.
the class GetDelimitedFieldEvaluator method evaluate.
@Override
public QueryResult<String> evaluate(final Map<String, String> attributes) {
final String subject = subjectEval.evaluate(attributes).getValue();
if (subject == null || subject.isEmpty()) {
return new StringQueryResult("");
}
final Long index = indexEval.evaluate(attributes).getValue();
if (index == null) {
throw new AttributeExpressionLanguageException("Cannot evaluate getDelimitedField function because the index (which field to obtain) was not specified");
}
if (index < 1) {
return new StringQueryResult("");
}
final String delimiter = delimiterEval.evaluate(attributes).getValue();
if (delimiter == null || delimiter.isEmpty()) {
throw new AttributeExpressionLanguageException("Cannot evaluate getDelimitedField function because the delimiter was not specified");
} else if (delimiter.length() > 1) {
throw new AttributeExpressionLanguageException("Cannot evaluate getDelimitedField function because the delimiter evaluated to \"" + delimiter + "\", but only a single character is allowed.");
}
final String quoteString = quoteCharEval.evaluate(attributes).getValue();
if (quoteString == null || quoteString.isEmpty()) {
throw new AttributeExpressionLanguageException("Cannot evaluate getDelimitedField function because the quote character " + "(which character is used to enclose values that contain the delimiter) was not specified");
} else if (quoteString.length() > 1) {
throw new AttributeExpressionLanguageException("Cannot evaluate getDelimitedField function because the quote character " + "(which character is used to enclose values that contain the delimiter) evaluated to \"" + quoteString + "\", but only a single character is allowed.");
}
final String escapeString = escapeCharEval.evaluate(attributes).getValue();
if (escapeString == null || escapeString.isEmpty()) {
throw new AttributeExpressionLanguageException("Cannot evaluate getDelimitedField function because the escape character " + "(which character is used to escape the quote character or delimiter) was not specified");
} else if (escapeString.length() > 1) {
throw new AttributeExpressionLanguageException("Cannot evaluate getDelimitedField function because the escape character " + "(which character is used to escape the quote character or delimiter) evaluated to \"" + escapeString + "\", but only a single character is allowed.");
}
Boolean stripChars = stripCharsEval.evaluate(attributes).getValue();
if (stripChars == null) {
stripChars = Boolean.FALSE;
}
final char quoteChar = quoteString.charAt(0);
final char delimiterChar = delimiter.charAt(0);
final char escapeChar = escapeString.charAt(0);
// ensure that quoteChar, delimiterChar, escapeChar are all different.
if (quoteChar == delimiterChar) {
throw new AttributeExpressionLanguageException("Cannot evaluate getDelimitedField function because the quote character and the delimiter are the same");
}
if (quoteChar == escapeChar) {
throw new AttributeExpressionLanguageException("Cannot evaluate getDelimitedField function because the quote character and the escape character are the same");
}
if (delimiterChar == escapeChar) {
throw new AttributeExpressionLanguageException("Cannot evaluate getDelimitedField function because the delimiter and the escape character are the same");
}
// Iterate through each character in the subject, trying to find the field index that we care about and extracting the chars from it.
final StringBuilder fieldBuilder = new StringBuilder();
final int desiredFieldIndex = index.intValue();
final int numChars = subject.length();
boolean inQuote = false;
int curFieldIndex = 1;
boolean lastCharIsEscape = false;
for (int i = 0; i < numChars; i++) {
final char c = subject.charAt(i);
if (c == quoteChar && !lastCharIsEscape) {
// we found a quote character that is not escaped. Flip the value of 'inQuote'
inQuote = !inQuote;
if (!stripChars && curFieldIndex == desiredFieldIndex) {
fieldBuilder.append(c);
}
} else if (c == delimiterChar && !lastCharIsEscape && !inQuote) {
// We found a delimiter that is not escaped and we are not in quotes - or we ran out of characters so we consider this
// the last character.
final int indexJustFinished = curFieldIndex++;
if (indexJustFinished == desiredFieldIndex) {
return new StringQueryResult(fieldBuilder.toString());
}
} else if (curFieldIndex == desiredFieldIndex) {
if (c != escapeChar || !stripChars) {
fieldBuilder.append(c);
}
}
lastCharIsEscape = (c == escapeChar) && !lastCharIsEscape;
}
if (curFieldIndex == desiredFieldIndex) {
// we have run out of characters and we are on the desired field. Return the characters from this field.
return new StringQueryResult(fieldBuilder.toString());
}
// We did not find enough fields. Return an empty string.
return new StringQueryResult("");
}
use of org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException in project nifi by apache.
the class JsonPathEvaluator method evaluate.
@Override
public QueryResult<String> evaluate(final Map<String, String> attributes) {
final String subjectValue = subject.evaluate(attributes).getValue();
if (subjectValue == null || subjectValue.length() == 0) {
throw new AttributeExpressionLanguageException("Subject is empty");
}
DocumentContext documentContext = null;
try {
documentContext = validateAndEstablishJsonContext(subjectValue);
} catch (InvalidJsonException e) {
throw new AttributeExpressionLanguageException("Subject contains invalid JSON: " + subjectValue, e);
}
final JsonPath compiledJsonPath;
if (precompiledJsonPathExp != null) {
compiledJsonPath = precompiledJsonPathExp;
} else {
compiledJsonPath = compileJsonPathExpression(jsonPathExp.evaluate(attributes).getValue());
}
Object result = null;
try {
result = documentContext.read(compiledJsonPath);
} catch (Exception e) {
// assume the path did not match anything in the document
return EMPTY_RESULT;
}
return new StringQueryResult(getResultRepresentation(result, EMPTY_RESULT.getValue()));
}
use of org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException in project nifi by apache.
the class MathEvaluator method evaluate.
@Override
public QueryResult<Number> evaluate(final Map<String, String> attributes) {
final String methodNamedValue = methodName.evaluate(attributes).getValue();
if (methodNamedValue == null) {
return new NumberQueryResult(null);
}
final Number subjectValue;
if (subject != null) {
subjectValue = subject.evaluate(attributes).getValue();
if (subjectValue == null) {
return new NumberQueryResult(null);
}
} else {
subjectValue = null;
}
final Number optionalArgValue;
if (optionalArg != null) {
optionalArgValue = optionalArg.evaluate(attributes).getValue();
if (optionalArgValue == null) {
return new NumberQueryResult(null);
}
} else {
optionalArgValue = null;
}
try {
Number executionValue = null;
if (subjectValue == null) {
Method method;
try {
method = Math.class.getMethod(methodNamedValue);
} catch (NoSuchMethodException subjectlessNoMethodException) {
throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because no subjectless method was found with the name:'" + methodNamedValue + "'", subjectlessNoMethodException);
}
if (method == null) {
throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because no subjectless method was found with the name:'" + methodNamedValue + "'");
}
executionValue = (Number) method.invoke(null);
} else if (optionalArg == null) {
boolean subjectIsDecimal = subjectValue instanceof Double;
Method method;
try {
method = Math.class.getMethod(methodNamedValue, subjectIsDecimal ? double.class : long.class);
} catch (NoSuchMethodException noOptionalNoMethodException) {
throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because no method was found matching the passed parameters:" + " name:'" + methodNamedValue + "', one argument of type: '" + (subjectIsDecimal ? "double" : "long") + "'", noOptionalNoMethodException);
}
if (method == null) {
throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because no method was found matching the passed parameters:" + " name:'" + methodNamedValue + "', one argument of type: '" + (subjectIsDecimal ? "double" : "long") + "'");
}
if (subjectIsDecimal) {
executionValue = (Number) method.invoke(null, subjectValue.doubleValue());
} else {
executionValue = (Number) method.invoke(null, subjectValue.longValue());
}
} else {
boolean subjectIsDecimal = subjectValue instanceof Double;
boolean optionalArgIsDecimal = optionalArgValue instanceof Double;
Method method;
boolean convertOptionalToInt = false;
try {
method = Math.class.getMethod(methodNamedValue, subjectIsDecimal ? double.class : long.class, optionalArgIsDecimal ? double.class : long.class);
} catch (NoSuchMethodException withOptionalNoMethodException) {
if (!optionalArgIsDecimal) {
try {
method = Math.class.getMethod(methodNamedValue, subjectIsDecimal ? double.class : long.class, int.class);
} catch (NoSuchMethodException withOptionalInnerNoMethodException) {
throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because no method was found matching the passed parameters: " + "name:'" + methodNamedValue + "', first argument type: '" + (subjectIsDecimal ? "double" : "long") + "', second argument type: 'long'", withOptionalInnerNoMethodException);
}
convertOptionalToInt = true;
} else {
throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because no method was found matching the passed parameters: " + "name:'" + methodNamedValue + "', first argument type: '" + (subjectIsDecimal ? "double" : "long") + "', second argument type: 'double'", withOptionalNoMethodException);
}
}
if (method == null) {
throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because no method was found matching the passed parameters: " + "name:'" + methodNamedValue + "', first argument type: '" + (subjectIsDecimal ? "double" : "long") + "', second argument type: '" + (optionalArgIsDecimal ? "double" : "long") + "'");
}
if (optionalArgIsDecimal) {
executionValue = (Number) method.invoke(null, subjectValue, optionalArgValue.doubleValue());
} else {
if (convertOptionalToInt) {
executionValue = (Number) method.invoke(null, subjectValue, optionalArgValue.intValue());
} else {
executionValue = (Number) method.invoke(null, subjectValue, optionalArgValue.longValue());
}
}
}
return new NumberQueryResult(executionValue);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new AttributeExpressionLanguageException("Unable to calculate math function value", e);
}
}
Aggregations