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 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 org.springframework.expression.TypedValue;
020import org.springframework.expression.spel.ExpressionState;
021import org.springframework.expression.spel.InternalParseException;
022import org.springframework.expression.spel.SpelEvaluationException;
023import org.springframework.expression.spel.SpelMessage;
024import org.springframework.expression.spel.SpelParseException;
025import org.springframework.lang.Nullable;
026
027/**
028 * Common superclass for nodes representing literals (boolean, string, number, etc).
029 *
030 * @author Andy Clement
031 * @author Juergen Hoeller
032 */
033public abstract class Literal extends SpelNodeImpl {
034
035        @Nullable
036        private final String originalValue;
037
038
039        public Literal(@Nullable String originalValue, int startPos, int endPos) {
040                super(startPos, endPos);
041                this.originalValue = originalValue;
042        }
043
044
045        @Nullable
046        public final String getOriginalValue() {
047                return this.originalValue;
048        }
049
050        @Override
051        public final TypedValue getValueInternal(ExpressionState state) throws SpelEvaluationException {
052                return getLiteralValue();
053        }
054
055        @Override
056        public String toString() {
057                return String.valueOf(getLiteralValue().getValue());
058        }
059
060        @Override
061        public String toStringAST() {
062                return toString();
063        }
064
065
066        public abstract TypedValue getLiteralValue();
067
068
069        /**
070         * Process the string form of a number, using the specified base if supplied
071         * and return an appropriate literal to hold it. Any suffix to indicate a
072         * long will be taken into account (either 'l' or 'L' is supported).
073         * @param numberToken the token holding the number as its payload (eg. 1234 or 0xCAFE)
074         * @param radix the base of number
075         * @return a subtype of Literal that can represent it
076         */
077        public static Literal getIntLiteral(String numberToken, int startPos, int endPos, int radix) {
078                try {
079                        int value = Integer.parseInt(numberToken, radix);
080                        return new IntLiteral(numberToken, startPos, endPos, value);
081                }
082                catch (NumberFormatException ex) {
083                        throw new InternalParseException(new SpelParseException(startPos, ex, SpelMessage.NOT_AN_INTEGER, numberToken));
084                }
085        }
086
087        public static Literal getLongLiteral(String numberToken, int startPos, int endPos, int radix) {
088                try {
089                        long value = Long.parseLong(numberToken, radix);
090                        return new LongLiteral(numberToken, startPos, endPos, value);
091                }
092                catch (NumberFormatException ex) {
093                        throw new InternalParseException(new SpelParseException(startPos, ex, SpelMessage.NOT_A_LONG, numberToken));
094                }
095        }
096
097        public static Literal getRealLiteral(String numberToken, int startPos, int endPos, boolean isFloat) {
098                try {
099                        if (isFloat) {
100                                float value = Float.parseFloat(numberToken);
101                                return new FloatLiteral(numberToken, startPos, endPos, value);
102                        }
103                        else {
104                                double value = Double.parseDouble(numberToken);
105                                return new RealLiteral(numberToken, startPos, endPos, value);
106                        }
107                }
108                catch (NumberFormatException ex) {
109                        throw new InternalParseException(new SpelParseException(startPos, ex, SpelMessage.NOT_A_REAL, numberToken));
110                }
111        }
112
113}