Search in sources :

Example 1 with AttributeExpressionLanguageException

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;
}
Also used : AttributeExpressionLanguageException(org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException) AnyAttributeEvaluator(org.apache.nifi.attribute.expression.language.evaluation.selection.AnyAttributeEvaluator) BooleanEvaluator(org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator) AllAttributesEvaluator(org.apache.nifi.attribute.expression.language.evaluation.selection.AllAttributesEvaluator) MultiAttributeEvaluator(org.apache.nifi.attribute.expression.language.evaluation.selection.MultiAttributeEvaluator) ResultType(org.apache.nifi.expression.AttributeExpression.ResultType) ReduceEvaluator(org.apache.nifi.attribute.expression.language.evaluation.reduce.ReduceEvaluator) AttributeExpressionLanguageParsingException(org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageParsingException) MappingEvaluator(org.apache.nifi.attribute.expression.language.evaluation.selection.MappingEvaluator)

Example 2 with AttributeExpressionLanguageException

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("");
}
Also used : StringQueryResult(org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult) AttributeExpressionLanguageException(org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException)

Example 3 with AttributeExpressionLanguageException

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()));
}
Also used : StringQueryResult(org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult) AttributeExpressionLanguageException(org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException) InvalidJsonException(com.jayway.jsonpath.InvalidJsonException) DocumentContext(com.jayway.jsonpath.DocumentContext) JsonPath(com.jayway.jsonpath.JsonPath) AttributeExpressionLanguageException(org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException) InvalidJsonException(com.jayway.jsonpath.InvalidJsonException)

Example 4 with AttributeExpressionLanguageException

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);
    }
}
Also used : AttributeExpressionLanguageException(org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException) NumberQueryResult(org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult) Method(java.lang.reflect.Method) InvocationTargetException(java.lang.reflect.InvocationTargetException)

Aggregations

AttributeExpressionLanguageException (org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException)4 StringQueryResult (org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult)2 DocumentContext (com.jayway.jsonpath.DocumentContext)1 InvalidJsonException (com.jayway.jsonpath.InvalidJsonException)1 JsonPath (com.jayway.jsonpath.JsonPath)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 BooleanEvaluator (org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator)1 NumberQueryResult (org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult)1 ReduceEvaluator (org.apache.nifi.attribute.expression.language.evaluation.reduce.ReduceEvaluator)1 AllAttributesEvaluator (org.apache.nifi.attribute.expression.language.evaluation.selection.AllAttributesEvaluator)1 AnyAttributeEvaluator (org.apache.nifi.attribute.expression.language.evaluation.selection.AnyAttributeEvaluator)1 MappingEvaluator (org.apache.nifi.attribute.expression.language.evaluation.selection.MappingEvaluator)1 MultiAttributeEvaluator (org.apache.nifi.attribute.expression.language.evaluation.selection.MultiAttributeEvaluator)1 AttributeExpressionLanguageParsingException (org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageParsingException)1 ResultType (org.apache.nifi.expression.AttributeExpression.ResultType)1