001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.jexl2.parser;
018    
019    import java.math.BigDecimal;
020    import java.math.BigInteger;
021    
022    public class ASTNumberLiteral extends JexlNode implements JexlNode.Literal<Number> {
023        /** The type literal value. */
024        Number literal = null;
025        /** The expected class. */
026        Class<?> clazz = null;
027    
028        public ASTNumberLiteral(int id) {
029            super(id);
030        }
031    
032        public ASTNumberLiteral(Parser p, int id) {
033            super(p, id);
034        }
035    
036        /**
037         * Gets the literal value.
038         * @return the number literal
039         */
040        public Number getLiteral() {
041            return literal;
042        }
043        
044        /** {@inheritDoc} */
045        @Override
046        protected boolean isConstant(boolean literal) {
047            return true;
048        }
049    
050        /** {@inheritDoc} */
051        @Override
052        public Object jjtAccept(ParserVisitor visitor, Object data) {
053            return visitor.visit(this, data);
054        }
055    
056        public Class<?> getLiteralClass() {
057            return clazz;
058        }
059    
060        public boolean isInteger() {
061            return Integer.class.equals(clazz);
062        }
063    
064        /**
065         * Sets this node as a natural literal.
066         * Originally from OGNL.
067         * @param s the natural as string
068         */
069        public void setNatural(String s) {
070            Number result;
071            Class<?> rclass;
072            // determine the base
073            final int base;
074            if (s.charAt(0) == '0') {
075                if ((s.length() > 1 && (s.charAt(1) == 'x' || s.charAt(1) == 'X'))) {
076                    base = 16;
077                    s = s.substring(2); // Trim the 0x off the front
078                } else {
079                    base = 8;
080                }
081            } else {
082                base = 10;
083            }
084            final int last = s.length() - 1;
085            switch (s.charAt(last)) {
086                case 'l':
087                case 'L': {
088                    rclass = Long.class;
089                    result = Long.valueOf(s.substring(0, last), base);
090                    break;
091                }
092                case 'h':
093                case 'H': {
094                    rclass = BigInteger.class;
095                    result = new BigInteger(s.substring(0, last), base);
096                    break;
097                }
098                default: {
099                    rclass = Integer.class;
100                    try {
101                        result = Integer.valueOf(s, base);
102                    } catch (NumberFormatException take2) {
103                        try {
104                            result = Long.valueOf(s, base);
105                        } catch (NumberFormatException take3) {
106                            result = new BigInteger(s, base);
107                        }
108                    }
109                }
110            }
111            literal = result;
112            clazz = rclass;
113        }
114    
115        /**
116         * Sets this node as a real literal.
117         * Originally from OGNL.
118         * @param s the real as string
119         */
120        public void setReal(String s) {
121            Number result;
122            Class<?> rclass;
123            final int last = s.length() - 1;
124            switch (s.charAt(last)) {
125                case 'b':
126                case 'B': {
127                    result = new BigDecimal(s.substring(0, last));
128                    rclass = BigDecimal.class;
129                    break;
130                }
131                case 'd':
132                case 'D': {
133                    rclass = Double.class;
134                    result = Double.valueOf(s);
135                    break;
136                }
137                case 'f':
138                case 'F':
139                default: {
140                    rclass = Float.class;
141                    try {
142                        result = Float.valueOf(s);
143                    } catch (NumberFormatException take2) {
144                        try {
145                            result = Double.valueOf(s);
146                        } catch (NumberFormatException take3) {
147                            result = new BigDecimal(s);
148                        }
149                    }
150                    break;
151                }
152            }
153            literal = result;
154            clazz = rclass;
155        }
156    }