001/*
002// Licensed to Julian Hyde under one or more contributor license
003// agreements. See the NOTICE file distributed with this work for
004// additional information regarding copyright ownership.
005//
006// Julian Hyde licenses this file to you under the Apache License,
007// Version 2.0 (the "License"); you may not use this file except in
008// compliance with the License. You may obtain a copy of the License at:
009//
010// http://www.apache.org/licenses/LICENSE-2.0
011//
012// Unless required by applicable law or agreed to in writing, software
013// distributed under the License is distributed on an "AS IS" BASIS,
014// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015// See the License for the specific language governing permissions and
016// limitations under the License.
017*/
018package org.olap4j.mdx;
019
020import org.olap4j.type.Type;
021
022import java.io.PrintWriter;
023import java.util.List;
024
025/**
026 * Parse tree node which declares a calculated member. Represented as the
027 * <code>WITH MEMBER</code> clause of an MDX <code>SELECT</code> statement.
028 *
029 * @author jhyde
030 */
031public class WithMemberNode implements ParseTreeNode {
032
033    private final ParseRegion region;
034
035    /** name of set or member */
036    private final IdentifierNode name;
037
038    /** defining expression */
039    private ParseTreeNode expression;
040
041    // properties of member, such as SOLVE_ORDER
042    private final List<PropertyValueNode> memberPropertyList;
043
044    /**
045     * Constructs a formula specifying a member.
046     *
047     * @param region Source code region
048     * @param name   Name of member being declared
049     * @param exp    Expression for value of member
050     * @param memberPropertyList Collection of properties of member
051     */
052    public WithMemberNode(
053        ParseRegion region,
054        IdentifierNode name,
055        ParseTreeNode exp,
056        List<PropertyValueNode> memberPropertyList)
057    {
058        this.region = region;
059        this.name = name;
060        this.expression = exp;
061        this.memberPropertyList = memberPropertyList;
062    }
063
064    public ParseRegion getRegion() {
065        return region;
066    }
067
068    public void unparse(ParseTreeWriter writer) {
069        PrintWriter pw = writer.getPrintWriter();
070        pw.print("MEMBER ");
071        name.unparse(writer);
072        writer.indent();
073        pw.println(" AS");
074        // The MDX language, and olap4j's parser, allows formulas in calculated
075        // members and sets to be specified with and without single quotes.
076        expression.unparse(writer);
077        if (memberPropertyList != null) {
078            for (PropertyValueNode memberProperty : memberPropertyList) {
079                pw.print(", ");
080                memberProperty.unparse(writer);
081            }
082        }
083        writer.outdent();
084    }
085
086    /**
087     * Returns the name of the member declared.
088     *
089     * <p>The name is as specified in the parse tree; it may not be identical
090     * to the unique name of the member.
091     *
092     * @return Name of member
093     */
094    public IdentifierNode getIdentifier() {
095        return name;
096    }
097
098    /**
099     * Returns the expression to evaluate to calculate the member.
100     *
101     * @return expression
102     */
103    public ParseTreeNode getExpression() {
104        return expression;
105    }
106
107    /**
108     * Sets the expression to evaluate to calculate the member.
109     *
110     * @param expression Expression
111     */
112    public void setExpression(ParseTreeNode expression) {
113        this.expression = expression;
114    }
115
116
117    public <T> T accept(ParseTreeVisitor<T> visitor) {
118        T t = visitor.visit(this);
119        name.accept(visitor);
120        expression.accept(visitor);
121        return t;
122    }
123
124    public Type getType() {
125        // not an expression
126        throw new UnsupportedOperationException();
127    }
128
129    /**
130     * Returns the list of properties of this member.
131     *
132     * <p>The list may be empty, but is never null.
133     * Each entry is a (name, expression) pair.
134     *
135     * @return list of properties
136     */
137    public List<PropertyValueNode> getMemberPropertyList() {
138        return memberPropertyList;
139    }
140
141    public WithMemberNode deepCopy() {
142        return new WithMemberNode(
143            this.region, // immutable
144            this.name.deepCopy(),
145            this.expression.deepCopy(),
146            MdxUtil.deepCopyList(memberPropertyList));
147    }
148}
149
150// End WithMemberNode.java