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