From f7b9343182046802988a5ecaf8540fe984995e06 Mon Sep 17 00:00:00 2001 From: jpercivall Date: Fri, 1 Apr 2016 18:36:30 -0400 Subject: [PATCH] NIFI-1662 Initial commit of adding Decimal and Math functions to Expression Language --- .../nifi/expression/AttributeExpression.java | 2 +- .../language/antlr/AttributeExpressionLexer.g | 11 + .../antlr/AttributeExpressionParser.g | 15 +- .../output/AttributeExpressionLexer.tokens | 141 +++++++------ .../attribute/expression/language/Query.java | 106 +++++++++- .../language/evaluation/DecimalEvaluator.java | 43 ++++ .../evaluation/DecimalQueryResult.java | 44 ++++ .../evaluation/cast/DateCastEvaluator.java | 2 + .../evaluation/cast/DecimalCastEvaluator.java | 119 +++++++++++ .../evaluation/cast/NumberCastEvaluator.java | 8 +- .../functions/DecimalToNumberEvaluator.java | 45 ++++ .../functions/DivideDecimalEvaluator.java | 57 +++++ .../GreaterThanDecimalEvaluator.java | 56 +++++ .../GreaterThanOrEqualDecimalEvaluator.java | 56 +++++ .../functions/LessThanDecimalEvaluator.java | 56 +++++ .../LessThanOrEqualDecimalEvaluator.java | 56 +++++ .../evaluation/functions/MathEvaluator.java | 106 ++++++++++ .../functions/MinusDecimalEvaluator.java | 57 +++++ .../functions/ModDecimalEvaluator.java | 57 +++++ .../functions/MultiplyDecimalEvaluator.java | 57 +++++ .../functions/NumberToDecimalEvaluator.java | 45 ++++ .../functions/PlusDecimalEvaluator.java | 57 +++++ .../expression/language/TestQuery.java | 73 ++++++- .../asciidoc/expression-language-guide.adoc | 198 +++++++++++++++++- 24 files changed, 1394 insertions(+), 73 deletions(-) create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/DecimalEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/DecimalQueryResult.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/DecimalCastEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/DecimalToNumberEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/DivideDecimalEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/GreaterThanDecimalEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/GreaterThanOrEqualDecimalEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/LessThanDecimalEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/LessThanOrEqualDecimalEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MathEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MinusDecimalEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/ModDecimalEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MultiplyDecimalEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/NumberToDecimalEvaluator.java create mode 100644 nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/PlusDecimalEvaluator.java diff --git a/nifi-api/src/main/java/org/apache/nifi/expression/AttributeExpression.java b/nifi-api/src/main/java/org/apache/nifi/expression/AttributeExpression.java index ed409ea2ad8f..ded24d8ca47b 100644 --- a/nifi-api/src/main/java/org/apache/nifi/expression/AttributeExpression.java +++ b/nifi-api/src/main/java/org/apache/nifi/expression/AttributeExpression.java @@ -70,6 +70,6 @@ public interface AttributeExpression { public static enum ResultType { - STRING, BOOLEAN, NUMBER, DATE; + STRING, BOOLEAN, NUMBER, DATE, DECIMAL; } } diff --git a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g index d56a27b19265..11ae8583c05c 100644 --- a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g +++ b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionLexer.g @@ -112,6 +112,7 @@ IS_NULL : 'isNull'; IS_EMPTY : 'isEmpty'; NOT_NULL : 'notNull'; TO_NUMBER : 'toNumber'; +TO_DECIMAL : 'toDecimal'; URL_ENCODE : 'urlEncode'; URL_DECODE : 'urlDecode'; NOT : 'not'; @@ -139,6 +140,10 @@ GREATER_THAN : 'gt'; LESS_THAN : 'lt'; GREATER_THAN_OR_EQUAL : 'ge'; LESS_THAN_OR_EQUAL : 'le'; +GREATER_THAN_DECIMAL : 'gtDecimal'; +LESS_THAN_DECIMAL : 'ltDecimal'; +GREATER_THAN_OR_EQUAL_DECIMAL : 'geDecimal'; +LESS_THAN_OR_EQUAL_DECIMAL : 'leDecimal'; FORMAT : 'format'; // takes string date format; uses SimpleDateFormat TO_DATE : 'toDate'; // takes string date format; converts the subject to a Long based on the date format MOD : 'mod'; @@ -147,6 +152,12 @@ MINUS : 'minus'; MULTIPLY : 'multiply'; DIVIDE : 'divide'; TO_RADIX : 'toRadix'; +MOD_DECIMAL : 'modDecimal'; +PLUS_DECIMAL : 'plusDecimal'; +MINUS_DECIMAL : 'minusDecimal'; +MULTIPLY_DECIMAL : 'multiplyDecimal'; +DIVIDE_DECIMAL : 'divideDecimal'; +MATH: 'math'; OR : 'or'; AND : 'and'; JOIN : 'join'; diff --git a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g index 780d8c5b952a..0d03bebd6434 100644 --- a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g +++ b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/AttributeExpressionParser.g @@ -86,7 +86,8 @@ zeroArgBool : (IS_NULL | NOT_NULL | IS_EMPTY | NOT) LPAREN! RPAREN!; oneArgBool : ((FIND | MATCHES | EQUALS_IGNORE_CASE) LPAREN! anyArg RPAREN!) | (GREATER_THAN | LESS_THAN | GREATER_THAN_OR_EQUAL | LESS_THAN_OR_EQUAL) LPAREN! anyArg RPAREN! | (EQUALS) LPAREN! anyArg RPAREN! | - (AND | OR) LPAREN! anyArg RPAREN!; + (AND | OR) LPAREN! anyArg RPAREN! | + (GREATER_THAN_DECIMAL | LESS_THAN_DECIMAL | GREATER_THAN_OR_EQUAL_DECIMAL | LESS_THAN_OR_EQUAL_DECIMAL) LPAREN! anyArg RPAREN!; // functions that return Numbers @@ -95,13 +96,21 @@ oneArgNum : ((INDEX_OF | LAST_INDEX_OF) LPAREN! anyArg RPAREN!) | (TO_DATE LPAREN! anyArg? RPAREN!) | ((MOD | PLUS | MINUS | MULTIPLY | DIVIDE) LPAREN! anyArg RPAREN!); + +// functions that return Decimals +zeroArgDec : (TO_DECIMAL) LPAREN! RPAREN!; +oneArgDec : ((MOD_DECIMAL | PLUS_DECIMAL | MINUS_DECIMAL | MULTIPLY_DECIMAL | DIVIDE_DECIMAL) LPAREN! anyArg RPAREN!)| + (MATH LPAREN! anyArg (COMMA! anyArg)? RPAREN!); + + stringFunctionRef : zeroArgString | oneArgString | twoArgString | fiveArgString; booleanFunctionRef : zeroArgBool | oneArgBool; numberFunctionRef : zeroArgNum | oneArgNum; +decimalFunctionRef : zeroArgDec | oneArgDec; -anyArg : NUMBER | numberFunctionRef | STRING_LITERAL | zeroArgString | oneArgString | twoArgString | fiveArgString | booleanLiteral | zeroArgBool | oneArgBool | expression; +anyArg : NUMBER | numberFunctionRef | decimalFunctionRef | STRING_LITERAL | zeroArgString | oneArgString | twoArgString | fiveArgString | booleanLiteral | zeroArgBool | oneArgBool | expression ; stringArg : STRING_LITERAL | zeroArgString | oneArgString | twoArgString | expression; -functionRef : stringFunctionRef | booleanFunctionRef | numberFunctionRef; +functionRef : stringFunctionRef | booleanFunctionRef | numberFunctionRef | decimalFunctionRef; diff --git a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/output/AttributeExpressionLexer.tokens b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/output/AttributeExpressionLexer.tokens index 0265bfb98291..9358dc63d994 100755 --- a/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/output/AttributeExpressionLexer.tokens +++ b/nifi-commons/nifi-expression-language/src/main/antlr3/org/apache/nifi/attribute/expression/language/antlr/output/AttributeExpressionLexer.tokens @@ -23,66 +23,83 @@ ANY_DELINEATED_VALUE=9 ANY_MATCHING_ATTRIBUTE=10 APPEND=11 ATTRIBUTE_NAME=12 -CEIL=13 -COLON=14 -COMMA=15 +COLON=13 +COMMA=14 +COMMENT=15 CONTAINS=16 -DIVIDE=17 -DOLLAR=18 -DOT=19 -ENDS_WITH=20 -EQUALS=21 -EQUALS_IGNORE_CASE=22 -FALSE=23 -FIND=24 -FLOOR=25 -FORMAT=26 -GREATER_THAN=27 -GREATER_THAN_OR_EQUAL=28 -HOSTNAME=29 -INDEX_OF=30 -IP=31 -IS_NULL=32 -LAST_INDEX_OF=33 -LBRACE=34 -LENGTH=35 -LESS_THAN=36 -LESS_THAN_OR_EQUAL=37 -LPAREN=38 -MATCHES=39 -MINUS=40 -MOD=41 -MULTIPLY=42 -NEXT_INT=43 -NOT=44 -NOT_NULL=45 -NOW=46 -NUMBER=47 -OR=48 -PLUS=49 -PREPEND=50 -RBRACE=51 -REPLACE=52 -REPLACE_ALL=53 -REPLACE_NULL=54 -RPAREN=55 -SEMICOLON=56 -STARTS_WITH=57 -STRING_LITERAL=58 -SUBSTRING=59 -SUBSTRING_AFTER=60 -SUBSTRING_AFTER_LAST=61 -SUBSTRING_BEFORE=62 -SUBSTRING_BEFORE_LAST=63 -TO_DATE=64 -TO_LOWER=65 -TO_NUMBER=66 -TO_RADIX=67 -TO_STRING=68 -TO_UPPER=69 -TRIM=70 -TRUE=71 -URL_DECODE=72 -URL_ENCODE=73 -UUID=74 -WHITESPACE=75 +COUNT=17 +DIVIDE=18 +DIVIDE_DECIMAL=19 +DOLLAR=20 +DOT=21 +ENDS_WITH=22 +EQUALS=23 +EQUALS_IGNORE_CASE=24 +ESC=25 +FALSE=26 +FIND=27 +FORMAT=28 +GET_DELIMITED_FIELD=29 +GREATER_THAN=30 +GREATER_THAN_DECIMAL=31 +GREATER_THAN_OR_EQUAL=32 +GREATER_THAN_OR_EQUAL_DECIMAL=33 +HOSTNAME=34 +INDEX_OF=35 +IP=36 +IS_EMPTY=37 +IS_NULL=38 +JOIN=39 +LAST_INDEX_OF=40 +LBRACE=41 +LENGTH=42 +LESS_THAN=43 +LESS_THAN_DECIMAL=44 +LESS_THAN_OR_EQUAL=45 +LESS_THAN_OR_EQUAL_DECIMAL=46 +LPAREN=47 +MATCHES=48 +MATH=49 +MINUS=50 +MINUS_DECIMAL=51 +MOD=52 +MOD_DECIMAL=53 +MULTIPLY=54 +MULTIPLY_DECIMAL=55 +NEXT_INT=56 +NOT=57 +NOT_NULL=58 +NOW=59 +NUMBER=60 +OR=61 +PLUS=62 +PLUS_DECIMAL=63 +PREPEND=64 +RBRACE=65 +REPLACE=66 +REPLACE_ALL=67 +REPLACE_EMPTY=68 +REPLACE_NULL=69 +RPAREN=70 +SEMICOLON=71 +STARTS_WITH=72 +STRING_LITERAL=73 +SUBSTRING=74 +SUBSTRING_AFTER=75 +SUBSTRING_AFTER_LAST=76 +SUBSTRING_BEFORE=77 +SUBSTRING_BEFORE_LAST=78 +TO_DATE=79 +TO_DECIMAL=80 +TO_LITERAL=81 +TO_LOWER=82 +TO_NUMBER=83 +TO_RADIX=84 +TO_STRING=85 +TO_UPPER=86 +TRIM=87 +TRUE=88 +URL_DECODE=89 +URL_ENCODE=90 +UUID=91 +WHITESPACE=92 \ No newline at end of file diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java index b3a364ae1cb3..025fbd704b30 100644 --- a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/Query.java @@ -31,12 +31,14 @@ import org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser; import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.DateEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; import org.apache.nifi.attribute.expression.language.evaluation.StringEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.cast.BooleanCastEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.cast.DateCastEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.cast.DecimalCastEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.cast.NumberCastEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.cast.StringCastEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.AndEvaluator; @@ -44,6 +46,8 @@ import org.apache.nifi.attribute.expression.language.evaluation.functions.AttributeEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.ContainsEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.DateToNumberEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.DecimalToNumberEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.DivideDecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.DivideEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.EndsWithEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.EqualsEvaluator; @@ -51,7 +55,9 @@ import org.apache.nifi.attribute.expression.language.evaluation.functions.FindEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.FormatEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.GetDelimitedFieldEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.GreaterThanDecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.GreaterThanEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.GreaterThanOrEqualDecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.GreaterThanOrEqualEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.HostnameEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.IPEvaluator; @@ -60,18 +66,26 @@ import org.apache.nifi.attribute.expression.language.evaluation.functions.IsNullEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.LastIndexOfEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.LengthEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.LessThanDecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.LessThanEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.LessThanOrEqualDecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.LessThanOrEqualEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.MatchesEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.MathEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.MinusDecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.MinusEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.ModDecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.ModEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.MultiplyDecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.MultiplyEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.NotEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.NotNullEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.NowEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.NumberToDateEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.NumberToDecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.OneUpSequenceEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.OrEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.functions.PlusDecimalEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.PlusEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.PrependEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.ReplaceAllEvaluator; @@ -86,7 +100,6 @@ import org.apache.nifi.attribute.expression.language.evaluation.functions.SubstringBeforeLastEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.SubstringEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.ToLowerEvaluator; -import org.apache.nifi.attribute.expression.language.evaluation.functions.ToNumberEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.ToRadixEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.ToStringEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.functions.ToUpperEvaluator; @@ -119,6 +132,16 @@ import org.antlr.runtime.CommonTokenStream; import org.antlr.runtime.tree.Tree; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer.DIVIDE_DECIMAL; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer.GREATER_THAN_DECIMAL; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer.GREATER_THAN_OR_EQUAL_DECIMAL; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer.LESS_THAN_DECIMAL; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer.LESS_THAN_OR_EQUAL_DECIMAL; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer.MATH; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer.MINUS_DECIMAL; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer.MOD_DECIMAL; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer.MULTIPLY_DECIMAL; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionLexer.PLUS_DECIMAL; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ALL_ATTRIBUTES; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ALL_DELINEATED_VALUES; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.ALL_MATCHING_ATTRIBUTES; @@ -177,6 +200,7 @@ import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.SUBSTRING_BEFORE; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.SUBSTRING_BEFORE_LAST; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_DATE; +import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_DECIMAL; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_LITERAL; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_LOWER; import static org.apache.nifi.attribute.expression.language.antlr.AttributeExpressionParser.TO_NUMBER; @@ -1040,12 +1064,34 @@ private static Evaluator toNumberEvaluator(final Evaluator evaluator, f return addToken(new NumberCastEvaluator(evaluator), evaluator.getToken()); case DATE: return addToken(new DateToNumberEvaluator((DateEvaluator) evaluator), evaluator.getToken()); + case DECIMAL: + return addToken(new NumberCastEvaluator(evaluator), evaluator.getToken()); default: throw new AttributeExpressionLanguageParsingException("Cannot implicitly convert Data Type " + evaluator.getResultType() + " to " + ResultType.NUMBER + (location == null ? "" : " at location [" + location + "]")); } } + private static Evaluator toDecimalEvaluator(final Evaluator evaluator) { + return toDecimalEvaluator(evaluator, null); + } + + @SuppressWarnings("unchecked") + private static Evaluator toDecimalEvaluator(final Evaluator evaluator, final String location) { + switch (evaluator.getResultType()) { + case DECIMAL: + return (Evaluator) evaluator; + case NUMBER: + return addToken(new DecimalCastEvaluator(evaluator), evaluator.getToken()); + case STRING: + return addToken(new DecimalCastEvaluator(evaluator), evaluator.getToken()); + case DATE: + default: + throw new AttributeExpressionLanguageParsingException("Cannot implicitly convert Data Type " + evaluator.getResultType() + " to " + ResultType.DECIMAL + + (location == null ? "" : " at location [" + location + "]")); + } + } + private static DateEvaluator toDateEvaluator(final Evaluator evaluator) { return toDateEvaluator(evaluator, null); } @@ -1222,6 +1268,26 @@ private static Evaluator buildFunctionEvaluator(final Tree tree, final Evalua return addToken(new LessThanOrEqualEvaluator(toNumberEvaluator(subjectEvaluator), toNumberEvaluator(argEvaluators.get(0), "first argument to le")), "le"); } + case GREATER_THAN_DECIMAL: { + verifyArgCount(argEvaluators, 1, "gtDecimal"); + return addToken(new GreaterThanDecimalEvaluator(toDecimalEvaluator(subjectEvaluator), + toDecimalEvaluator(argEvaluators.get(0), "first argument to gtDecimal")), "gtDecimal"); + } + case GREATER_THAN_OR_EQUAL_DECIMAL: { + verifyArgCount(argEvaluators, 1, "geDecimal"); + return addToken(new GreaterThanOrEqualDecimalEvaluator(toDecimalEvaluator(subjectEvaluator), + toDecimalEvaluator(argEvaluators.get(0), "first argument to geDecimal")), "geDecimal"); + } + case LESS_THAN_DECIMAL: { + verifyArgCount(argEvaluators, 1, "ltDecimal"); + return addToken(new LessThanDecimalEvaluator(toDecimalEvaluator(subjectEvaluator), + toDecimalEvaluator(argEvaluators.get(0), "first argument to ltDecimal")), "ltDecimal"); + } + case LESS_THAN_OR_EQUAL_DECIMAL: { + verifyArgCount(argEvaluators, 1, "leDecimal"); + return addToken(new LessThanOrEqualDecimalEvaluator(toDecimalEvaluator(subjectEvaluator), + toDecimalEvaluator(argEvaluators.get(0), "first argument to leDecimal")), "leDecimal"); + } case LENGTH: { verifyArgCount(argEvaluators, 0, "length"); return addToken(new LengthEvaluator(toStringEvaluator(subjectEvaluator)), "length"); @@ -1238,14 +1304,28 @@ private static Evaluator buildFunctionEvaluator(final Tree tree, final Evalua case TO_NUMBER: { verifyArgCount(argEvaluators, 0, "toNumber"); switch (subjectEvaluator.getResultType()) { + case DECIMAL: + return addToken(new DecimalToNumberEvaluator((DecimalEvaluator) subjectEvaluator), "toNumber"); case STRING: - return addToken(new ToNumberEvaluator((StringEvaluator) subjectEvaluator), "toNumber"); + return addToken(new NumberCastEvaluator(subjectEvaluator), "toNumber"); case DATE: return addToken(new DateToNumberEvaluator((DateEvaluator) subjectEvaluator), "toNumber"); default: throw new AttributeExpressionLanguageParsingException(subjectEvaluator + " returns type " + subjectEvaluator.getResultType() + " but expected to get " + ResultType.STRING); } } + case TO_DECIMAL: { + verifyArgCount(argEvaluators, 0, "toDecimal"); + switch (subjectEvaluator.getResultType()) { + case NUMBER: + return addToken(new NumberToDecimalEvaluator((NumberEvaluator) subjectEvaluator), "toNumber"); + case STRING: + return addToken(new DecimalCastEvaluator(subjectEvaluator), "toDecimal"); + case DATE: + default: + throw new AttributeExpressionLanguageParsingException(subjectEvaluator + " returns type " + subjectEvaluator.getResultType() + " but expected to get " + ResultType.STRING); + } + } case TO_RADIX: { if (argEvaluators.size() == 1) { return addToken(new ToRadixEvaluator((NumberEvaluator) subjectEvaluator, toNumberEvaluator(argEvaluators.get(0))), "toRadix"); @@ -1268,6 +1348,28 @@ private static Evaluator buildFunctionEvaluator(final Tree tree, final Evalua case DIVIDE: { return addToken(new DivideEvaluator(toNumberEvaluator(subjectEvaluator), toNumberEvaluator(argEvaluators.get(0))), "divide"); } + case PLUS_DECIMAL: { + return addToken(new PlusDecimalEvaluator(toDecimalEvaluator(subjectEvaluator), toDecimalEvaluator(argEvaluators.get(0))), "plusDecimal"); + } + case MINUS_DECIMAL: { + return addToken(new MinusDecimalEvaluator(toDecimalEvaluator(subjectEvaluator), toDecimalEvaluator(argEvaluators.get(0))), "minusDecimal"); + } + case MULTIPLY_DECIMAL: { + return addToken(new MultiplyDecimalEvaluator(toDecimalEvaluator(subjectEvaluator), toDecimalEvaluator(argEvaluators.get(0))), "multiplyDecimal"); + } + case DIVIDE_DECIMAL: { + return addToken(new DivideDecimalEvaluator(toDecimalEvaluator(subjectEvaluator), toDecimalEvaluator(argEvaluators.get(0))), "divideDecimal"); + } + case MOD_DECIMAL: { + return addToken(new ModDecimalEvaluator(toDecimalEvaluator(subjectEvaluator), toDecimalEvaluator(argEvaluators.get(0))), "modDecimal"); + } + case MATH: { + if (argEvaluators.size() == 1) { + return addToken(new MathEvaluator(toDecimalEvaluator(subjectEvaluator), toStringEvaluator(argEvaluators.get(0)), null), "math"); + } else { + return addToken(new MathEvaluator(toDecimalEvaluator(subjectEvaluator), toStringEvaluator(argEvaluators.get(0)), toDecimalEvaluator(argEvaluators.get(1))), "math"); + } + } case INDEX_OF: { verifyArgCount(argEvaluators, 1, "indexOf"); return addToken(new IndexOfEvaluator(toStringEvaluator(subjectEvaluator), diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/DecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/DecimalEvaluator.java new file mode 100644 index 000000000000..f41b9653e44f --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/DecimalEvaluator.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation; + +import org.apache.nifi.expression.AttributeExpression.ResultType; + +public abstract class DecimalEvaluator implements Evaluator { + private String token; + + @Override + public ResultType getResultType() { + return ResultType.DECIMAL; + } + + @Override + public int getEvaluationsRemaining() { + return 0; + } + + @Override + public String getToken() { + return token; + } + + @Override + public void setToken(final String token) { + this.token = token; + } +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/DecimalQueryResult.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/DecimalQueryResult.java new file mode 100644 index 000000000000..8a09bc12cae2 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/DecimalQueryResult.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation; + +import org.apache.nifi.expression.AttributeExpression.ResultType; + +public class DecimalQueryResult implements QueryResult { + + private final Double value; + + public DecimalQueryResult(final Double value) { + this.value = value; + } + + @Override + public Double getValue() { + return value; + } + + @Override + public ResultType getResultType() { + return ResultType.DECIMAL; + } + + @Override + public String toString() { + return String.valueOf(getValue()); + } +} + diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/DateCastEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/DateCastEvaluator.java index 96e74ef5986f..e31d409b3a28 100644 --- a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/DateCastEvaluator.java +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/DateCastEvaluator.java @@ -104,6 +104,8 @@ public QueryResult evaluate(final Map attributes) { } case NUMBER: return new DateQueryResult(new Date((Long) result.getValue())); + case DECIMAL: + return new DateQueryResult(new Date(((Double) result.getValue()).longValue())); default: return new DateQueryResult(null); } diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/DecimalCastEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/DecimalCastEvaluator.java new file mode 100644 index 000000000000..752b07ab2d1e --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/DecimalCastEvaluator.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.cast; + +import org.apache.nifi.attribute.expression.language.evaluation.DateQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.StringQueryResult; +import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageParsingException; +import org.apache.nifi.expression.AttributeExpression.ResultType; + +import java.util.Map; +import java.util.regex.Pattern; + +public class DecimalCastEvaluator extends DecimalEvaluator { + + private final Evaluator subjectEvaluator; + + + // Double regex according to Oracle documentation: http://docs.oracle.com/javase/6/docs/api/java/lang/Double.html#valueOf%28java.lang.String%29 + private static final String Digits = "(\\p{Digit}+)"; + private static final String HexDigits = "(\\p{XDigit}+)"; + // an exponent is 'e' or 'E' followed by an optionally + // signed decimal integer. + private static final String Exp = "[eE][+-]?"+Digits; + private static final String fpRegex = + ("[\\x00-\\x20]*"+ // Optional leading "whitespace" + "[+-]?(" + // Optional sign character + "NaN|" + // "NaN" string + "Infinity|" + // "Infinity" string + + // A decimal floating-point string representing a finite positive + // number without a leading sign has at most five basic pieces: + // Digits . Digits ExponentPart FloatTypeSuffix + // + // Since this method allows integer-only strings as input + // in addition to strings of floating-point literals, the + // two sub-patterns below are simplifications of the grammar + // productions from the Java Language Specification, 2nd + // edition, section 3.10.2. + + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt + "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ + + // . Digits ExponentPart_opt FloatTypeSuffix_opt + "(\\.("+Digits+")("+Exp+")?)|"+ + + // Hexadecimal strings + "((" + + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "(\\.)?)|" + + + // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt + "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + + + ")[pP][+-]?" + Digits + "))" + + "[fFdD]?))" + + "[\\x00-\\x20]*");// Optional trailing "whitespace" + protected static final Pattern DOUBLE_PATTERN = Pattern.compile(fpRegex); + + + + public DecimalCastEvaluator(final Evaluator subjectEvaluator) { + if (subjectEvaluator.getResultType() == ResultType.BOOLEAN) { + throw new AttributeExpressionLanguageParsingException("Cannot implicitly convert Data Type " + subjectEvaluator.getResultType() + " to " + ResultType.DECIMAL); + } + this.subjectEvaluator = subjectEvaluator; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final QueryResult result = subjectEvaluator.evaluate(attributes); + if (result.getValue() == null) { + return new DecimalQueryResult(null); + } + + switch (result.getResultType()) { + case NUMBER: + return new DecimalQueryResult(((Long) result.getValue()).doubleValue()); + case DECIMAL: + return (DecimalQueryResult) result; + case STRING: + final String trimmed = ((StringQueryResult) result).getValue().trim(); + if (DOUBLE_PATTERN.matcher(trimmed).matches()) { + return new DecimalQueryResult(Double.valueOf(trimmed)); + } else if (NumberCastEvaluator.NUMBER_PATTERN.matcher(trimmed).matches()){ + return new DecimalQueryResult(Long.valueOf(trimmed).doubleValue()); + } else { + return new DecimalQueryResult(null); + } + case DATE: + return new DecimalQueryResult((double) ((DateQueryResult) result).getValue().getTime()); + default: + return new DecimalQueryResult(null); + } + } + + @Override + public Evaluator getSubjectEvaluator() { + return subjectEvaluator; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/NumberCastEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/NumberCastEvaluator.java index 0447d483a8e5..f68ad63202a4 100644 --- a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/NumberCastEvaluator.java +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/cast/NumberCastEvaluator.java @@ -20,6 +20,7 @@ import java.util.regex.Pattern; import org.apache.nifi.attribute.expression.language.evaluation.DateQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalQueryResult; import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator; import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult; @@ -31,7 +32,7 @@ public class NumberCastEvaluator extends NumberEvaluator { private final Evaluator subjectEvaluator; - private static final Pattern NUMBER_PATTERN = Pattern.compile("-?\\d+"); + protected static final Pattern NUMBER_PATTERN = Pattern.compile("-?\\d+"); public NumberCastEvaluator(final Evaluator subjectEvaluator) { if (subjectEvaluator.getResultType() == ResultType.BOOLEAN) { @@ -50,10 +51,15 @@ public QueryResult evaluate(final Map attributes) { switch (result.getResultType()) { case NUMBER: return (NumberQueryResult) result; + case DECIMAL: + final Double value = ((DecimalQueryResult) result).getValue(); + return new NumberQueryResult(value.longValue()); case STRING: final String trimmed = ((StringQueryResult) result).getValue().trim(); if (NUMBER_PATTERN.matcher(trimmed).matches()) { return new NumberQueryResult(Long.valueOf(trimmed)); + } else if (DecimalCastEvaluator.DOUBLE_PATTERN.matcher(trimmed).matches()){ + return new NumberQueryResult(Double.valueOf(trimmed).longValue()); } else { return new NumberQueryResult(null); } diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/DecimalToNumberEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/DecimalToNumberEvaluator.java new file mode 100644 index 000000000000..e0b7907c1ef2 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/DecimalToNumberEvaluator.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.NumberEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.NumberQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class DecimalToNumberEvaluator extends NumberEvaluator { + + private final Evaluator subject; + + public DecimalToNumberEvaluator(final Evaluator subject) { + this.subject = subject; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Double subjectValue = subject.evaluate(attributes).getValue(); + return new NumberQueryResult(subjectValue == null ? null : subjectValue.longValue()); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/DivideDecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/DivideDecimalEvaluator.java new file mode 100644 index 000000000000..1112c435a139 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/DivideDecimalEvaluator.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.DecimalEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class DivideDecimalEvaluator extends DecimalEvaluator { + + private final Evaluator subject; + private final Evaluator divideValue; + + public DivideDecimalEvaluator(final Evaluator subject, final Evaluator divideValue) { + this.subject = subject; + this.divideValue = divideValue; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Double subjectValue = subject.evaluate(attributes).getValue(); + if (subjectValue == null) { + return new DecimalQueryResult(null); + } + + final Double divide = divideValue.evaluate(attributes).getValue(); + if (divide == null) { + return new DecimalQueryResult(null); + } + + final Double result = subjectValue / divide; + return new DecimalQueryResult(result); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/GreaterThanDecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/GreaterThanDecimalEvaluator.java new file mode 100644 index 000000000000..d21149de3970 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/GreaterThanDecimalEvaluator.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class GreaterThanDecimalEvaluator extends BooleanEvaluator { + + private final Evaluator subject; + private final Evaluator comparison; + + public GreaterThanDecimalEvaluator(final Evaluator subject, final Evaluator comparison) { + this.subject = subject; + this.comparison = comparison; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Double subjectValue = subject.evaluate(attributes).getValue(); + if (subjectValue == null) { + return new BooleanQueryResult(false); + } + + final Double comparisonValue = comparison.evaluate(attributes).getValue(); + if (comparisonValue == null) { + return new BooleanQueryResult(false); + } + + return new BooleanQueryResult(subjectValue > comparisonValue); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/GreaterThanOrEqualDecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/GreaterThanOrEqualDecimalEvaluator.java new file mode 100644 index 000000000000..69650307d8f7 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/GreaterThanOrEqualDecimalEvaluator.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class GreaterThanOrEqualDecimalEvaluator extends BooleanEvaluator { + + private final Evaluator subject; + private final Evaluator comparison; + + public GreaterThanOrEqualDecimalEvaluator(final Evaluator subject, final Evaluator comparison) { + this.subject = subject; + this.comparison = comparison; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Double subjectValue = subject.evaluate(attributes).getValue(); + if (subjectValue == null) { + return new BooleanQueryResult(false); + } + + final Double comparisonValue = comparison.evaluate(attributes).getValue(); + if (comparisonValue == null) { + return new BooleanQueryResult(false); + } + + return new BooleanQueryResult(subjectValue >= comparisonValue); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/LessThanDecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/LessThanDecimalEvaluator.java new file mode 100644 index 000000000000..d824d868b469 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/LessThanDecimalEvaluator.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class LessThanDecimalEvaluator extends BooleanEvaluator { + + private final Evaluator subject; + private final Evaluator comparison; + + public LessThanDecimalEvaluator(final Evaluator subject, final Evaluator comparison) { + this.subject = subject; + this.comparison = comparison; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Double subjectValue = subject.evaluate(attributes).getValue(); + if (subjectValue == null) { + return new BooleanQueryResult(false); + } + + final Double comparisonValue = comparison.evaluate(attributes).getValue(); + if (comparisonValue == null) { + return new BooleanQueryResult(false); + } + + return new BooleanQueryResult(subjectValue < comparisonValue); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/LessThanOrEqualDecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/LessThanOrEqualDecimalEvaluator.java new file mode 100644 index 000000000000..83c49170eb36 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/LessThanOrEqualDecimalEvaluator.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.BooleanEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.BooleanQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class LessThanOrEqualDecimalEvaluator extends BooleanEvaluator { + + private final Evaluator subject; + private final Evaluator comparison; + + public LessThanOrEqualDecimalEvaluator(final Evaluator subject, final Evaluator comparison) { + this.subject = subject; + this.comparison = comparison; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Double subjectValue = subject.evaluate(attributes).getValue(); + if (subjectValue == null) { + return new BooleanQueryResult(false); + } + + final Double comparisonValue = comparison.evaluate(attributes).getValue(); + if (comparisonValue == null) { + return new BooleanQueryResult(false); + } + + return new BooleanQueryResult(subjectValue <= comparisonValue); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MathEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MathEvaluator.java new file mode 100644 index 000000000000..1dbcf6048d15 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MathEvaluator.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.DecimalEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; +import org.apache.nifi.attribute.expression.language.exception.AttributeExpressionLanguageException; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; + +public class MathEvaluator extends DecimalEvaluator { + + private final Evaluator subject; + private final Evaluator methodName; + private final Evaluator optionalDecimal; + + public MathEvaluator(final Evaluator subject, final Evaluator methodName, final Evaluator optionalDecimal) { + this.subject = subject; + this.methodName = methodName; + this.optionalDecimal = optionalDecimal; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final String methodNamedValue = methodName.evaluate(attributes).getValue(); + if (methodNamedValue == null) { + return new DecimalQueryResult(null); + } + + final Double subjectValue; + if(subject != null) { + subjectValue = subject.evaluate(attributes).getValue(); + if(subjectValue == null){ + throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because the subject evaluated to be null."); + } + } else { + throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because the subject was null."); + } + + final Double optionalDecimalValue; + if(optionalDecimal != null) { + optionalDecimalValue = optionalDecimal.evaluate(attributes).getValue(); + + if(optionalDecimalValue == null) { + throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because the second argument evaluated to be null. " + + "If a function with only one argument is desired to run (like 'sqrt') only pass pass the name of the method to 'math'."); + } + } else { + optionalDecimalValue = null; + } + + try { + Double executionValue = null; + + if(optionalDecimal == null) { + Method method = Math.class.getMethod(methodNamedValue, double.class); + + if(method == null) { + throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because no method was found matching the passed parameters:" + + " name:'"+methodNamedValue+"' and one double argument."); + } + + executionValue = (Double) method.invoke(null, (double) subjectValue); + + } else { + + Method method = Math.class.getMethod(methodNamedValue, double.class, double.class); + + if(method == null) { + throw new AttributeExpressionLanguageException("Cannot evaluate 'math' function because no method was found matching the passed parameters: " + + "name:'"+methodNamedValue+"' and two double arguments."); + } + + executionValue = (Double) method.invoke(null, (double) subjectValue, (double) optionalDecimalValue); + } + + return new DecimalQueryResult(executionValue); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + return new DecimalQueryResult(null); + } + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MinusDecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MinusDecimalEvaluator.java new file mode 100644 index 000000000000..61ece0747cd4 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MinusDecimalEvaluator.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.DecimalEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class MinusDecimalEvaluator extends DecimalEvaluator { + + private final Evaluator subject; + private final Evaluator minusValue; + + public MinusDecimalEvaluator(final Evaluator subject, final Evaluator minusValue) { + this.subject = subject; + this.minusValue = minusValue; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Double subjectValue = subject.evaluate(attributes).getValue(); + if (subjectValue == null) { + return new DecimalQueryResult(null); + } + + final Double minus = minusValue.evaluate(attributes).getValue(); + if (minus == null) { + return new DecimalQueryResult(null); + } + + final double result = subjectValue - minus; + return new DecimalQueryResult(result); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/ModDecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/ModDecimalEvaluator.java new file mode 100644 index 000000000000..4db4dfdef3f5 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/ModDecimalEvaluator.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.DecimalEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class ModDecimalEvaluator extends DecimalEvaluator { + + private final Evaluator subject; + private final Evaluator modValue; + + public ModDecimalEvaluator(final Evaluator subject, final Evaluator modValue) { + this.subject = subject; + this.modValue = modValue; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Double subjectValue = subject.evaluate(attributes).getValue(); + if (subjectValue == null) { + return new DecimalQueryResult(null); + } + + final Double mod = modValue.evaluate(attributes).getValue(); + if (mod == null) { + return new DecimalQueryResult(null); + } + + final double result = subjectValue % mod; + return new DecimalQueryResult(result); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MultiplyDecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MultiplyDecimalEvaluator.java new file mode 100644 index 000000000000..4b511e4ef0e9 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/MultiplyDecimalEvaluator.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.DecimalEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class MultiplyDecimalEvaluator extends DecimalEvaluator { + + private final Evaluator subject; + private final Evaluator multiplyValue; + + public MultiplyDecimalEvaluator(final Evaluator subject, final Evaluator multiplyValue) { + this.subject = subject; + this.multiplyValue = multiplyValue; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Double subjectValue = subject.evaluate(attributes).getValue(); + if (subjectValue == null) { + return new DecimalQueryResult(null); + } + + final Double multiply = multiplyValue.evaluate(attributes).getValue(); + if (multiply == null) { + return new DecimalQueryResult(null); + } + + final double result = subjectValue * multiply; + return new DecimalQueryResult(result); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/NumberToDecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/NumberToDecimalEvaluator.java new file mode 100644 index 000000000000..1711e8aa5e00 --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/NumberToDecimalEvaluator.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.DecimalEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class NumberToDecimalEvaluator extends DecimalEvaluator { + + private final Evaluator subject; + + public NumberToDecimalEvaluator(final Evaluator subject) { + this.subject = subject; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Long subjectValue = subject.evaluate(attributes).getValue(); + return new DecimalQueryResult(subjectValue == null ? null : Double.valueOf(subjectValue)); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/PlusDecimalEvaluator.java b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/PlusDecimalEvaluator.java new file mode 100644 index 000000000000..d557cd19170a --- /dev/null +++ b/nifi-commons/nifi-expression-language/src/main/java/org/apache/nifi/attribute/expression/language/evaluation/functions/PlusDecimalEvaluator.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.attribute.expression.language.evaluation.functions; + +import org.apache.nifi.attribute.expression.language.evaluation.DecimalEvaluator; +import org.apache.nifi.attribute.expression.language.evaluation.DecimalQueryResult; +import org.apache.nifi.attribute.expression.language.evaluation.Evaluator; +import org.apache.nifi.attribute.expression.language.evaluation.QueryResult; + +import java.util.Map; + +public class PlusDecimalEvaluator extends DecimalEvaluator { + + private final Evaluator subject; + private final Evaluator plusValue; + + public PlusDecimalEvaluator(final Evaluator subject, final Evaluator plusValue) { + this.subject = subject; + this.plusValue = plusValue; + } + + @Override + public QueryResult evaluate(final Map attributes) { + final Double subjectValue = subject.evaluate(attributes).getValue(); + if (subjectValue == null) { + return new DecimalQueryResult(null); + } + + final Double plus = plusValue.evaluate(attributes).getValue(); + if (plus == null) { + return new DecimalQueryResult(null); + } + + final double result = subjectValue + plus; + return new DecimalQueryResult(result); + } + + @Override + public Evaluator getSubjectEvaluator() { + return subject; + } + +} diff --git a/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java b/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java index 751a0acce0a6..3aa4a603826f 100644 --- a/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java +++ b/nifi-commons/nifi-expression-language/src/test/java/org/apache/nifi/attribute/expression/language/TestQuery.java @@ -727,6 +727,75 @@ public void testMathOperations() { verifyEquals("${hundred:toNumber():multiply(2):divide(3):plus(1):mod(5)}", attributes, 2L); } + @Test + public void testDecimalMathOperations() { + final Map attributes = new HashMap<>(); + attributes.put("one", "1.1"); + attributes.put("two", "2.2"); + attributes.put("three", "3.3"); + attributes.put("four", "4.4"); + attributes.put("hundred", "100.001"); + attributes.put("exactOne", "1"); + + verifyEquals("${hundred:toDecimal():multiplyDecimal(${one}):divideDecimal(${two}):plusDecimal(${three}):minusDecimal(${four})}", attributes, 48.9005); + // Example of Double's loss of precision + verifyEquals("${one:modDecimal('0.9')}", attributes, 0.20000000000000007); + + verifyEquals("${exactOne:toDecimal()}", attributes, 1D); + verifyEquals("${one:toNumber()}", attributes, 1L); + + } + + @Test + public void testStaticMathOperations() { + final Map attributes = new HashMap<>(); + attributes.put("negative", "-1"); + attributes.put("two", "2"); + attributes.put("one.two", "1.2984581213888124"); + attributes.put("tiny", "5.577469913807151E-4"); + attributes.put("otherFormat", "1.5304136440e+1"); + + verifyEquals("${otherFormat:math('sqrt')}", attributes, 3.9120501581651532); + verifyEquals("${tiny:math('sqrt')}", attributes, 0.023616667660377386); + + verifyEquals("${negative:math('abs')}", attributes, 1.0); + verifyEquals("${two:math('pow',${two})}", attributes, 4.0); + verifyEquals("${two:math('pow',2)}", attributes, 4.0); + verifyEquals("${two:math('pow','2.0')}", attributes, 4.0); + verifyEquals("${negative:plusDecimal(${two:math('pow','2.0')})}", attributes, 3.0); + verifyEquals("${one.two:math('sqrt')}", attributes, 1.139499065988565); + } + + @Test + public void testDecimalLogicOperations() { + final Map attributes = new HashMap<>(); + attributes.put("one", "1.1"); + attributes.put("two", "2.2"); + attributes.put("one_2", "1.1"); + + /*verifyEquals("${one:toNumber()}",attributes, 1);//(${two})}", attributes, true); + verifyEquals("${one:lt(${one_2})}", attributes, false); + verifyEquals("${two:lt(${one})}", attributes, false);*/ + + verifyEquals("${one:ltDecimal(${two})}", attributes, true); + verifyEquals("${one:ltDecimal(${one_2})}", attributes, false); + verifyEquals("${two:ltDecimal(${one})}", attributes, false); + + + verifyEquals("${one:leDecimal(${two})}", attributes, true); + verifyEquals("${one:leDecimal(${one_2})}", attributes, true); + verifyEquals("${two:leDecimal(${one_2})}", attributes, false); + + verifyEquals("${one:geDecimal(${two})}", attributes, false); + verifyEquals("${one:geDecimal(${one_2})}", attributes, true); + verifyEquals("${two:geDecimal(${one_2})}", attributes, true); + + verifyEquals("${one:gtDecimal(${two})}", attributes, false); + verifyEquals("${one:gtDecimal(${one_2})}", attributes, false); + verifyEquals("${two:gtDecimal(${one})}", attributes, true); + } + + @Test public void testIndexOf() { final Map attributes = new HashMap<>(); @@ -1234,10 +1303,12 @@ private void verifyEquals(final String expression, final Map att final Query query = Query.compile(expression); final QueryResult result = query.evaluate(attributes); - if (expectedResult instanceof Number) { + if (expectedResult instanceof Long) { assertEquals(ResultType.NUMBER, result.getResultType()); } else if (expectedResult instanceof Boolean) { assertEquals(ResultType.BOOLEAN, result.getResultType()); + } else if (expectedResult instanceof Double) { + assertEquals(ResultType.DECIMAL, result.getResultType()); } else { assertEquals(ResultType.STRING, result.getResultType()); } diff --git a/nifi-docs/src/main/asciidoc/expression-language-guide.adoc b/nifi-docs/src/main/asciidoc/expression-language-guide.adoc index a78c559fad18..e9e7e93e33b6 100644 --- a/nifi-docs/src/main/asciidoc/expression-language-guide.adoc +++ b/nifi-docs/src/main/asciidoc/expression-language-guide.adoc @@ -192,13 +192,18 @@ Language supports four different data types: - *Number*: A Number is an integer comprised of one or more digits (`0` through `9`). The Expression Language does not provide support for fractional numbers. When converting to numbers from Date data types, they are represented as the number of milliseconds since midnight GMT on January 1, 1970. +- *Decimal*: A Decimal is a numeric value that can support decimals and larger values with minimal loss of precision. More precisely it + is a double-precision 64-bit IEEE 754 floating point. Due to this minimal loss of precision this data type should not be used for + very precise values, such as currency. For more documentation on the range of values stored in this data type + refer to this https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.3[link]. Decimals cannot be expressed as literals + when inputting an Expression Language function. They be input as Strings using single quotes, like so: '1.1'. - *Date*: A Date is an object that holds a Date and Time. Utilizing the <> and <> functions this data type can be converted to/from Strings and numbers. If the whole Expression Language expression is evaluated to be a date then it will be converted to a String with the format: " ::