001 /*
002 // $Id: AxisNode.java 482 2012-01-05 23:27:27Z jhyde $
003 //
004 // Licensed to Julian Hyde under one or more contributor license
005 // agreements. See the NOTICE file distributed with this work for
006 // additional information regarding copyright ownership.
007 //
008 // Julian Hyde licenses this file to you under the Apache License,
009 // Version 2.0 (the "License"); you may not use this file except in
010 // compliance with the License. You may obtain a copy of the License at:
011 //
012 // http://www.apache.org/licenses/LICENSE-2.0
013 //
014 // Unless required by applicable law or agreed to in writing, software
015 // distributed under the License is distributed on an "AS IS" BASIS,
016 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 // See the License for the specific language governing permissions and
018 // limitations under the License.
019 */
020 package org.olap4j.mdx;
021
022 import org.olap4j.Axis;
023 import org.olap4j.type.Type;
024
025 import java.io.PrintWriter;
026 import java.util.Collections;
027 import java.util.List;
028
029 /**
030 * An axis in an MDX query. For example, the typical MDX query has two axes,
031 * which appear as the "ON COLUMNS" and "ON ROWS" clauses.
032 *
033 * @version $Id: AxisNode.java 482 2012-01-05 23:27:27Z jhyde $
034 */
035 public class AxisNode implements ParseTreeNode {
036
037 private final ParseRegion region;
038 private boolean nonEmpty;
039 private ParseTreeNode expression;
040 private final Axis axis;
041
042 private final List<IdentifierNode> dimensionProperties;
043
044 /**
045 * Creates an axis.
046 *
047 * @param region Region of source code
048 * @param nonEmpty Whether to filter out members of this axis whose cells
049 * are all empty
050 * @param axis Which axis (ROWS, COLUMNS, etc.)
051 * @param dimensionProperties List of dimension properties; if null,
052 * empty list is assumed
053 * @param expression Expression to populate the axis
054 */
055 public AxisNode(
056 ParseRegion region,
057 boolean nonEmpty,
058 Axis axis,
059 List<IdentifierNode> dimensionProperties,
060 ParseTreeNode expression)
061 {
062 this.region = region;
063 this.nonEmpty = nonEmpty;
064 this.expression = expression;
065 this.axis = axis;
066 if (axis == null) {
067 throw new IllegalArgumentException("Axis type must not be null");
068 }
069 if (dimensionProperties == null) {
070 dimensionProperties = Collections.emptyList();
071 }
072 this.dimensionProperties = dimensionProperties;
073 }
074
075 public ParseRegion getRegion() {
076 return region;
077 }
078
079 public <T> T accept(ParseTreeVisitor<T> visitor) {
080 final T o = visitor.visit(this);
081
082 // visit the expression which forms the axis
083 expression.accept(visitor);
084
085 return o;
086 }
087
088 /**
089 * Returns the name of the axis this axis expression is populating.
090 *
091 * @return axis name
092 */
093 public Axis getAxis() {
094 return axis;
095 }
096
097 /**
098 * Returns whether the axis has the <code>NON EMPTY</code> property set.
099 *
100 * @return whether the axis is NON EMPTY
101 */
102 public boolean isNonEmpty() {
103 return nonEmpty;
104 }
105
106 /**
107 * Sets whether the axis has the <code>NON EMPTY</code> property set.
108 *
109 * See {@link #isNonEmpty()}.
110 *
111 * @param nonEmpty whether the axis is NON EMPTY
112 */
113 public void setNonEmpty(boolean nonEmpty) {
114 this.nonEmpty = nonEmpty;
115 }
116
117 /**
118 * Returns the expression which is used to compute the value of this axis.
119 *
120 * @return the expression which is used to compute the value of this axis
121 */
122 public ParseTreeNode getExpression() {
123 return expression;
124 }
125
126 /**
127 * Sets the expression which is used to compute the value of this axis.
128 * See {@link #getExpression()}.
129 *
130 * @param expr the expression which is used to compute the value of this
131 * axis
132 */
133 public void setExpression(ParseTreeNode expr) {
134 this.expression = expr;
135 }
136
137 public void unparse(ParseTreeWriter writer) {
138 PrintWriter pw = writer.getPrintWriter();
139 if (nonEmpty) {
140 pw.print("NON EMPTY ");
141 }
142 if (expression != null) {
143 expression.unparse(writer);
144 }
145 if (dimensionProperties.size() > 0) {
146 pw.print(" DIMENSION PROPERTIES ");
147 for (int i = 0; i < dimensionProperties.size(); i++) {
148 IdentifierNode dimensionProperty = dimensionProperties.get(i);
149 if (i > 0) {
150 pw.print(", ");
151 }
152 dimensionProperty.unparse(writer);
153 }
154 }
155 if (axis != Axis.FILTER) {
156 pw.print(" ON " + axis);
157 }
158 }
159
160 /**
161 * Returns the list of dimension properties of this axis.
162 *
163 * @return list of dimension properties
164 */
165 public List<IdentifierNode> getDimensionProperties() {
166 return dimensionProperties;
167 }
168
169 public Type getType() {
170 // An axis is not an expression, so does not have a type.
171 // Try AxisNode.getExpression().getType() instead.
172 return null;
173 }
174
175 public AxisNode deepCopy() {
176 return new AxisNode(
177 this.region,
178 this.nonEmpty,
179 this.axis,
180 MdxUtil.deepCopyList(dimensionProperties),
181 this.expression != null ? this.expression.deepCopy() : null);
182 }
183 }
184
185 // End AxisNode.java