001/*002 * Copyright 2002-2019 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 at007 *008 * https://www.apache.org/licenses/LICENSE-2.0009 *010 * Unless required by applicable law or agreed to in writing, software011 * 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 and014 * limitations under the License.015 */016017package org.springframework.expression.spel.ast;018019import java.math.BigDecimal;020import java.math.BigInteger;021022import org.springframework.asm.MethodVisitor;023import org.springframework.expression.EvaluationException;024import org.springframework.expression.Operation;025import org.springframework.expression.TypedValue;026import org.springframework.expression.spel.CodeFlow;027import org.springframework.expression.spel.ExpressionState;028import org.springframework.util.Assert;029import org.springframework.util.NumberUtils;030031/**032 * The minus operator supports:033 * <ul>034 * <li>subtraction of numbers035 * <li>subtraction of an int from a string of one character036 * (effectively decreasing that character), so 'd'-3='a'037 * </ul>038 *039 * <p>It can be used as a unary operator for numbers.040 * The standard promotions are performed when the operand types vary (double-int=double).041 * For other options it defers to the registered overloader.042 *043 * @author Andy Clement044 * @author Juergen Hoeller045 * @author Giovanni Dall'Oglio Risso046 * @since 3.0047 */048public class OpMinus extends Operator {049050 public OpMinus(int startPos, int endPos, SpelNodeImpl... operands) {051 super("-", startPos, endPos, operands);052 }053054055 @Override056 public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {057 SpelNodeImpl leftOp = getLeftOperand();058059 if (this.children.length < 2) { // if only one operand, then this is unary minus060 Object operand = leftOp.getValueInternal(state).getValue();061 if (operand instanceof Number) {062 if (operand instanceof BigDecimal) {063 return new TypedValue(((BigDecimal) operand).negate());064 }065 else if (operand instanceof Double) {066 this.exitTypeDescriptor = "D";067 return new TypedValue(0 - ((Number) operand).doubleValue());068 }069 else if (operand instanceof Float) {070 this.exitTypeDescriptor = "F";071 return new TypedValue(0 - ((Number) operand).floatValue());072 }073