use of org.springframework.expression.TypedValue in project spring-framework by spring-projects.
the class PropertyOrFieldReference method getValueInternal.
private TypedValue getValueInternal(TypedValue contextObject, EvaluationContext evalContext, boolean isAutoGrowNullReferences) throws EvaluationException {
TypedValue result = readProperty(contextObject, evalContext, this.name);
// Dynamically create the objects if the user has requested that optional behavior
if (result.getValue() == null && isAutoGrowNullReferences && nextChildIs(Indexer.class, PropertyOrFieldReference.class)) {
TypeDescriptor resultDescriptor = result.getTypeDescriptor();
// Create a new collection or map ready for the indexer
if (List.class == resultDescriptor.getType()) {
if (isWritableProperty(this.name, contextObject, evalContext)) {
List<?> newList = new ArrayList<>();
writeProperty(contextObject, evalContext, this.name, newList);
result = readProperty(contextObject, evalContext, this.name);
}
} else if (Map.class == resultDescriptor.getType()) {
if (isWritableProperty(this.name, contextObject, evalContext)) {
Map<?, ?> newMap = new HashMap<>();
writeProperty(contextObject, evalContext, this.name, newMap);
result = readProperty(contextObject, evalContext, this.name);
}
} else {
// 'simple' object
try {
if (isWritableProperty(this.name, contextObject, evalContext)) {
Class<?> clazz = result.getTypeDescriptor().getType();
Object newObject = ReflectionUtils.accessibleConstructor(clazz).newInstance();
writeProperty(contextObject, evalContext, this.name, newObject);
result = readProperty(contextObject, evalContext, this.name);
}
} catch (InvocationTargetException ex) {
throw new SpelEvaluationException(getStartPosition(), ex.getTargetException(), SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT, result.getTypeDescriptor().getType());
} catch (Throwable ex) {
throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.UNABLE_TO_DYNAMICALLY_CREATE_OBJECT, result.getTypeDescriptor().getType());
}
}
}
return result;
}
use of org.springframework.expression.TypedValue in project spring-framework by spring-projects.
the class OpInc method getValueInternal.
@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
SpelNodeImpl operand = getLeftOperand();
ValueRef valueRef = operand.getValueRef(state);
TypedValue typedValue = valueRef.getValue();
Object value = typedValue.getValue();
TypedValue returnValue = typedValue;
TypedValue newValue = null;
if (value instanceof Number) {
Number op1 = (Number) value;
if (op1 instanceof BigDecimal) {
newValue = new TypedValue(((BigDecimal) op1).add(BigDecimal.ONE), typedValue.getTypeDescriptor());
} else if (op1 instanceof Double) {
newValue = new TypedValue(op1.doubleValue() + 1.0d, typedValue.getTypeDescriptor());
} else if (op1 instanceof Float) {
newValue = new TypedValue(op1.floatValue() + 1.0f, typedValue.getTypeDescriptor());
} else if (op1 instanceof BigInteger) {
newValue = new TypedValue(((BigInteger) op1).add(BigInteger.ONE), typedValue.getTypeDescriptor());
} else if (op1 instanceof Long) {
newValue = new TypedValue(op1.longValue() + 1L, typedValue.getTypeDescriptor());
} else if (op1 instanceof Integer) {
newValue = new TypedValue(op1.intValue() + 1, typedValue.getTypeDescriptor());
} else if (op1 instanceof Short) {
newValue = new TypedValue(op1.shortValue() + (short) 1, typedValue.getTypeDescriptor());
} else if (op1 instanceof Byte) {
newValue = new TypedValue(op1.byteValue() + (byte) 1, typedValue.getTypeDescriptor());
} else {
// Unknown Number subtype -> best guess is double increment
newValue = new TypedValue(op1.doubleValue() + 1.0d, typedValue.getTypeDescriptor());
}
}
if (newValue == null) {
try {
newValue = state.operate(Operation.ADD, returnValue.getValue(), 1);
} catch (SpelEvaluationException ex) {
if (ex.getMessageCode() == SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES) {
// This means the operand is not incrementable
throw new SpelEvaluationException(operand.getStartPosition(), SpelMessage.OPERAND_NOT_INCREMENTABLE, operand.toStringAST());
}
throw ex;
}
}
// set the name value
try {
valueRef.setValue(newValue.getValue());
} catch (SpelEvaluationException see) {
// If unable to set the value the operand is not writable (e.g. 1++ )
if (see.getMessageCode() == SpelMessage.SETVALUE_NOT_SUPPORTED) {
throw new SpelEvaluationException(operand.getStartPosition(), SpelMessage.OPERAND_NOT_INCREMENTABLE);
} else {
throw see;
}
}
if (!this.postfix) {
// The return value is the new value, not the original value
returnValue = newValue;
}
return returnValue;
}
use of org.springframework.expression.TypedValue in project spring-framework by spring-projects.
the class OpMinus 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 minus
Object operand = leftOp.getValueInternal(state).getValue();
if (operand instanceof Number) {
if (operand instanceof BigDecimal) {
return new TypedValue(((BigDecimal) operand).negate());
} else if (operand instanceof Double) {
this.exitTypeDescriptor = "D";
return new TypedValue(0 - ((Number) operand).doubleValue());
} else if (operand instanceof Float) {
this.exitTypeDescriptor = "F";
return new TypedValue(0 - ((Number) operand).floatValue());
} else if (operand instanceof BigInteger) {
return new TypedValue(((BigInteger) operand).negate());
} else if (operand instanceof Long) {
this.exitTypeDescriptor = "J";
return new TypedValue(0 - ((Number) operand).longValue());
} else if (operand instanceof Integer) {
this.exitTypeDescriptor = "I";
return new TypedValue(0 - ((Number) operand).intValue());
} else if (operand instanceof Short) {
return new TypedValue(0 - ((Number) operand).shortValue());
} else if (operand instanceof Byte) {
return new TypedValue(0 - ((Number) operand).byteValue());
} else {
// Unknown Number subtypes -> best guess is double subtraction
return new TypedValue(0 - ((Number) operand).doubleValue());
}
}
return state.operate(Operation.SUBTRACT, operand, null);
}
Object left = leftOp.getValueInternal(state).getValue();
Object right = rightOp.getValueInternal(state).getValue();
if (left instanceof Number && right instanceof Number) {
Number leftNumber = (Number) left;
Number rightNumber = (Number) right;
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.subtract(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.subtract(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 subtraction
return new TypedValue(leftNumber.doubleValue() - rightNumber.doubleValue());
}
}
if (left instanceof String && right instanceof Integer && ((String) left).length() == 1) {
String theString = (String) left;
Integer theInteger = (Integer) right;
// Implements character - int (ie. b - 1 = a)
return new TypedValue(Character.toString((char) (theString.charAt(0) - theInteger)));
}
return state.operate(Operation.SUBTRACT, left, right);
}
use of org.springframework.expression.TypedValue in project spring-framework by spring-projects.
the class OpMultiply method getValueInternal.
/**
* Implements the {@code multiply} operator directly here for certain types
* of supported operands and otherwise delegates to any registered overloader
* for types not supported here.
* <p>Supported operand types:
* <ul>
* <li>numbers
* <li>String and int ('abc' * 2 == 'abcabc')
* </ul>
*/
@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
Object leftOperand = getLeftOperand().getValueInternal(state).getValue();
Object rightOperand = getRightOperand().getValueInternal(state).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.multiply(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.multiply(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 multiplication
return new TypedValue(leftNumber.doubleValue() * rightNumber.doubleValue());
}
}
if (leftOperand instanceof String && rightOperand instanceof Integer) {
int repeats = (Integer) rightOperand;
StringBuilder result = new StringBuilder();
for (int i = 0; i < repeats; i++) {
result.append(leftOperand);
}
return new TypedValue(result.toString());
}
return state.operate(Operation.MULTIPLY, leftOperand, rightOperand);
}
use of org.springframework.expression.TypedValue in project spring-framework by spring-projects.
the class SpelExpression method getValue.
@SuppressWarnings("unchecked")
@Override
public <T> T getValue(Class<T> expectedResultType) throws EvaluationException {
if (this.compiledAst != null) {
try {
TypedValue contextRoot = evaluationContext == null ? null : evaluationContext.getRootObject();
Object result = this.compiledAst.getValue(contextRoot == null ? null : contextRoot.getValue(), evaluationContext);
if (expectedResultType == null) {
return (T) result;
} else {
return ExpressionUtils.convertTypedValue(getEvaluationContext(), new TypedValue(result), expectedResultType);
}
} catch (Throwable ex) {
// If running in mixed mode, revert to interpreted
if (this.configuration.getCompilerMode() == SpelCompilerMode.MIXED) {
this.interpretedCount = 0;
this.compiledAst = null;
} else {
// Running in SpelCompilerMode.immediate mode - propagate exception to caller
throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_RUNNING_COMPILED_EXPRESSION);
}
}
}
ExpressionState expressionState = new ExpressionState(getEvaluationContext(), this.configuration);
TypedValue typedResultValue = this.ast.getTypedValue(expressionState);
checkCompile(expressionState);
return ExpressionUtils.convertTypedValue(expressionState.getEvaluationContext(), typedResultValue, expectedResultType);
}
Aggregations