001 /*
002 // $Id: LiteralNode.java 229 2009-05-08 19:11:29Z jhyde $
003 // This software is subject to the terms of the Eclipse Public License v1.0
004 // Agreement, available at the following URL:
005 // http://www.eclipse.org/legal/epl-v10.html.
006 // Copyright (C) 2007-2008 Julian Hyde
007 // All Rights Reserved.
008 // You must accept the terms of that agreement to use this software.
009 */
010 package org.olap4j.mdx;
011
012 import org.olap4j.type.*;
013
014 import java.io.PrintWriter;
015
016 /**
017 * Represents a constant value, such as a string or number, in a parse tree.
018 *
019 * <p>Symbols, such as the <code>ASC</code> keyword in
020 * <code>Order([Store].Members, [Measures].[Unit Sales], ASC)</code>, are
021 * also represented as Literals.
022 *
023 * <p>A LiteralNode is immutable.
024 *
025 * @version $Id: LiteralNode.java 229 2009-05-08 19:11:29Z jhyde $
026 * @author jhyde
027 */
028 public class LiteralNode implements ParseTreeNode {
029
030 // Data members.
031
032 private final Object value;
033 private final Type type;
034 private final ParseRegion region;
035
036 /**
037 * Private constructor.
038 *
039 * <p>Use the creation methods {@link #createString} etc.
040 *
041 * @param region Region of source code
042 * @param type Type of this literal; must not be null
043 * @param value Value of this literal, must be null only if this is the
044 * null literal
045 */
046 private LiteralNode(
047 ParseRegion region,
048 Type type,
049 Object value)
050 {
051 assert type != null;
052 assert (type instanceof NullType) == (value == null);
053 this.region = region;
054 this.type = type;
055 this.value = value;
056 }
057
058 /**
059 * Creates a literal with the NULL value.
060 *
061 * @param region Region of source code
062 * @return literal representing the NULL value
063 */
064 public static LiteralNode createNull(ParseRegion region) {
065 return new LiteralNode(region, new NullType(), null);
066 }
067
068 /**
069 * Creates a string literal.
070 *
071 * @param region Region of source code
072 * @param value String value
073 *
074 * @return literal representing the string value
075 *
076 * @see #createSymbol
077 */
078 public static LiteralNode createString(
079 ParseRegion region,
080 String value)
081 {
082 if (value == null) {
083 throw new IllegalArgumentException("value must not be null");
084 }
085 return new LiteralNode(region, new StringType(), value);
086 }
087
088 /**
089 * Creates a symbol literal.
090 *
091 * @param region Region of source code
092 * @param value Name of symbol
093 *
094 * @return literal representing the symbol value
095 *
096 * @see #createString
097 */
098 public static LiteralNode createSymbol(
099 ParseRegion region,
100 String value)
101 {
102 if (value == null) {
103 throw new IllegalArgumentException("value must not be null");
104 }
105 return new LiteralNode(region, new SymbolType(), value);
106 }
107
108 /**
109 * Creates a floating-point numeric literal.
110 *
111 * @param region Region of source code
112 * @param value Value of literal; must not be null
113 *
114 * @return literal representing the floating-point value
115 */
116 public static LiteralNode create(
117 ParseRegion region,
118 Double value)
119 {
120 if (value == null) {
121 throw new IllegalArgumentException("value must not be null");
122 }
123 return new LiteralNode(region, new NumericType(), value);
124 }
125
126 /**
127 * Creates an integer literal.
128 *
129 * @param region Region of source code
130 * @param value Value of literal; must not be null
131 *
132 * @return literal representing the integer value
133 */
134 public static LiteralNode create(
135 ParseRegion region,
136 Integer value)
137 {
138 if (value == null) {
139 throw new IllegalArgumentException("value must not be null");
140 }
141 return new LiteralNode(region, new NumericType(), value);
142 }
143
144 public <T> T accept(ParseTreeVisitor<T> visitor) {
145 return visitor.visit(this);
146 }
147
148 public Type getType() {
149 return type;
150 }
151
152 public ParseRegion getRegion() {
153 return region;
154 }
155
156 /**
157 * Returns the value of this literal.
158 *
159 * @return value
160 */
161 public Object getValue() {
162 return value;
163 }
164
165 public void unparse(ParseTreeWriter writer) {
166 PrintWriter pw = writer.getPrintWriter();
167 if (value == null) {
168 pw.print("NULL");
169 } else if (type instanceof SymbolType) {
170 pw.print(value);
171 } else if (type instanceof NumericType) {
172 pw.print(value);
173 } else if (type instanceof StringType) {
174 pw.print(MdxUtil.quoteForMdx((String) value));
175 } else {
176 throw new AssertionError("unexpected literal type " + type);
177 }
178 }
179
180 public LiteralNode deepCopy() {
181 // No need to copy: literal nodes are immutable.
182 return this;
183 }
184
185 }
186
187 // End LiteralNode.java