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