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