use of org.springframework.expression.TypedValue in project spring-framework by spring-projects.
the class CompoundExpression method getValueRef.
@Override
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
if (getChildCount() == 1) {
return this.children[0].getValueRef(state);
}
SpelNodeImpl nextNode = this.children[0];
try {
TypedValue result = nextNode.getValueInternal(state);
int cc = getChildCount();
for (int i = 1; i < cc - 1; i++) {
try {
state.pushActiveContextObject(result);
nextNode = this.children[i];
result = nextNode.getValueInternal(state);
} finally {
state.popActiveContextObject();
}
}
try {
state.pushActiveContextObject(result);
nextNode = this.children[cc - 1];
return nextNode.getValueRef(state);
} finally {
state.popActiveContextObject();
}
} catch (SpelEvaluationException ex) {
// Correct the position for the error before re-throwing
ex.setPosition(nextNode.getStartPosition());
throw ex;
}
}
use of org.springframework.expression.TypedValue in project spring-framework by spring-projects.
the class Selection method getValueRef.
@Override
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
TypedValue op = state.getActiveContextObject();
Object operand = op.getValue();
SpelNodeImpl selectionCriteria = this.children[0];
if (operand instanceof Map) {
Map<?, ?> mapdata = (Map<?, ?>) operand;
// TODO don't lose generic info for the new map
Map<Object, Object> result = new HashMap<>();
Object lastKey = null;
for (Map.Entry<?, ?> entry : mapdata.entrySet()) {
try {
TypedValue kvPair = new TypedValue(entry);
state.pushActiveContextObject(kvPair);
state.enterScope();
Object val = selectionCriteria.getValueInternal(state).getValue();
if (val instanceof Boolean) {
if ((Boolean) val) {
if (this.variant == FIRST) {
result.put(entry.getKey(), entry.getValue());
return new ValueRef.TypedValueHolderValueRef(new TypedValue(result), this);
}
result.put(entry.getKey(), entry.getValue());
lastKey = entry.getKey();
}
} else {
throw new SpelEvaluationException(selectionCriteria.getStartPosition(), SpelMessage.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN);
}
} finally {
state.popActiveContextObject();
state.exitScope();
}
}
if ((this.variant == FIRST || this.variant == LAST) && result.isEmpty()) {
return new ValueRef.TypedValueHolderValueRef(new TypedValue(null), this);
}
if (this.variant == LAST) {
Map<Object, Object> resultMap = new HashMap<>();
Object lastValue = result.get(lastKey);
resultMap.put(lastKey, lastValue);
return new ValueRef.TypedValueHolderValueRef(new TypedValue(resultMap), this);
}
return new ValueRef.TypedValueHolderValueRef(new TypedValue(result), this);
}
if (operand instanceof Iterable || ObjectUtils.isArray(operand)) {
Iterable<?> data = (operand instanceof Iterable ? (Iterable<?>) operand : Arrays.asList(ObjectUtils.toObjectArray(operand)));
List<Object> result = new ArrayList<>();
int index = 0;
for (Object element : data) {
try {
state.pushActiveContextObject(new TypedValue(element));
state.enterScope("index", index);
Object val = selectionCriteria.getValueInternal(state).getValue();
if (val instanceof Boolean) {
if ((Boolean) val) {
if (this.variant == FIRST) {
return new ValueRef.TypedValueHolderValueRef(new TypedValue(element), this);
}
result.add(element);
}
} else {
throw new SpelEvaluationException(selectionCriteria.getStartPosition(), SpelMessage.RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN);
}
index++;
} finally {
state.exitScope();
state.popActiveContextObject();
}
}
if ((this.variant == FIRST || this.variant == LAST) && result.isEmpty()) {
return ValueRef.NullValueRef.INSTANCE;
}
if (this.variant == LAST) {
return new ValueRef.TypedValueHolderValueRef(new TypedValue(result.get(result.size() - 1)), this);
}
if (operand instanceof Iterable) {
return new ValueRef.TypedValueHolderValueRef(new TypedValue(result), this);
}
Class<?> elementType = ClassUtils.resolvePrimitiveIfNecessary(op.getTypeDescriptor().getElementTypeDescriptor().getType());
Object resultArray = Array.newInstance(elementType, result.size());
System.arraycopy(result.toArray(), 0, resultArray, 0, result.size());
return new ValueRef.TypedValueHolderValueRef(new TypedValue(resultArray), this);
}
if (operand == null) {
if (this.nullSafe) {
return ValueRef.NullValueRef.INSTANCE;
}
throw new SpelEvaluationException(getStartPosition(), SpelMessage.INVALID_TYPE_FOR_SELECTION, "null");
}
throw new SpelEvaluationException(getStartPosition(), SpelMessage.INVALID_TYPE_FOR_SELECTION, operand.getClass().getName());
}
use of org.springframework.expression.TypedValue in project spring-framework by spring-projects.
the class Ternary method getValueInternal.
/**
* Evaluate the condition and if true evaluate the first alternative, otherwise
* evaluate the second alternative.
* @param state the expression state
* @throws EvaluationException if the condition does not evaluate correctly to
* a boolean or there is a problem executing the chosen alternative
*/
@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
Boolean value = this.children[0].getValue(state, Boolean.class);
if (value == null) {
throw new SpelEvaluationException(getChild(0).getStartPosition(), SpelMessage.TYPE_CONVERSION_ERROR, "null", "boolean");
}
TypedValue result = this.children[value ? 1 : 2].getValueInternal(state);
computeExitTypeDescriptor();
return result;
}
use of org.springframework.expression.TypedValue in project spring-framework by spring-projects.
the class OpPlus method getValueInternal.
@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
SpelNodeImpl leftOp = getLeftOperand();
SpelNodeImpl rightOp = getRightOperand();
if (rightOp == null) {
// if only one operand, then this is unary plus
Object operandOne = leftOp.getValueInternal(state).getValue();
if (operandOne instanceof Number) {
if (operandOne instanceof Double) {
this.exitTypeDescriptor = "D";
} else if (operandOne instanceof Float) {
this.exitTypeDescriptor = "F";
} else if (operandOne instanceof Long) {
this.exitTypeDescriptor = "J";
} else if (operandOne instanceof Integer) {
this.exitTypeDescriptor = "I";
}
return new TypedValue(operandOne);
}
return state.operate(Operation.ADD, operandOne, null);
}
TypedValue operandOneValue = leftOp.getValueInternal(state);
Object leftOperand = operandOneValue.getValue();
TypedValue operandTwoValue = rightOp.getValueInternal(state);
Object rightOperand = operandTwoValue.getValue();
if (leftOperand instanceof Number && rightOperand instanceof Number) {
Number leftNumber = (Number) leftOperand;
Number rightNumber = (Number) rightOperand;
if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);
return new TypedValue(leftBigDecimal.add(rightBigDecimal));
} else if (leftNumber instanceof Double || rightNumber instanceof Double) {
this.exitTypeDescriptor = "D";
return new TypedValue(leftNumber.doubleValue() + rightNumber.doubleValue());
} else if (leftNumber instanceof Float || rightNumber instanceof Float) {
this.exitTypeDescriptor = "F";
return new TypedValue(leftNumber.floatValue() + rightNumber.floatValue());
} else if (leftNumber instanceof BigInteger || rightNumber instanceof BigInteger) {
BigInteger leftBigInteger = NumberUtils.convertNumberToTargetClass(leftNumber, BigInteger.class);
BigInteger rightBigInteger = NumberUtils.convertNumberToTargetClass(rightNumber, BigInteger.class);
return new TypedValue(leftBigInteger.add(rightBigInteger));
} else if (leftNumber instanceof Long || rightNumber instanceof Long) {
this.exitTypeDescriptor = "J";
return new TypedValue(leftNumber.longValue() + rightNumber.longValue());
} else if (CodeFlow.isIntegerForNumericOp(leftNumber) || CodeFlow.isIntegerForNumericOp(rightNumber)) {
this.exitTypeDescriptor = "I";
return new TypedValue(leftNumber.intValue() + rightNumber.intValue());
} else {
// Unknown Number subtypes -> best guess is double addition
return new TypedValue(leftNumber.doubleValue() + rightNumber.doubleValue());
}
}
if (leftOperand instanceof String && rightOperand instanceof String) {
this.exitTypeDescriptor = "Ljava/lang/String";
return new TypedValue((String) leftOperand + rightOperand);
}
if (leftOperand instanceof String) {
return new TypedValue(leftOperand + (rightOperand == null ? "null" : convertTypedValueToString(operandTwoValue, state)));
}
if (rightOperand instanceof String) {
return new TypedValue((leftOperand == null ? "null" : convertTypedValueToString(operandOneValue, state)) + rightOperand);
}
return state.operate(Operation.ADD, leftOperand, rightOperand);
}
use of org.springframework.expression.TypedValue in project spring-framework by spring-projects.
the class OperatorPower method getValueInternal.
@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
SpelNodeImpl leftOp = getLeftOperand();
SpelNodeImpl rightOp = getRightOperand();
Object leftOperand = leftOp.getValueInternal(state).getValue();
Object rightOperand = rightOp.getValueInternal(state).getValue();
if (leftOperand instanceof Number && rightOperand instanceof Number) {
Number leftNumber = (Number) leftOperand;
Number rightNumber = (Number) rightOperand;
if (leftNumber instanceof BigDecimal) {
BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
return new TypedValue(leftBigDecimal.pow(rightNumber.intValue()));
} else if (leftNumber instanceof BigInteger) {
BigInteger leftBigInteger = NumberUtils.convertNumberToTargetClass(leftNumber, BigInteger.class);
return new TypedValue(leftBigInteger.pow(rightNumber.intValue()));
} else if (leftNumber instanceof Double || rightNumber instanceof Double) {
return new TypedValue(Math.pow(leftNumber.doubleValue(), rightNumber.doubleValue()));
} else if (leftNumber instanceof Float || rightNumber instanceof Float) {
return new TypedValue(Math.pow(leftNumber.floatValue(), rightNumber.floatValue()));
}
double d = Math.pow(leftNumber.doubleValue(), rightNumber.doubleValue());
if (d > Integer.MAX_VALUE || leftNumber instanceof Long || rightNumber instanceof Long) {
return new TypedValue((long) d);
} else {
return new TypedValue((int) d);
}
}
return state.operate(Operation.POWER, leftOperand, rightOperand);
}
Aggregations