001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap/Literal.java#23 $
003    // This software is subject to the terms of the Common Public License
004    // Agreement, available at the following URL:
005    // http://www.opensource.org/licenses/cpl.html.
006    // Copyright (C) 1998-2002 Kana Software, Inc.
007    // Copyright (C) 2001-2008 Julian Hyde and others
008    // All Rights Reserved.
009    // You must accept the terms of that agreement to use this software.
010    //
011    // jhyde, 21 January, 1999
012    */
013    
014    package mondrian.olap;
015    import mondrian.olap.type.*;
016    import mondrian.calc.*;
017    import mondrian.calc.impl.ConstantCalc;
018    import mondrian.mdx.MdxVisitor;
019    
020    import java.io.PrintWriter;
021    
022    /**
023     * Represents a constant value, such as a string or number, in a parse tree.
024     *
025     * <p>Symbols, such as the <code>ASC</code> keyword in
026     * <code>Order([Store].Members, [Measures].[Unit Sales], ASC)</code>, are
027     * also represented as Literals.
028     *
029     * @version $Id: //open/mondrian/src/main/mondrian/olap/Literal.java#23 $
030     * @author jhyde
031     */
032    public class Literal extends ExpBase {
033    
034        // Data members.
035    
036        public final int category;
037        private final Object o;
038    
039    
040        // Constants for commonly used literals.
041    
042        public static final Literal nullValue = new Literal(Category.Null, null);
043    
044        public static final Literal emptyString = new Literal("", false);
045    
046        public static final Literal zero = new Literal(0);
047    
048        public static final Literal one = new Literal(1);
049    
050        public static final Literal negativeOne = new Literal(-1);
051    
052        public static final Literal doubleZero = new Literal(0.0);
053    
054        public static final Literal doubleOne = new Literal(1.0);
055    
056        public static final Literal doubleNegativeOne = new Literal(-1.0);
057    
058        /**
059         * Private constructor.
060         *
061         * <p>Use the creation methods {@link #createString(String)} etc.
062         */
063        private Literal(int type, Object o) {
064            this.category = type;
065            this.o = o;
066        }
067    
068        /**
069         * Creates a string literal.
070         * @see #createSymbol
071         */
072        public static Literal createString(String s) {
073            return (s.equals(""))
074                ? emptyString
075                : new Literal(s, false);
076        }
077    
078        /**
079         * Creates a symbol.
080         * @see #createString
081         */
082        public static Literal createSymbol(String s) {
083            return new Literal(s, true);
084        }
085    
086        /**
087         * Creates a numeric literal.
088         */
089        public static Literal create(Double d) {
090            double dv = d.doubleValue();
091            if (dv == 0.0) {
092                return doubleZero;
093            } else if (dv == 1.0) {
094                return doubleOne;
095            } else if (dv == -1.0) {
096                return doubleNegativeOne;
097            } else {
098                return new Literal(d);
099            }
100        }
101    
102        /**
103         * Creates an integer literal.
104         */
105        public static Literal create(Integer i) {
106            switch (i) {
107            case -1:
108                return negativeOne;
109            case 0:
110                return zero;
111            case 1:
112                return one;
113            default:
114                return new Literal(i);
115            }
116        }
117    
118        private Literal(String s, boolean isSymbol) {
119            this.o = s;
120            this.category = isSymbol ? Category.Symbol : Category.String;
121        }
122    
123        private Literal(Double d) {
124            this.o = d;
125            this.category = Category.Numeric;
126        }
127        private Literal(Integer i) {
128            this.o = i;
129            this.category = Category.Numeric;
130        }
131    
132        public Literal clone() {
133            return this;
134        }
135    
136        public void unparse(PrintWriter pw) {
137            switch (category) {
138            case Category.Symbol:
139            case Category.Numeric:
140                pw.print(o);
141                break;
142            case Category.String:
143                pw.print(Util.quoteForMdx((String) o));
144                break;
145            case Category.Null:
146                pw.print("NULL");
147                break;
148            default:
149                throw Util.newInternal("bad literal type " + category);
150            }
151        }
152    
153        public int getCategory() {
154            return category;
155        }
156    
157        public Type getType() {
158            switch (category) {
159            case Category.Symbol:
160                return new SymbolType();
161            case Category.Numeric:
162                return new NumericType();
163            case Category.String:
164                return new StringType();
165            case Category.Null:
166                return new NullType();
167            default:
168                throw Category.instance.badValue(category);
169            }
170        }
171    
172        public Exp accept(Validator validator) {
173            return this;
174        }
175    
176        public Calc accept(ExpCompiler compiler) {
177            return new ConstantCalc(getType(), o);
178        }
179    
180        public Object accept(MdxVisitor visitor) {
181            return visitor.visit(this);
182        }
183    
184        public Object getValue() {
185            return o;
186        }
187    
188        public int getIntValue() {
189            if (o instanceof Number) {
190                return ((Number) o).intValue();
191            } else {
192                throw Util.newInternal("cannot convert " + o + " to int");
193            }
194        }
195    
196    }
197    
198    // End Literal.java