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*/ 020package org.olap4j.mdx; 021 022import org.olap4j.Axis; 023import org.olap4j.type.Type; 024 025import java.io.PrintWriter; 026import java.util.Collections; 027import 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 */ 035public 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