001/*
002 * Copyright 2002-2014 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.asm.MethodVisitor;
023import org.springframework.expression.EvaluationException;
024import org.springframework.expression.spel.CodeFlow;
025import org.springframework.expression.spel.ExpressionState;
026import org.springframework.expression.spel.support.BooleanTypedValue;
027import org.springframework.util.NumberUtils;
028
029/**
030 * Implements greater-than-or-equal operator.
031 *
032 * @author Andy Clement
033 * @author Juergen Hoeller
034 * @author Giovanni Dall'Oglio Risso
035 * @since 3.0
036 */
037public class OpGE extends Operator {
038
039        public OpGE(int pos, SpelNodeImpl... operands) {
040                super(">=", pos, operands);
041                this.exitTypeDescriptor = "Z";
042        }
043
044
045        @Override
046        public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
047                Object left = getLeftOperand().getValueInternal(state).getValue();
048                Object right = getRightOperand().getValueInternal(state).getValue();
049
050                this.leftActualDescriptor = CodeFlow.toDescriptorFromObject(left);
051                this.rightActualDescriptor = CodeFlow.toDescriptorFromObject(right);
052                
053                if (left instanceof Number && right instanceof Number) {
054                        Number leftNumber = (Number) left;
055                        Number rightNumber = (Number) right;
056
057                        if (leftNumber instanceof BigDecimal || rightNumber instanceof BigDecimal) {
058                                BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
059                                BigDecimal rightBigDecimal = NumberUtils.convertNumberToTargetClass(rightNumber, BigDecimal.class);
060                                return BooleanTypedValue.forValue(leftBigDecimal.compareTo(rightBigDecimal) >= 0);
061                        }
062                        else if (leftNumber instanceof Double || rightNumber instanceof Double) {
063                                return BooleanTypedValue.forValue(leftNumber.doubleValue() >= rightNumber.doubleValue());
064                        }
065                        else if (leftNumber instanceof Float || rightNumber instanceof Float) {
066                                return BooleanTypedValue.forValue(leftNumber.floatValue() >= rightNumber.floatValue());
067                        }
068                        else if (leftNumber instanceof BigInteger || rightNumber instanceof BigInteger) {
069                                BigInteger leftBigInteger = NumberUtils.convertNumberToTargetClass(leftNumber, BigInteger.class);
070                                BigInteger rightBigInteger = NumberUtils.convertNumberToTargetClass(rightNumber, BigInteger.class);
071                                return BooleanTypedValue.forValue(leftBigInteger.compareTo(rightBigInteger) >= 0);
072                        }
073                        else if (leftNumber instanceof Long || rightNumber instanceof Long) {
074                                return BooleanTypedValue.forValue(leftNumber.longValue() >= rightNumber.longValue());
075                        }
076                        else if (leftNumber instanceof Integer || rightNumber instanceof Integer) {
077                                return BooleanTypedValue.forValue(leftNumber.intValue() >= rightNumber.intValue());
078                        }
079                        else if (leftNumber instanceof Short || rightNumber instanceof Short) {
080                                return BooleanTypedValue.forValue(leftNumber.shortValue() >= rightNumber.shortValue());
081                        }
082                        else if (leftNumber instanceof Byte || rightNumber instanceof Byte) {
083                                return BooleanTypedValue.forValue(leftNumber.byteValue() >= rightNumber.byteValue());
084                        }
085                        else {
086                                // Unknown Number subtypes -> best guess is double comparison
087                                return BooleanTypedValue.forValue(leftNumber.doubleValue() >= rightNumber.doubleValue());
088                        }
089                }
090
091                return BooleanTypedValue.forValue(state.getTypeComparator().compare(left, right) >= 0);
092        }
093        
094        @Override
095        public boolean isCompilable() {
096                return isCompilableOperatorUsingNumerics();
097        }
098        
099        @Override
100        public void generateCode(MethodVisitor mv, CodeFlow cf) {
101                generateComparisonCode(mv, cf, IFLT, IF_ICMPLT);
102        }
103
104}