return getValueRef(state).getValue();
}
@Override
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
TypedValue op = state.getActiveContextObject();
Object operand = op.getValue();
boolean operandIsArray = ObjectUtils.isArray(operand);
// TypeDescriptor operandTypeDescriptor = op.getTypeDescriptor();
// When the input is a map, we push a special context object on the stack
// before calling the specified operation. This special context object
// has two fields 'key' and 'value' that refer to the map entries key
// and value, and they can be referenced in the operation
// eg. {'a':'y','b':'n'}.!{value=='y'?key:null}" == ['a', null]
if (operand instanceof Map) {
Map<?, ?> mapData = (Map<?, ?>) operand;
List<Object> result = new ArrayList<Object>();
for (Map.Entry<?,?> entry : mapData.entrySet()) {
try {
state.pushActiveContextObject(new TypedValue(entry));
result.add(this.children[0].getValueInternal(state).getValue());
}
finally {
state.popActiveContextObject();
}
}
return new ValueRef.TypedValueHolderValueRef(new TypedValue(result),this); // TODO unable to build correct type descriptor
}
else if (operand instanceof Collection || operandIsArray) {
Collection<?> data = (operand instanceof Collection ? (Collection<?>) operand :
Arrays.asList(ObjectUtils.toObjectArray(operand)));
List<Object> result = new ArrayList<Object>();
int idx = 0;
Class<?> arrayElementType = null;
for (Object element : data) {
try {
state.pushActiveContextObject(new TypedValue(element));
state.enterScope("index", idx);
Object value = children[0].getValueInternal(state).getValue();
if (value != null && operandIsArray) {
arrayElementType = determineCommonType(arrayElementType, value.getClass());
}
result.add(value);
}
finally {
state.exitScope();
state.popActiveContextObject();
}
idx++;
}
if (operandIsArray) {
if (arrayElementType == null) {
arrayElementType = Object.class;
}
Object resultArray = Array.newInstance(arrayElementType, result.size());
System.arraycopy(result.toArray(), 0, resultArray, 0, result.size());
return new ValueRef.TypedValueHolderValueRef(new TypedValue(resultArray),this);
}
return new ValueRef.TypedValueHolderValueRef(new TypedValue(result),this);
}
else {
if (operand==null) {
if (this.nullSafe) {
return ValueRef.NullValueRef.instance;