001 /*
002 // $Id: AxisNode.java 245 2009-05-26 21:14:13Z sgwood $
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 java.io.PrintWriter;
013 import java.util.List;
014 import java.util.Collections;
015
016 import org.olap4j.Axis;
017 import org.olap4j.type.Type;
018
019 /**
020 * An axis in an MDX query. For example, the typical MDX query has two axes,
021 * which appear as the "ON COLUMNS" and "ON ROWS" clauses.
022 *
023 * @version $Id: AxisNode.java 245 2009-05-26 21:14:13Z sgwood $
024 */
025 public class AxisNode implements ParseTreeNode {
026
027 private final ParseRegion region;
028 private boolean nonEmpty;
029 private ParseTreeNode expression;
030 private final Axis axis;
031
032 private final List<IdentifierNode> dimensionProperties;
033
034 /**
035 * Creates an axis.
036 *
037 * @param region Region of source code
038 * @param nonEmpty Whether to filter out members of this axis whose cells
039 * are all empty
040 * @param axis Which axis (ROWS, COLUMNS, etc.)
041 * @param dimensionProperties List of dimension properties; if null,
042 * empty list is assumed
043 * @param expression Expression to populate the axis
044 */
045 public AxisNode(
046 ParseRegion region,
047 boolean nonEmpty,
048 Axis axis,
049 List<IdentifierNode> dimensionProperties,
050 ParseTreeNode expression)
051 {
052 this.region = region;
053 this.nonEmpty = nonEmpty;
054 this.expression = expression;
055 this.axis = axis;
056 if (axis == null) {
057 throw new IllegalArgumentException("Axis type must not be null");
058 }
059 if (dimensionProperties == null) {
060 dimensionProperties = Collections.emptyList();
061 }
062 this.dimensionProperties = dimensionProperties;
063 }
064
065 public ParseRegion getRegion() {
066 return region;
067 }
068
069 public <T> T accept(ParseTreeVisitor<T> visitor) {
070 final T o = visitor.visit(this);
071
072 // visit the expression which forms the axis
073 expression.accept(visitor);
074
075 return o;
076 }
077
078 /**
079 * Returns the name of the axis this axis expression is populating.
080 *
081 * @return axis name
082 */
083 public Axis getAxis() {
084 return axis;
085 }
086
087 /**
088 * Returns whether the axis has the <code>NON EMPTY</code> property set.
089 *
090 * @return whether the axis is NON EMPTY
091 */
092 public boolean isNonEmpty() {
093 return nonEmpty;
094 }
095
096 /**
097 * Sets whether the axis has the <code>NON EMPTY</code> property set.
098 *
099 * See {@link #isNonEmpty()}.
100 *
101 * @param nonEmpty whether the axis is NON EMPTY
102 */
103 public void setNonEmpty(boolean nonEmpty) {
104 this.nonEmpty = nonEmpty;
105 }
106
107 /**
108 * Returns the expression which is used to compute the value of this axis.
109 *
110 * @return the expression which is used to compute the value of this axis
111 */
112 public ParseTreeNode getExpression() {
113 return expression;
114 }
115
116 /**
117 * Sets the expression which is used to compute the value of this axis.
118 * See {@link #getExpression()}.
119 *
120 * @param expr the expression which is used to compute the value of this
121 * axis
122 */
123 public void setExpression(ParseTreeNode expr) {
124 this.expression = expr;
125 }
126
127 public void unparse(ParseTreeWriter writer) {
128 PrintWriter pw = writer.getPrintWriter();
129 if (nonEmpty) {
130 pw.print("NON EMPTY ");
131 }
132 if (expression != null) {
133 expression.unparse(writer);
134 }
135 if (dimensionProperties.size() > 0) {
136 pw.print(" DIMENSION PROPERTIES ");
137 for (int i = 0; i < dimensionProperties.size(); i++) {
138 IdentifierNode dimensionProperty = dimensionProperties.get(i);
139 if (i > 0) {
140 pw.print(", ");
141 }
142 dimensionProperty.unparse(writer);
143 }
144 }
145 if (axis != Axis.FILTER) {
146 pw.print(" ON " + axis);
147 }
148 }
149
150 /**
151 * Returns the list of dimension properties of this axis.
152 *
153 * @return list of dimension properties
154 */
155 public List<IdentifierNode> getDimensionProperties() {
156 return dimensionProperties;
157 }
158
159 public Type getType() {
160 // An axis is not an expression, so does not have a type.
161 // Try AxisNode.getExpression().getType() instead.
162 return null;
163 }
164
165 public AxisNode deepCopy() {
166 return new AxisNode(
167 this.region,
168 this.nonEmpty,
169 this.axis,
170 MdxUtil.deepCopyList(dimensionProperties),
171 this.expression != null ? this.expression.deepCopy() : null);
172 }
173 }
174
175 // End AxisNode.java