001 /*
002 // $Id: LiteralNode.java 404 2011-03-18 21:54:56Z lucboudreau $
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-2010 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.impl.Olap4jUtil;
013 import org.olap4j.type.*;
014
015 import java.io.PrintWriter;
016 import java.math.BigDecimal;
017
018 /**
019 * Represents a constant value, such as a string or number, in a parse tree.
020 *
021 * <p>Symbols, such as the <code>ASC</code> keyword in
022 * <code>Order([Store].Members, [Measures].[Unit Sales], ASC)</code>, are
023 * also represented as Literals.
024 *
025 * <p>A LiteralNode is immutable.
026 *
027 * @version $Id: LiteralNode.java 404 2011-03-18 21:54:56Z lucboudreau $
028 * @author jhyde
029 */
030 public class LiteralNode implements ParseTreeNode {
031
032 // Data members.
033
034 private final Object value;
035 private final Type type;
036 private final ParseRegion region;
037
038 /**
039 * Private constructor.
040 *
041 * <p>Use the creation methods {@link #createString} etc.
042 *
043 * @param region Region of source code
044 * @param type Type of this literal; must not be null
045 * @param value Value of this literal, must be null only if this is the
046 * null literal
047 */
048 private LiteralNode(
049 ParseRegion region,
050 Type type,
051 Object value)
052 {
053 assert type != null;
054 assert (type instanceof NullType) == (value == null);
055 assert (type instanceof StringType || type instanceof SymbolType)
056 == (value instanceof String);
057 assert (type instanceof NumericType) == (value instanceof BigDecimal);
058 this.region = region;
059 this.type = type;
060 this.value = value;
061 }
062
063 /**
064 * Creates a literal with the NULL value.
065 *
066 * @param region Region of source code
067 * @return literal representing the NULL value
068 */
069 public static LiteralNode createNull(ParseRegion region) {
070 return new LiteralNode(region, new NullType(), null);
071 }
072
073 /**
074 * Creates a string literal.
075 *
076 * @param region Region of source code
077 * @param value String value
078 *
079 * @return literal representing the string value
080 *
081 * @see #createSymbol
082 */
083 public static LiteralNode createString(
084 ParseRegion region,
085 String value)
086 {
087 if (value == null) {
088 throw new IllegalArgumentException("value must not be null");
089 }
090 return new LiteralNode(region, new StringType(), value);
091 }
092
093 /**
094 * Creates a symbol literal.
095 *
096 * @param region Region of source code
097 * @param value Name of symbol
098 *
099 * @return literal representing the symbol value
100 *
101 * @see #createString
102 */
103 public static LiteralNode createSymbol(
104 ParseRegion region,
105 String value)
106 {
107 if (value == null) {
108 throw new IllegalArgumentException("value must not be null");
109 }
110 return new LiteralNode(region, new SymbolType(), value);
111 }
112
113 /**
114 * Creates a numeric literal.
115 *
116 * @param region Region of source code
117 * @param value Value of literal; must not be null
118 * @param approximate Whether the literal is approximate
119 *
120 * @return literal representing the integer value
121 */
122 public static LiteralNode createNumeric(
123 ParseRegion region,
124 BigDecimal value,
125 boolean approximate)
126 {
127 if (value == null) {
128 throw new IllegalArgumentException("value must not be null");
129 }
130 Olap4jUtil.discard(approximate); // reserved for future use
131 return new LiteralNode(region, new NumericType(), value);
132 }
133
134 public <T> T accept(ParseTreeVisitor<T> visitor) {
135 return visitor.visit(this);
136 }
137
138 public Type getType() {
139 return type;
140 }
141
142 public ParseRegion getRegion() {
143 return region;
144 }
145
146 /**
147 * Returns the value of this literal.
148 *
149 * <p>Value is always of type {@link String} (if the literal is a string or
150 * a symbol), of type {@link java.math.BigDecimal} (if the literal is
151 * numeric), or null (if the literal is of null type).
152 *
153 * @return value
154 */
155 public Object getValue() {
156 return value;
157 }
158
159 public void unparse(ParseTreeWriter writer) {
160 PrintWriter pw = writer.getPrintWriter();
161 if (value == null) {
162 pw.print("NULL");
163 } else if (type instanceof SymbolType) {
164 pw.print(value);
165 } else if (type instanceof NumericType) {
166 pw.print(value);
167 } else if (type instanceof StringType) {
168 pw.print(MdxUtil.quoteForMdx((String) value));
169 } else {
170 throw new AssertionError("unexpected literal type " + type);
171 }
172 }
173
174 public LiteralNode deepCopy() {
175 // No need to copy: literal nodes are immutable.
176 return this;
177 }
178
179 }
180
181 // End LiteralNode.java