Polishing
This commit is contained in:
parent
f295def2a8
commit
347d085020
|
|
@ -13,7 +13,7 @@ Java::
|
|||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
// evaluates to ["SmilJan", "Idvor"]
|
||||
// evaluates to ["Smiljan", "Idvor"]
|
||||
List placesOfBirth = parser.parseExpression("members.![placeOfBirth.city]")
|
||||
.getValue(societyContext, List.class);
|
||||
----
|
||||
|
|
@ -22,7 +22,7 @@ Kotlin::
|
|||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
// evaluates to ["SmilJan", "Idvor"]
|
||||
// evaluates to ["Smiljan", "Idvor"]
|
||||
val placesOfBirth = parser.parseExpression("members.![placeOfBirth.city]")
|
||||
.getValue(societyContext) as List<*>
|
||||
----
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
[[expressions-operator-safe-navigation]]
|
||||
= Safe Navigation Operator
|
||||
|
||||
The safe navigation operator is used to avoid a `NullPointerException` and comes from
|
||||
the https://www.groovy-lang.org/operators.html#_safe_navigation_operator[Groovy]
|
||||
language. Typically, when you have a reference to an object, you might need to verify that
|
||||
it is not null before accessing methods or properties of the object. To avoid this, the
|
||||
safe navigation operator returns null instead of throwing an exception. The following
|
||||
example shows how to use the safe navigation operator:
|
||||
The safe navigation operator (`?`) is used to avoid a `NullPointerException` and comes
|
||||
from the https://www.groovy-lang.org/operators.html#_safe_navigation_operator[Groovy]
|
||||
language. Typically, when you have a reference to an object, you might need to verify
|
||||
that it is not `null` before accessing methods or properties of the object. To avoid
|
||||
this, the safe navigation operator returns `null` instead of throwing an exception.
|
||||
|
||||
The following example shows how to use the safe navigation operator for property access
|
||||
(`?.`).
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
|
@ -20,13 +22,18 @@ Java::
|
|||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
|
||||
|
||||
String city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String.class);
|
||||
System.out.println(city); // Smiljan
|
||||
// evaluates to "Smiljan"
|
||||
String city = parser.parseExpression("placeOfBirth?.city") // <1>
|
||||
.getValue(context, tesla, String.class);
|
||||
|
||||
tesla.setPlaceOfBirth(null);
|
||||
city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String.class);
|
||||
System.out.println(city); // null - does not throw NullPointerException!!!
|
||||
|
||||
// evaluates to null - does not throw NullPointerException
|
||||
city = parser.parseExpression("placeOfBirth?.city") // <2>
|
||||
.getValue(context, tesla, String.class);
|
||||
----
|
||||
<1> Use safe navigation operator on non-null `placeOfBirth` property
|
||||
<2> Use safe navigation operator on null `placeOfBirth` property
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
|
|
@ -38,14 +45,17 @@ Kotlin::
|
|||
val tesla = Inventor("Nikola Tesla", "Serbian")
|
||||
tesla.setPlaceOfBirth(PlaceOfBirth("Smiljan"))
|
||||
|
||||
var city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String::class.java)
|
||||
println(city) // Smiljan
|
||||
// evaluates to "Smiljan"
|
||||
var city = parser.parseExpression("placeOfBirth?.city") // <1>
|
||||
.getValue(context, tesla, String::class.java)
|
||||
|
||||
tesla.setPlaceOfBirth(null)
|
||||
city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String::class.java)
|
||||
println(city) // null - does not throw NullPointerException!!!
|
||||
|
||||
// evaluates to null - does not throw NullPointerException
|
||||
city = parser.parseExpression("placeOfBirth?.city") // <2>
|
||||
.getValue(context, tesla, String::class.java)
|
||||
----
|
||||
<1> Use safe navigation operator on non-null `placeOfBirth` property
|
||||
<2> Use safe navigation operator on null `placeOfBirth` property
|
||||
======
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ class EvaluationTests extends AbstractExpressionTests {
|
|||
|
||||
@Test
|
||||
void stringType() {
|
||||
evaluateAndAskForReturnType("getPlaceOfBirth().getCity()", "SmilJan", String.class);
|
||||
evaluateAndAskForReturnType("getPlaceOfBirth().getCity()", "Smiljan", String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -594,7 +594,7 @@ class EvaluationTests extends AbstractExpressionTests {
|
|||
// nested properties
|
||||
@Test
|
||||
void propertiesNested01() {
|
||||
evaluate("placeOfBirth.city", "SmilJan", String.class, true);
|
||||
evaluate("placeOfBirth.city", "Smiljan", String.class, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class MethodInvocationTests extends AbstractExpressionTests {
|
|||
|
||||
@Test
|
||||
void testSimpleAccess01() {
|
||||
evaluate("getPlaceOfBirth().getCity()", "SmilJan", String.class);
|
||||
evaluate("getPlaceOfBirth().getCity()", "Smiljan", String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.expression.spel;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
|
|
@ -24,6 +25,8 @@ import org.junit.jupiter.api.Test;
|
|||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.ast.Operator;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.expression.spel.SpelMessage.MAX_CONCATENATED_STRING_LENGTH_EXCEEDED;
|
||||
|
|
@ -670,6 +673,18 @@ class OperatorTests extends AbstractExpressionTests {
|
|||
evaluate("new java.math.BigInteger('5') ^ 3", new BigInteger("125"), BigInteger.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void bigIntFunction() throws Exception {
|
||||
SpelExpressionParser parser = new SpelExpressionParser();
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
Method method = BigInteger.class.getMethod("valueOf", long.class);
|
||||
context.registerFunction("bigInt", method);
|
||||
|
||||
Expression expression = parser.parseExpression("3 + #bigInt(5)");
|
||||
BigInteger result = expression.getValue(context, BigInteger.class);
|
||||
assertThat(result).isEqualTo(BigInteger.valueOf(8));
|
||||
}
|
||||
|
||||
|
||||
private Operator getOperatorNode(SpelExpression expr) {
|
||||
SpelNode node = expr.getAST();
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class PropertyAccessTests extends AbstractExpressionTests {
|
|||
|
||||
@Test
|
||||
void simpleAccess02() {
|
||||
evaluate("placeOfBirth.city", "SmilJan", String.class);
|
||||
evaluate("placeOfBirth.city", "Smiljan", String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class SpelDocumentationTests extends AbstractExpressionTests {
|
|||
GregorianCalendar c = new GregorianCalendar();
|
||||
c.set(1856, 7, 9);
|
||||
tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
|
||||
tesla.setPlaceOfBirth(new PlaceOfBirth("SmilJan"));
|
||||
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
|
||||
tesla.setInventions("Telephone repeater", "Rotating magnetic field principle",
|
||||
"Polyphase alternating-current system", "Induction motor", "Alternating-current power transmission",
|
||||
"Tesla coil transformer", "Wireless communication", "Radio", "Fluorescent lights");
|
||||
|
|
@ -167,7 +167,7 @@ class SpelDocumentationTests extends AbstractExpressionTests {
|
|||
assertThat(year).isEqualTo(1856);
|
||||
|
||||
String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);
|
||||
assertThat(city).isEqualTo("SmilJan");
|
||||
assertThat(city).isEqualTo("Smiljan");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -616,11 +616,10 @@ class SpelDocumentationTests extends AbstractExpressionTests {
|
|||
StandardEvaluationContext societyContext = new StandardEvaluationContext();
|
||||
societyContext.setRootObject(new IEEE());
|
||||
|
||||
|
||||
parser.parseExpression("Name").setValue(societyContext, "IEEE");
|
||||
societyContext.setVariable("queryName", "Nikola Tesla");
|
||||
|
||||
String expression = "isMember(#queryName)? #queryName + ' is a member of the ' "
|
||||
String expression = "isMember(#queryName) ? #queryName + ' is a member of the ' "
|
||||
+ "+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'";
|
||||
|
||||
String queryResultString = parser.parseExpression(expression).getValue(societyContext, String.class);
|
||||
|
|
@ -629,6 +628,28 @@ class SpelDocumentationTests extends AbstractExpressionTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class SaveNavigationOperator {
|
||||
|
||||
@Test
|
||||
void nullSafePropertyAccess() {
|
||||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
|
||||
|
||||
// evaluates to "Smiljan"
|
||||
String city = parser.parseExpression("placeOfBirth?.city") // <1>
|
||||
.getValue(context, tesla, String.class);
|
||||
assertThat(city).isEqualTo("Smiljan");
|
||||
|
||||
tesla.setPlaceOfBirth(null);
|
||||
|
||||
// evaluates to null - does not throw a NullPointerException
|
||||
city = parser.parseExpression("placeOfBirth?.city") // <2>
|
||||
.getValue(context, tesla, String.class);
|
||||
assertThat(city).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class CollectionSelection {
|
||||
|
||||
|
|
@ -650,10 +671,10 @@ class SpelDocumentationTests extends AbstractExpressionTests {
|
|||
@SuppressWarnings("unchecked")
|
||||
void projection() {
|
||||
StandardEvaluationContext societyContext = new StandardEvaluationContext(new IEEE());
|
||||
// evaluates to ["SmilJan", "Idvor"]
|
||||
// evaluates to ["Smiljan", "Idvor"]
|
||||
List placesOfBirth = parser.parseExpression("members.![placeOfBirth.city]")
|
||||
.getValue(societyContext, List.class);
|
||||
assertThat(placesOfBirth).containsExactly("SmilJan", "Idvor");
|
||||
assertThat(placesOfBirth).containsExactly("Smiljan", "Idvor");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class TestScenarioCreator {
|
|||
GregorianCalendar c = new GregorianCalendar();
|
||||
c.set(1856, 7, 9);
|
||||
Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
|
||||
tesla.setPlaceOfBirth(new PlaceOfBirth("SmilJan"));
|
||||
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
|
||||
tesla.setInventions("Telephone repeater", "Rotating magnetic field principle",
|
||||
"Polyphase alternating-current system", "Induction motor", "Alternating-current power transmission",
|
||||
"Tesla coil transformer", "Wireless communication", "Radio", "Fluorescent lights");
|
||||
|
|
|
|||
Loading…
Reference in New Issue