Skip to content

Commit ae2e66f

Browse files
committed
Introduce getValueType(ValueEvaluationContext) to ValueExpression.
Closes #3169
1 parent 83a7ee5 commit ae2e66f

File tree

6 files changed

+65
-7
lines changed

6 files changed

+65
-7
lines changed

src/main/java/org/springframework/data/expression/CompositeValueExpression.java

+6
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,10 @@ public String evaluate(ValueEvaluationContext context) {
7272

7373
return builder.toString();
7474
}
75+
76+
@Override
77+
public Class<?> getValueType(ValueEvaluationContext context) {
78+
return String.class;
79+
}
80+
7581
}

src/main/java/org/springframework/data/expression/ExpressionExpression.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,14 @@ public boolean isLiteral() {
4747
public Object evaluate(ValueEvaluationContext context) {
4848

4949
EvaluationContext evaluationContext = context.getEvaluationContext();
50-
if (evaluationContext != null) {
51-
return expression.getValue(evaluationContext);
52-
}
53-
return expression.getValue();
50+
return evaluationContext != null ? expression.getValue(evaluationContext) : expression.getValue();
5451
}
52+
53+
@Override
54+
public Class<?> getValueType(ValueEvaluationContext context) {
55+
56+
EvaluationContext evaluationContext = context.getEvaluationContext();
57+
return evaluationContext != null ? expression.getValueType(evaluationContext) : expression.getValueType();
58+
}
59+
5560
}

src/main/java/org/springframework/data/expression/LiteralValueExpression.java

+5
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,9 @@ public String evaluate(ValueEvaluationContext context) {
3939
return expression;
4040
}
4141

42+
@Override
43+
public Class<?> getValueType(ValueEvaluationContext context) {
44+
return String.class;
45+
}
46+
4247
}

src/main/java/org/springframework/data/expression/PlaceholderExpression.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public boolean isLiteral() {
3838
}
3939

4040
@Override
41-
public Object evaluate(ValueEvaluationContext context) {
41+
public String evaluate(ValueEvaluationContext context) {
4242

4343
Environment environment = context.getEnvironment();
4444
if (environment != null) {
@@ -51,4 +51,9 @@ public Object evaluate(ValueEvaluationContext context) {
5151
return expression;
5252
}
5353

54+
@Override
55+
public Class<?> getValueType(ValueEvaluationContext context) {
56+
return String.class;
57+
}
58+
5459
}

src/main/java/org/springframework/data/expression/ValueExpression.java

+11
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,15 @@ default ExpressionDependencies getExpressionDependencies() {
6262
@Nullable
6363
Object evaluate(ValueEvaluationContext context) throws EvaluationException;
6464

65+
/**
66+
* Return the most general type that the expression would use as return type for the given context.
67+
*
68+
* @param context the context in which to evaluate the expression.
69+
* @return the most general type of value.
70+
* @throws EvaluationException if there is a problem determining the type
71+
* @since 3.4
72+
*/
73+
@Nullable
74+
Class<?> getValueType(ValueEvaluationContext context) throws EvaluationException;
75+
6576
}

src/test/java/org/springframework/data/expression/ValueEvaluationUnitTests.java

+28-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.util.Map;
2121

22+
import org.jetbrains.annotations.Nullable;
2223
import org.junit.jupiter.api.BeforeEach;
2324
import org.junit.jupiter.api.Test;
2425

@@ -38,6 +39,7 @@
3839
*/
3940
public class ValueEvaluationUnitTests {
4041

42+
private ValueExpressionParser parser = ValueExpressionParser.create();
4143
private ValueEvaluationContext evaluationContext;
4244

4345
@BeforeEach
@@ -47,6 +49,10 @@ void setUp() {
4749
StandardEnvironment environment = new StandardEnvironment();
4850
environment.getPropertySources().addFirst(propertySource);
4951

52+
record MyRecord(String foo, @org.springframework.lang.Nullable String bar) {
53+
54+
}
55+
5056
this.evaluationContext = new ValueEvaluationContext() {
5157
@Override
5258
public Environment getEnvironment() {
@@ -57,6 +63,8 @@ public Environment getEnvironment() {
5763
public EvaluationContext getEvaluationContext() {
5864
StandardEvaluationContext context = new StandardEvaluationContext();
5965
context.setVariable("contextVar", "contextVal");
66+
context.setVariable("nullVar", null);
67+
context.setVariable("someRecord", new MyRecord("foo", null));
6068

6169
return context;
6270
}
@@ -82,6 +90,20 @@ void shouldParseAndEvaluateExpressions() {
8290
.withMessageContaining("Could not resolve placeholder 'env.does.not.exist'");
8391
}
8492

93+
@Test // GH-3169
94+
void shouldReturnValueType() {
95+
96+
assertThat(getValueType("foo")).isEqualTo(String.class);
97+
assertThat(getValueType("${env.key.one}")).isEqualTo(String.class);
98+
assertThat(getValueType("#{'foo'}")).isEqualTo(String.class);
99+
assertThat(getValueType("#{1+1}")).isEqualTo(Integer.class);
100+
assertThat(getValueType("#{null}")).isNull();
101+
assertThat(getValueType("#{#contextVar}")).isEqualTo(String.class);
102+
assertThat(getValueType("#{#nullVar}")).isNull();
103+
assertThat(getValueType("#{#someRecord.foo}")).isEqualTo(String.class);
104+
assertThat(getValueType("#{#someRecord.bar}")).isEqualTo(String.class);
105+
}
106+
85107
@Test // GH-2369
86108
void shouldParseLiteral() {
87109

@@ -128,10 +150,14 @@ void shouldParseQuoted() {
128150
assertThat(eval("#{(1+1) + \"-foo'}\" + '-bar}'}")).isEqualTo("2-foo'}-bar}");
129151
}
130152

153+
@SuppressWarnings("DataFlowIssue")
131154
private String eval(String expressionString) {
132-
133-
ValueExpressionParser parser = ValueExpressionParser.create();
134155
return (String) parser.parse(expressionString).evaluate(evaluationContext);
135156
}
136157

158+
@Nullable
159+
private Class<?> getValueType(String expressionString) {
160+
return parser.parse(expressionString).getValueType(evaluationContext);
161+
}
162+
137163
}

0 commit comments

Comments
 (0)