Skip to content

Commit defb6b7

Browse files
committed
Polish documentation and implementation of SpEL's Indexer
1 parent 726ac91 commit defb6b7

File tree

1 file changed

+18
-13
lines changed
  • spring-expression/src/main/java/org/springframework/expression/spel/ast

1 file changed

+18
-13
lines changed

spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java

+18-13
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,11 @@
5454
*
5555
* <ul>
5656
* <li>Arrays: the n<sup>th</sup> element</li>
57-
* <li>Collections (lists and sets): the n<sup>th</sup> element</li>
57+
* <li>Collections (lists, sets, etc.): the n<sup>th</sup> element</li>
5858
* <li>Strings: the n<sup>th</sup> character as a {@link String}</li>
5959
* <li>Maps: the value for the specified key</li>
6060
* <li>Objects: the property with the specified name</li>
61+
* <li>Custom Structures: via registered {@link IndexAccessor} implementations</li>
6162
* </ul>
6263
*
6364
* <h3>Null-safe Indexing</h3>
@@ -72,6 +73,9 @@
7273
* @author Stephane Nicoll
7374
* @author Sam Brannen
7475
* @since 3.0
76+
* @see org.springframework.expression.IndexAccessor
77+
* @see org.springframework.expression.spel.CompilableIndexAccessor
78+
* @see org.springframework.expression.spel.support.ReflectiveIndexAccessor
7579
*/
7680
public class Indexer extends SpelNodeImpl {
7781

@@ -385,7 +389,7 @@ else if (this.indexedType == IndexedType.MAP) {
385389
mv.visitTypeInsn(CHECKCAST, "java/util/Map");
386390
// Special case when the key is an unquoted string literal that will be parsed as
387391
// a property/field reference
388-
if ((index instanceof PropertyOrFieldReference reference)) {
392+
if (index instanceof PropertyOrFieldReference reference) {
389393
String mapKeyName = reference.getName();
390394
mv.visitLdcInsn(mapKeyName);
391395
}
@@ -849,30 +853,31 @@ public TypedValue getValue() {
849853
exitTypeDescriptor = CodeFlow.toDescriptor(Object.class);
850854
return new TypedValue(o, this.collectionEntryDescriptor.elementTypeDescriptor(o));
851855
}
856+
852857
int pos = 0;
853858
for (Object o : this.collection) {
854859
if (pos == this.index) {
855860
return new TypedValue(o, this.collectionEntryDescriptor.elementTypeDescriptor(o));
856861
}
857862
pos++;
858863
}
859-
throw new IllegalStateException("Failed to find indexed element " + this.index + ": " + this.collection);
864+
throw new SpelEvaluationException(getStartPosition(), SpelMessage.COLLECTION_INDEX_OUT_OF_BOUNDS,
865+
this.collection.size(), this.index);
860866
}
861867

862868
@Override
863869
public void setValue(@Nullable Object newValue) {
864-
growCollectionIfNecessary();
865-
if (this.collection instanceof List list) {
866-
if (this.collectionEntryDescriptor.getElementTypeDescriptor() != null) {
867-
newValue = this.typeConverter.convertValue(newValue, TypeDescriptor.forObject(newValue),
868-
this.collectionEntryDescriptor.getElementTypeDescriptor());
869-
}
870-
list.set(this.index, newValue);
871-
}
872-
else {
870+
if (!(this.collection instanceof List list)) {
873871
throw new SpelEvaluationException(getStartPosition(), SpelMessage.INDEXING_NOT_SUPPORTED_FOR_TYPE,
874872
this.collectionEntryDescriptor.toString());
875873
}
874+
875+
growCollectionIfNecessary();
876+
if (this.collectionEntryDescriptor.getElementTypeDescriptor() != null) {
877+
newValue = this.typeConverter.convertValue(newValue, TypeDescriptor.forObject(newValue),
878+
this.collectionEntryDescriptor.getElementTypeDescriptor());
879+
}
880+
list.set(this.index, newValue);
876881
}
877882

878883
private void growCollectionIfNecessary() {
@@ -906,7 +911,7 @@ private void growCollectionIfNecessary() {
906911

907912
@Override
908913
public boolean isWritable() {
909-
return true;
914+
return (this.collection instanceof List);
910915
}
911916

912917
@Nullable

0 commit comments

Comments
 (0)