Indexed objects (arrays/maps/lists) now settable

This commit is contained in:
Andy Clement 2009-03-30 19:40:20 +00:00
parent 401b7f66c4
commit c057638bd0
2 changed files with 90 additions and 19 deletions

View File

@ -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) {

View File

@ -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;
}
}