Search in sources :

Example 16 with TypedValue

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;
}
Also used : SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) ArrayList(java.util.ArrayList) InvocationTargetException(java.lang.reflect.InvocationTargetException) TypeDescriptor(org.springframework.core.convert.TypeDescriptor) HashMap(java.util.HashMap) Map(java.util.Map) TypedValue(org.springframework.expression.TypedValue)

Example 17 with TypedValue

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;
}
Also used : SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) BigDecimal(java.math.BigDecimal) BigInteger(java.math.BigInteger) BigInteger(java.math.BigInteger) TypedValue(org.springframework.expression.TypedValue)

Example 18 with TypedValue

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);
}
Also used : BigDecimal(java.math.BigDecimal) BigInteger(java.math.BigInteger) BigInteger(java.math.BigInteger) TypedValue(org.springframework.expression.TypedValue)

Example 19 with TypedValue

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);
}
Also used : BigInteger(java.math.BigInteger) BigInteger(java.math.BigInteger) BigDecimal(java.math.BigDecimal) TypedValue(org.springframework.expression.TypedValue)

Example 20 with TypedValue

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);
}
Also used : SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) ExpressionState(org.springframework.expression.spel.ExpressionState) TypedValue(org.springframework.expression.TypedValue)

Aggregations

TypedValue (org.springframework.expression.TypedValue)63 Test (org.junit.Test)18 SpelEvaluationException (org.springframework.expression.spel.SpelEvaluationException)18 StandardEvaluationContext (org.springframework.expression.spel.support.StandardEvaluationContext)13 ExpressionState (org.springframework.expression.spel.ExpressionState)11 BigDecimal (java.math.BigDecimal)8 BigInteger (java.math.BigInteger)8 TypeDescriptor (org.springframework.core.convert.TypeDescriptor)8 EvaluationContext (org.springframework.expression.EvaluationContext)6 ArrayList (java.util.ArrayList)5 Map (java.util.Map)4 AccessException (org.springframework.expression.AccessException)4 Expression (org.springframework.expression.Expression)4 SpelExpressionParser (org.springframework.expression.spel.standard.SpelExpressionParser)4 MethodParameter (org.springframework.core.MethodParameter)3 EvaluationException (org.springframework.expression.EvaluationException)3 SpelNode (org.springframework.expression.spel.SpelNode)3 ReflectivePropertyAccessor (org.springframework.expression.spel.support.ReflectivePropertyAccessor)3 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 Method (java.lang.reflect.Method)2