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