001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.expression.spel.ast; 018 019import java.math.BigDecimal; 020import java.math.BigInteger; 021 022import org.springframework.expression.EvaluationException; 023import org.springframework.expression.Operation; 024import org.springframework.expression.TypedValue; 025import org.springframework.expression.spel.ExpressionState; 026import org.springframework.expression.spel.SpelEvaluationException; 027import org.springframework.expression.spel.SpelMessage; 028import org.springframework.util.Assert; 029 030/** 031 * Increment operator. Can be used in a prefix or postfix form. This will throw 032 * appropriate exceptions if the operand in question does not support increment. 033 * 034 * @author Andy Clement 035 * @author Juergen Hoeller 036 * @author Giovanni Dall'Oglio Risso 037 * @since 3.2 038 */ 039public class OpInc extends Operator { 040 041 private final boolean postfix; // false means prefix 042 043 044 public OpInc(int pos, boolean postfix, SpelNodeImpl... operands) { 045 super("++", pos, operands); 046 this.postfix = postfix; 047 Assert.notEmpty(operands, "Operands must not be empty"); 048 } 049 050 051 @Override 052 public TypedValue getValueInternal(ExpressionState state) throws EvaluationException { 053 SpelNodeImpl operand = getLeftOperand(); 054 ValueRef valueRef = operand.getValueRef(state); 055 056 TypedValue typedValue = valueRef.getValue(); 057 Object value = typedValue.getValue(); 058 TypedValue returnValue = typedValue; 059 TypedValue newValue = null; 060 061 if (value instanceof Number) { 062 Number op1 = (Number) value; 063 if (op1 instanceof BigDecimal) { 064 newValue = new TypedValue(((BigDecimal) op1).add(BigDecimal.ONE), typedValue.getTypeDescriptor()); 065 } 066 else if (op1 instanceof Double) { 067 newValue = new TypedValue(op1.doubleValue() + 1.0d, typedValue.getTypeDescriptor()); 068 } 069 else if (op1 instanceof Float) { 070 newValue = new TypedValue(op1.floatValue() + 1.0f, typedValue.getTypeDescriptor()); 071 } 072 else if (op1 instanceof BigInteger) { 073 newValue = new TypedValue(((BigInteger) op1).add(BigInteger.ONE), typedValue.getTypeDescriptor()); 074 } 075 else if (op1 instanceof Long) { 076 newValue = new TypedValue(op1.longValue() + 1L, typedValue.getTypeDescriptor()); 077 } 078 else if (op1 instanceof Integer) { 079 newValue = new TypedValue(op1.intValue() + 1, typedValue.getTypeDescriptor()); 080 } 081 else if (op1 instanceof Short) { 082 newValue = new TypedValue(op1.shortValue() + (short) 1, typedValue.getTypeDescriptor()); 083 } 084 else if (op1 instanceof Byte) { 085 newValue = new TypedValue(op1.byteValue() + (byte) 1, typedValue.getTypeDescriptor()); 086 } 087 else { 088 // Unknown Number subtype -> best guess is double increment 089 newValue = new TypedValue(op1.doubleValue() + 1.0d, typedValue.getTypeDescriptor()); 090 } 091 } 092 093 if (newValue == null) { 094 try { 095 newValue = state.operate(Operation.ADD, returnValue.getValue(), 1); 096 } 097 catch (SpelEvaluationException ex) { 098 if (ex.getMessageCode() == SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES) { 099 // This means the operand is not incrementable 100 throw new SpelEvaluationException(operand.getStartPosition(), 101 SpelMessage.OPERAND_NOT_INCREMENTABLE, operand.toStringAST()); 102 } 103 throw ex; 104 } 105 } 106 107 // set the name value 108 try { 109 valueRef.setValue(newValue.getValue()); 110 } 111 catch (SpelEvaluationException see) { 112 // If unable to set the value the operand is not writable (e.g. 1++ ) 113 if (see.getMessageCode() == SpelMessage.SETVALUE_NOT_SUPPORTED) { 114 throw new SpelEvaluationException(operand.getStartPosition(), SpelMessage.OPERAND_NOT_INCREMENTABLE); 115 } 116 else { 117 throw see; 118 } 119 } 120 121 if (!this.postfix) { 122 // The return value is the new value, not the original value 123 returnValue = newValue; 124 } 125 126 return returnValue; 127 } 128 129 @Override 130 public String toStringAST() { 131 return getLeftOperand().toStringAST() + "++"; 132 } 133 134 @Override 135 public SpelNodeImpl getRightOperand() { 136 return null; 137 } 138 139}