@@ -158,14 +158,14 @@ public TypedValue setValueInternal(ExpressionState state, Supplier<TypedValue> v
158
158
throws EvaluationException {
159
159
160
160
TypedValue typedValue = valueSupplier .get ();
161
- // TODO Set value for IndexAccessor via its write () method, NOT via the ValueRef returned from its read () method.
161
+ // TODO Query IndexAccessor's canWrite () method before invoking its write () method.
162
162
getValueRef (state ).setValue (typedValue .getValue ());
163
163
return typedValue ;
164
164
}
165
165
166
166
@ Override
167
167
public boolean isWritable (ExpressionState expressionState ) throws SpelEvaluationException {
168
- return true ;
168
+ return getValueRef ( expressionState ). isWritable () ;
169
169
}
170
170
171
171
@@ -254,13 +254,13 @@ else if (target instanceof Collection<?> collection) {
254
254
try {
255
255
for (IndexAccessor indexAccessor : accessorsToTry ) {
256
256
if (indexAccessor .canRead (evalContext , target , index )) {
257
- // TODO Introduce local IndexAccessorValueRef.
258
- return indexAccessor .read (evalContext , target , index );
257
+ return new IndexAccessorValueRef (indexAccessor , target , index , evalContext , targetDescriptor );
259
258
}
260
259
}
261
260
}
262
261
catch (Exception ex ) {
263
- // TODO throw SpelEvaluationException for "exception during index access"
262
+ // TODO throw SpelEvaluationException for "exception during index access",
263
+ // analogous to SpelMessage.EXCEPTION_DURING_PROPERTY_READ.
264
264
}
265
265
266
266
throw new SpelEvaluationException (
@@ -874,4 +874,57 @@ public boolean isWritable() {
874
874
}
875
875
}
876
876
877
+
878
+ private class IndexAccessorValueRef implements ValueRef {
879
+
880
+ private final IndexAccessor indexAccessor ;
881
+
882
+ private final Object target ;
883
+
884
+ private final Object index ;
885
+
886
+ private final EvaluationContext evaluationContext ;
887
+
888
+ private final TypeDescriptor typeDescriptor ;
889
+
890
+
891
+ IndexAccessorValueRef (IndexAccessor indexAccessor , Object target , Object index ,
892
+ EvaluationContext evaluationContext , TypeDescriptor typeDescriptor ) {
893
+
894
+ this .indexAccessor = indexAccessor ;
895
+ this .target = target ;
896
+ this .index = index ;
897
+ this .evaluationContext = evaluationContext ;
898
+ this .typeDescriptor = typeDescriptor ;
899
+ }
900
+
901
+
902
+ @ Override
903
+ public TypedValue getValue () {
904
+ try {
905
+ return this .indexAccessor .read (this .evaluationContext , this .target , this .index );
906
+ }
907
+ catch (AccessException ex ) {
908
+ throw new SpelEvaluationException (getStartPosition (), ex ,
909
+ SpelMessage .INDEXING_NOT_SUPPORTED_FOR_TYPE , this .typeDescriptor .toString ());
910
+ }
911
+ }
912
+
913
+ @ Override
914
+ public void setValue (@ Nullable Object newValue ) {
915
+ try {
916
+ this .indexAccessor .write (this .evaluationContext , this .target , this .index , newValue );
917
+ }
918
+ catch (AccessException ex ) {
919
+ throw new SpelEvaluationException (getStartPosition (), ex ,
920
+ SpelMessage .INDEXING_NOT_SUPPORTED_FOR_TYPE , this .typeDescriptor .toString ());
921
+ }
922
+ }
923
+
924
+ @ Override
925
+ public boolean isWritable () {
926
+ return true ;
927
+ }
928
+ }
929
+
877
930
}
0 commit comments