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.util.List;
020
021import org.springframework.expression.EvaluationException;
022import org.springframework.expression.TypeComparator;
023import org.springframework.expression.spel.ExpressionState;
024import org.springframework.expression.spel.SpelEvaluationException;
025import org.springframework.expression.spel.SpelMessage;
026import org.springframework.expression.spel.support.BooleanTypedValue;
027
028/**
029 * Represents the between operator. The left operand to between must be a single value and
030 * the right operand must be a list - this operator returns true if the left operand is
031 * between (using the registered comparator) the two elements in the list. The definition
032 * of between being inclusive follows the SQL BETWEEN definition.
033 *
034 * @author Andy Clement
035 * @since 3.0
036 */
037public class OperatorBetween extends Operator {
038
039        public OperatorBetween(int pos, SpelNodeImpl... operands) {
040                super("between", pos, operands);
041        }
042
043
044        /**
045         * Returns a boolean based on whether a value is in the range expressed. The first
046         * operand is any value whilst the second is a list of two values - those two values
047         * being the bounds allowed for the first operand (inclusive).
048         * @param state the expression state
049         * @return true if the left operand is in the range specified, false otherwise
050         * @throws EvaluationException if there is a problem evaluating the expression
051         */
052        @Override
053        public BooleanTypedValue getValueInternal(ExpressionState state) throws EvaluationException {
054                Object left = getLeftOperand().getValueInternal(state).getValue();
055                Object right = getRightOperand().getValueInternal(state).getValue();
056                if (!(right instanceof List) || ((List<?>) right).size() != 2) {
057                        throw new SpelEvaluationException(getRightOperand().getStartPosition(),
058                                        SpelMessage.BETWEEN_RIGHT_OPERAND_MUST_BE_TWO_ELEMENT_LIST);
059                }
060
061                List<?> list = (List<?>) right;
062                Object low = list.get(0);
063                Object high = list.get(1);
064                TypeComparator comp = state.getTypeComparator();
065                try {
066                        return BooleanTypedValue.forValue(comp.compare(left, low) >= 0 && comp.compare(left, high) <= 0);
067                }
068                catch (SpelEvaluationException ex) {
069                        ex.setPosition(getStartPosition());
070                        throw ex;
071                }
072        }
073
074}