This is an automated email from the ASF dual-hosted git repository.
pvillard pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 1191b9254f NIFI-14873 - Support unquoted parameter references with
spaces in their names within expression language
1191b9254f is described below
commit 1191b9254fbbc6590bbe2c150b2478ef193cfce9
Author: Rob Fellows <[email protected]>
AuthorDate: Mon Aug 18 13:38:52 2025 -0400
NIFI-14873 - Support unquoted parameter references with spaces in their
names within expression language
Signed-off-by: Pierre Villard <[email protected]>
This closes #10215.
---
.../language/antlr/AttributeExpressionLexer.g | 25 ++++++++++++++++++++++
.../language/antlr/AttributeExpressionParser.g | 13 +++++++++--
.../attribute/expression/language/TestQuery.java | 8 +++++++
3 files changed, 44 insertions(+), 2 deletions(-)
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 3b62311334..0905f4119a 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
@@ -69,6 +69,31 @@ WHITESPACE : (' '|'\t'|'\n'|'\r')+ { $channel = HIDDEN; };
COMMENT : '#' ( ~('{') ) ( ~('\n') )* '\n' { $channel = HIDDEN; };
// PARAMETERS
+// Capture the entire parameter reference (e.g., #{Batch Size}) as a single
token so that
+// parameter names may contain spaces without requiring quotes. The lexer
action normalizes
+// the token text to contain only the inner parameter name (without the
surrounding "#{" and
+// "}"), and if the inner text itself is quoted (e.g., #{"Batch Size"}), the
surrounding quotes
+// are also stripped. This preserves backward compatibility and ensures the
parser/AST consumer
+// (ExpressionCompiler) receives a consistent parameter name string.
+PARAMETER_REFERENCE
+ : '#{' (~('}'))+ '}'
+ {
+ final String full = getText();
+ if (full != null && full.length() >= 3) {
+ String inner = full.substring(2, full.length() - 1);
+ if (inner.length() >= 2) {
+ final char first = inner.charAt(0);
+ final char last = inner.charAt(inner.length() - 1);
+ if ((first == '\'' && last == '\'') || (first == '"' && last
== '"')) {
+ inner = inner.substring(1, inner.length() - 1);
+ }
+ }
+ setText(inner);
+ }
+ }
+ ;
+// Retained for legacy form where the parameter name is parsed as a separate
token sequence
+// (e.g., #{'Batch Size'}) and rewritten by the parser rule below.
PARAMETER_REFERENCE_START : '#{';
DOLLAR : '$';
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 4533d250f1..6c8226eda5 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
@@ -145,8 +145,17 @@ attributeRefOrFunctionCall : (attributeRef |
standaloneFunction | parameterRefer
referenceOrFunction : DOLLAR LBRACE attributeRefOrFunctionCall (COLON
functionCall)* RBRACE ->
^(EXPRESSION attributeRefOrFunctionCall functionCall*);
-parameterReference : PARAMETER_REFERENCE_START singleAttrRef RBRACE ->
- ^(PARAMETER_REFERENCE singleAttrRef);
+// Parameter reference rule
+// Supports two forms:
+// 1) Legacy: "#{" singleAttrRef "}" where the name is either ATTRIBUTE_NAME
or STRING_LITERAL
+// 2) New: a single PARAMETER_REFERENCE token produced by the lexer that
already contains the
+// normalized inner name (surrounding #{ } removed and optional inner
quotes stripped).
+// Both forms are rewritten to the same AST shape: ^(PARAMETER_REFERENCE
<child-token-with-name>)
+// so downstream consumers (ExpressionCompiler) can read child(0).getText()
for the parameter name.
+parameterReference
+ : PARAMETER_REFERENCE_START singleAttrRef RBRACE -> ^(PARAMETER_REFERENCE
singleAttrRef)
+ | p=PARAMETER_REFERENCE -> ^(PARAMETER_REFERENCE $p)
+ ;
expression : referenceOrFunction;
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 07beec7196..30eeb8160c 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
@@ -447,6 +447,14 @@ public class TestQuery {
verifyEquals("${#{'test param'}:append(' - '):append(#{'test
param'})}", attributes, stateValues, parameters, "unit - unit");
verifyEquals("${#{\"test param\"}}", attributes, stateValues,
parameters, "unit");
+
+ // Unquoted parameter reference with spaces should also work
+ verifyEquals("${#{test param}}", attributes, stateValues, parameters,
"unit");
+
+ // Unquoted parameter used within a function argument
+ parameters.put("Date Format", "yyyy");
+ final String expectedYear =
String.valueOf(java.time.LocalDate.now().getYear());
+ verifyEquals("${now():format(#{Date Format})}", attributes,
stateValues, parameters, expectedYear);
}
@Test