Indexed objects (arrays/maps/lists) now settable
This commit is contained in:
parent
401b7f66c4
commit
c057638bd0
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.expression.spel.ast;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
|
|
@ -90,6 +91,94 @@ public class Indexer extends SpelNodeImpl {
|
|||
throw new SpelException(SpelMessages.INDEXING_NOT_SUPPORTED_FOR_TYPE, ctx.getClass().getName());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void setValue(ExpressionState state, Object newValue) throws EvaluationException {
|
||||
Object ctx = state.getActiveContextObject();
|
||||
Object index = getChild(0).getValueInternal(state);
|
||||
|
||||
// Indexing into a Map
|
||||
if (ctx instanceof Map) {
|
||||
((Map) ctx).put(index,newValue); // TODO missing conversion for both index and newValue
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = state.convertValue(index, Integer.class);
|
||||
|
||||
if (ctx.getClass().isArray()) {
|
||||
setArrayElement(state, ctx, idx, newValue);
|
||||
} else if (ctx instanceof List) {
|
||||
List<Object> c = (List<Object>) ctx;
|
||||
if (idx >= c.size()) {
|
||||
throw new SpelException(SpelMessages.COLLECTION_INDEX_OUT_OF_BOUNDS, c.size(), idx);
|
||||
}
|
||||
c.set(idx,newValue); // TODO missing conversion
|
||||
} else {
|
||||
throw new SpelException(SpelMessages.INDEXING_NOT_SUPPORTED_FOR_TYPE, ctx.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (i > 0)
|
||||
sb.append(",");
|
||||
sb.append(getChild(i).toStringAST());
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void setArrayElement(ExpressionState state, Object ctx, int idx, Object newValue) throws EvaluationException {
|
||||
Class<?> arrayComponentType = ctx.getClass().getComponentType();
|
||||
if (arrayComponentType == Integer.TYPE) {
|
||||
int[] array = (int[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
array[idx] = state.convertValue(newValue, Integer.class);
|
||||
} else if (arrayComponentType == Boolean.TYPE) {
|
||||
boolean[] array = (boolean[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
array[idx] = state.convertValue(newValue, Boolean.class);
|
||||
} else if (arrayComponentType == Character.TYPE) {
|
||||
char[] array = (char[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
array[idx] = state.convertValue(newValue, Character.class);
|
||||
} else if (arrayComponentType == Long.TYPE) {
|
||||
long[] array = (long[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
array[idx] = state.convertValue(newValue, Long.class);
|
||||
} else if (arrayComponentType == Short.TYPE) {
|
||||
short[] array = (short[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
array[idx] = state.convertValue(newValue, Short.class);
|
||||
} else if (arrayComponentType == Double.TYPE) {
|
||||
double[] array = (double[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
array[idx] = state.convertValue(newValue, Double.class);
|
||||
} else if (arrayComponentType == Float.TYPE) {
|
||||
float[] array = (float[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
array[idx] = state.convertValue(newValue, Float.class);
|
||||
} else if (arrayComponentType == Byte.TYPE) {
|
||||
byte[] array = (byte[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
array[idx] = state.convertValue(newValue, Byte.class);
|
||||
} else {
|
||||
Object[] array = (Object[]) ctx;
|
||||
checkAccess(array.length, idx);
|
||||
array[idx] = state.convertValue(newValue, arrayComponentType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Object accessArrayElement(Object ctx, int idx) throws SpelException {
|
||||
Class<?> arrayComponentType = ctx.getClass().getComponentType();
|
||||
if (arrayComponentType == Integer.TYPE) {
|
||||
|
|
@ -131,23 +220,6 @@ public class Indexer extends SpelNodeImpl {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (i > 0)
|
||||
sb.append(",");
|
||||
sb.append(getChild(i).toStringAST());
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable(ExpressionState expressionState) throws SpelException {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkAccess(int arrayLength, int index) throws SpelException {
|
||||
if (index > arrayLength) {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
|
|
@ -141,7 +140,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
|||
for (PropertyAccessor accessor : accessorsToTry) {
|
||||
if (accessor.canWrite(eContext, contextObject, name)) {
|
||||
this.cachedWriteAccessor = accessor;
|
||||
accessor.write(eContext, contextObject, name, newValue);
|
||||
accessor.write(eContext, contextObject, name, newValue); // TODO missing conversion of newValue to the type of the property
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue