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.asm.MethodVisitor;
23  import org.springframework.expression.EvaluationException;
24  import org.springframework.expression.spel.CodeFlow;
25  import org.springframework.expression.spel.ExpressionState;
26  import org.springframework.expression.spel.support.BooleanTypedValue;
27  import org.springframework.util.NumberUtils;
28  
29  /**
30   * Implements the less-than operator.
31   *
32   * @author Andy Clement
33   * @author Juergen Hoeller
34   * @author Giovanni Dall'Oglio Risso
35   * @since 3.0
36   */
37  public class OpLT extends Operator {
38  
39  	public OpLT(int pos, SpelNodeImpl... operands) {
40  		super("<", pos, operands);
41  		this.exitTypeDescriptor = "Z";
42  	}
43  
44  
45  	@Override
46  	public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
47  		Object left = getLeftOperand().getValueInternal(state).getValue();
48  		Object right = getRightOperand().getValueInternal(state).getValue();
49  
50  		this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left);
51  		this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right);
52  
53  		if (left instanceof Number && right instanceof Number) {
54  			Number leftNumber = (Number) left;
55  			Number rightNumber = (Number) right;
56  
57  			if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
58  				BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
59  				BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);
60  				return BooleanTypedValue.forValue(leftBigDecimal.compareTo(rightBigDecimal) < 0);
61  			}
62  			else if (leftNumber instanceof Double || rightNumber instanceof Double) {
63  				return BooleanTypedValue.forValue(leftNumber.doubleValue() < rightNumber.doubleValue());
64  			}
65  			else if (leftNumber instanceof Float || rightNumber instanceof Float) {
66  				return BooleanTypedValue.forValue(leftNumber.floatValue() < rightNumber.floatValue());
67  			}
68  			else if (leftNumber instanceof BigInteger || rightNumber instanceof BigInteger) {
69  				BigInteger leftBigInteger = NumberUtils.convertNumberToTargetClass(leftNumber, BigInteger.class);
70  				BigInteger rightBigInteger = NumberUtils.convertNumberToTargetClass(rightNumber, BigInteger.class);
71  				return BooleanTypedValue.forValue(leftBigInteger.compareTo(rightBigInteger) < 0);
72  			}
73  			else if (leftNumber instanceof Long || rightNumber instanceof Long) {
74  				return BooleanTypedValue.forValue(leftNumber.longValue() < rightNumber.longValue());
75  			}
76  			else if (leftNumber instanceof Integer || rightNumber instanceof Integer) {
77  				return BooleanTypedValue.forValue(leftNumber.intValue() < rightNumber.intValue());
78  			}
79  			else if (leftNumber instanceof Short || rightNumber instanceof Short) {
80  				return BooleanTypedValue.forValue(leftNumber.shortValue() < rightNumber.shortValue());
81  			}
82  			else if (leftNumber instanceof Byte || rightNumber instanceof Byte) {
83  				return BooleanTypedValue.forValue(leftNumber.byteValue() < rightNumber.byteValue());
84  			}
85  			else {
86  				// Unknown Number subtypes -> best guess is double comparison
87  				return BooleanTypedValue.forValue(leftNumber.doubleValue() < rightNumber.doubleValue());
88  			}
89  		}
90  
91  		if (left instanceof CharSequence && right instanceof CharSequence) {
92  			left = left.toString();
93  			right = right.toString();
94  		}
95  
96  		return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) < 0);
97  	}
98  	
99  	@Override
100 	public boolean isCompilable() {
101 		return isCompilableOperatorUsingNumerics();
102 	}
103 	
104 	@Override
105 	public void generateCode(MethodVisitor mv, CodeFlow cf) {
106 		generateComparisonCode(mv, cf, IFGE, IF_ICMPGE);
107 	}
108 
109 }