View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.expression.spel.ast;
18  
19  import java.math.BigDecimal;
20  import java.math.BigInteger;
21  
22  import org.springframework.expression.EvaluationException;
23  import org.springframework.expression.Operation;
24  import org.springframework.expression.TypedValue;
25  import org.springframework.expression.spel.ExpressionState;
26  import org.springframework.expression.spel.SpelEvaluationException;
27  import org.springframework.expression.spel.SpelMessage;
28  import org.springframework.util.Assert;
29  
30  /**
31   * Increment operator. Can be used in a prefix or postfix form. This will throw
32   * appropriate exceptions if the operand in question does not support increment.
33   *
34   * @author Andy Clement
35   * @author Juergen Hoeller
36   * @author Giovanni Dall'Oglio Risso
37   * @since 3.2
38   */
39  public class OpInc extends Operator {
40  
41  	private final boolean postfix;  // false means prefix
42  
43  
44  	public OpInc(int pos, boolean postfix, SpelNodeImpl... operands) {
45  		super("++", pos, operands);
46  		Assert.notEmpty(operands);
47  		this.postfix = postfix;
48  	}
49  
50  
51  	@Override
52  	public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
53  		SpelNodeImpl operand = getLeftOperand();
54  		ValueRef valueRef = operand.getValueRef(state);
55  
56  		TypedValue typedValue = valueRef.getValue();
57  		Object value = typedValue.getValue();
58  		TypedValue returnValue = typedValue;
59  		TypedValue newValue = null;
60  
61  		if (value instanceof Number) {
62  			Number op1 = (Number) value;
63  			if (op1 instanceof BigDecimal) {
64  				newValue = new TypedValue(((BigDecimal) op1).add(BigDecimal.ONE), typedValue.getTypeDescriptor());
65  			}
66  			else if (op1 instanceof Double) {
67  				newValue = new TypedValue(op1.doubleValue() + 1.0d, typedValue.getTypeDescriptor());
68  			}
69  			else if (op1 instanceof Float) {
70  				newValue = new TypedValue(op1.floatValue() + 1.0f, typedValue.getTypeDescriptor());
71  			}
72  			else if (op1 instanceof BigInteger) {
73  				newValue = new TypedValue(((BigInteger) op1).add(BigInteger.ONE), typedValue.getTypeDescriptor());
74  			}
75  			else if (op1 instanceof Long) {
76  				newValue = new TypedValue(op1.longValue() + 1L, typedValue.getTypeDescriptor());
77  			}
78  			else if (op1 instanceof Integer) {
79  				newValue = new TypedValue(op1.intValue() + 1, typedValue.getTypeDescriptor());
80  			}
81  			else if (op1 instanceof Short) {
82  				newValue = new TypedValue(op1.shortValue() + (short) 1, typedValue.getTypeDescriptor());
83  			}
84  			else if (op1 instanceof Byte) {
85  				newValue = new TypedValue(op1.byteValue() + (byte) 1, typedValue.getTypeDescriptor());
86  			}
87  			else {
88  				// Unknown Number subtype -> best guess is double increment
89  				newValue = new TypedValue(op1.doubleValue() + 1.0d, typedValue.getTypeDescriptor());
90  			}
91  		}
92  
93  		if (newValue == null) {
94  			try {
95  				newValue = state.operate(Operation.ADD, returnValue.getValue(), 1);
96  			}
97  			catch (SpelEvaluationException ex) {
98  				if (ex.getMessageCode() == SpelMessage.OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES) {
99  					// 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 }