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.expression.EvaluationException;
023import org.springframework.expression.Operation;
024import org.springframework.expression.TypedValue;
025import org.springframework.expression.spel.ExpressionState;
026import org.springframework.util.NumberUtils;
027
028/**
029 * The power operator.
030 *
031 * @author Andy Clement
032 * @author Giovanni Dall'Oglio Risso
033 * @since 3.0
034 */
035public class OperatorPower extends Operator {
036
037        public OperatorPower(int pos, SpelNodeImpl... operands) {
038                super("^", pos, operands);
039        }
040
041
042        @Override
043        public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
044                SpelNodeImpl leftOp = getLeftOperand();
045                SpelNodeImpl rightOp = getRightOperand();
046
047                Object leftOperand = leftOp.getValueInternal(state).getValue();
048                Object rightOperand = rightOp.getValueInternal(state).getValue();
049
050                if (leftOperand instanceof Number && rightOperand instanceof Number) {
051                        Number leftNumber = (Number) leftOperand;
052                        Number rightNumber = (Number) rightOperand;
053
054                        if (leftNumber instanceof BigDecimal) {
055                                BigDecimal leftBigDecimal = NumberUtils.convertNumberToTargetClass(leftNumber, BigDecimal.class);
056                                return new TypedValue(leftBigDecimal.pow(rightNumber.intValue()));
057                        }
058                        else if (leftNumber instanceof BigInteger) {
059                                BigInteger leftBigInteger = NumberUtils.convertNumberToTargetClass(leftNumber, BigInteger.class);
060                                return new TypedValue(leftBigInteger.pow(rightNumber.intValue()));
061                        }
062                        else if (leftNumber instanceof Double || rightNumber instanceof Double) {
063                                return new TypedValue(Math.pow(leftNumber.doubleValue(), rightNumber.doubleValue()));
064                        }
065                        else if (leftNumber instanceof Float || rightNumber instanceof Float) {
066                                return new TypedValue(Math.pow(leftNumber.floatValue(), rightNumber.floatValue()));
067                        }
068
069                        double d = Math.pow(leftNumber.doubleValue(), rightNumber.doubleValue());
070                        if (d > Integer.MAX_VALUE || leftNumber instanceof Long || rightNumber instanceof Long) {
071                                return new TypedValue((long) d);
072                        }
073                        else {
074                                return new TypedValue((int) d);
075                        }
076                }
077
078                return state.operate(Operation.POWER, leftOperand, rightOperand);
079        }
080
081}