Polish SpEL's Indexer and test

This commit is contained in:
Sam Brannen 2024-02-21 17:44:09 +01:00
parent 5a2b127a21
commit 734fc476ee
2 changed files with 29 additions and 12 deletions

View File

@ -44,8 +44,21 @@ import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* An Indexer can index into some proceeding structure to access a particular piece of it.
* <p>Supported structures are: strings / collections (lists/sets) / arrays.
* An {@code Indexer} can index into some proceeding structure to access a
* particular element of the structure.
*
* <p>Numerical index values are zero-based, such as when accessing the
* n<sup>th</sup> element of an array in Java.
*
* <h3>Supported Structures</h3>
*
* <ul>
* <li>Arrays: the n<sup>th</sup> element</li>
* <li>Collections (list and sets): the n<sup>th</sup> element</li>
* <li>Strings: the n<sup>th</sup> character as a {@link String}</li>
* <li>Maps: the value for the specified key</li>
* <li>Objects: the property with the specified name</li>
* </ul>
*
* @author Andy Clement
* @author Phillip Webb
@ -58,6 +71,9 @@ public class Indexer extends SpelNodeImpl {
private enum IndexedType {ARRAY, LIST, MAP, STRING, OBJECT}
@Nullable
private IndexedType indexedType;
// These fields are used when the indexer is being used as a property read accessor.
// If the name and target type match these cached values then the cachedReadAccessor
// is used to read the property. If they do not match, the correct accessor is
@ -86,12 +102,13 @@ public class Indexer extends SpelNodeImpl {
@Nullable
private PropertyAccessor cachedWriteAccessor;
@Nullable
private IndexedType indexedType;
public Indexer(int startPos, int endPos, SpelNodeImpl expr) {
super(startPos, endPos, expr);
/**
* Create an {@code Indexer} with the given start position, end position, and
* index expression.
*/
public Indexer(int startPos, int endPos, SpelNodeImpl indexExpression) {
super(startPos, endPos, indexExpression);
}
@ -146,6 +163,7 @@ public class Indexer extends SpelNodeImpl {
if (target == null) {
throw new SpelEvaluationException(getStartPosition(), SpelMessage.CANNOT_INDEX_INTO_NULL_VALUE);
}
// At this point, we need a TypeDescriptor for a non-null target object
Assert.state(targetDescriptor != null, "No type descriptor");

View File

@ -62,7 +62,6 @@ class IndexingTests {
assertThat(expression.getValue(this)).isEqualTo(4);
}
@Test
@SuppressWarnings("unchecked")
void indexIntoGenericPropertyContainingMap() {
@ -302,7 +301,7 @@ class IndexingTests {
@Test
void indexIntoGenericPropertyContainingArray() {
String[] property = new String[] { "bar" };
String[] property = { "bar" };
this.property = property;
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("property");
@ -357,17 +356,17 @@ class IndexingTests {
@Test
@SuppressWarnings("unchecked")
void testListOfScalar() {
void listOfScalars() {
listOfScalarNotGeneric = new ArrayList(1);
listOfScalarNotGeneric.add("5");
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("listOfScalarNotGeneric[0]");
assertThat(expression.getValue(this, Integer.class)).isEqualTo(Integer.valueOf(5));
assertThat(expression.getValue(this, Integer.class)).isEqualTo(5);
}
@Test
@SuppressWarnings("unchecked")
void testListsOfMap() {
void listOfMaps() {
listOfMapsNotGeneric = new ArrayList();
Map map = new HashMap();
map.put("fruit", "apple");