1 13 14 package mondrian.olap; 15 16 import mondrian.calc.Calc; 17 import mondrian.calc.ExpCompiler; 18 import mondrian.calc.ExpCompiler.ResultStyle; 19 import mondrian.mdx.*; 20 import mondrian.olap.type.Type; 21 import mondrian.olap.type.TypeUtil; 22 import mondrian.resource.MondrianResource; 23 24 import java.io.PrintWriter ; 25 26 32 public class QueryAxis extends QueryPart { 33 34 private boolean nonEmpty; 35 private Exp exp; 36 private final AxisOrdinal axisOrdinal; 37 38 42 private SubtotalVisibility subtotalVisibility; 43 private final Id[] dimensionProperties; 44 45 55 public QueryAxis( 56 boolean nonEmpty, 57 Exp set, 58 AxisOrdinal axisDef, 59 SubtotalVisibility subtotalVisibility, 60 Id[] dimensionProperties) { 61 assert dimensionProperties != null; 62 this.nonEmpty = nonEmpty || 63 MondrianProperties.instance().EnableNonEmptyOnAllAxis.get(); 64 this.exp = set; 65 this.axisOrdinal = axisDef; 66 this.subtotalVisibility = subtotalVisibility; 67 this.dimensionProperties = dimensionProperties; 68 } 69 70 75 public QueryAxis( 76 boolean nonEmpty, 77 Exp set, 78 AxisOrdinal axisDef, 79 SubtotalVisibility subtotalVisibility) { 80 this(nonEmpty, set, axisDef, subtotalVisibility, new Id[0]); 81 } 82 83 public Object clone() { 84 return new QueryAxis(nonEmpty, exp.clone(), axisOrdinal, 85 subtotalVisibility, dimensionProperties.clone()); 86 } 87 88 static QueryAxis[] cloneArray(QueryAxis[] a) { 89 QueryAxis[] a2 = new QueryAxis[a.length]; 90 for (int i = 0; i < a.length; i++) { 91 a2[i] = (QueryAxis) a[i].clone(); 92 } 93 return a2; 94 } 95 96 public Object accept(MdxVisitor visitor) { 97 final Object o = visitor.visit(this); 98 99 exp.accept(visitor); 101 102 return o; 103 } 104 105 public Calc compile(ExpCompiler compiler, ResultStyle[] resultStyles) { 106 Exp exp = this.exp; 107 if (axisOrdinal == AxisOrdinal.SLICER) { 108 exp = normalizeSlicerExpression(exp); 109 exp = exp.accept(compiler.getValidator()); 110 } 111 return compiler.compile(exp, resultStyles); 112 } 113 114 private static Exp normalizeSlicerExpression(Exp exp) { 115 Exp slicer = exp; 116 if (slicer instanceof LevelExpr || 117 slicer instanceof HierarchyExpr || 118 slicer instanceof DimensionExpr) { 119 120 slicer = new UnresolvedFunCall( 121 "DefaultMember", Syntax.Property, new Exp[] { 122 slicer}); 123 } 124 if (slicer == null) { 125 ; 126 } else if (slicer instanceof FunCall && 127 ((FunCall) slicer).getSyntax() == Syntax.Parentheses) { 128 slicer = new UnresolvedFunCall( 129 "{}", Syntax.Braces, new Exp[] { 130 slicer}); 131 } else { 132 slicer = new UnresolvedFunCall( 133 "{}", Syntax.Braces, new Exp[] { 134 new UnresolvedFunCall( 135 "()", Syntax.Parentheses, new Exp[] { 136 slicer})}); 137 } 138 139 return slicer; 140 } 141 142 public String getAxisName() { 143 return axisOrdinal.name(); 144 } 145 146 149 public AxisOrdinal getAxisOrdinal() { 150 return axisOrdinal; 151 } 152 153 156 public boolean isNonEmpty() { 157 return nonEmpty; 158 } 159 160 164 public void setNonEmpty(boolean nonEmpty) { 165 this.nonEmpty = nonEmpty; 166 } 167 168 171 public Exp getSet() { 172 return exp; 173 } 174 175 179 public void setSet(Exp set) { 180 this.exp = set; 181 } 182 183 public void resolve(Validator validator) { 184 exp = validator.validate(exp, false); 185 final Type type = exp.getType(); 186 if (!TypeUtil.isSet(type)) { 187 throw MondrianResource.instance().MdxAxisIsNotSet.ex(axisOrdinal.name()); 188 } 189 } 190 191 public Object [] getChildren() { 192 return new Object [] {exp}; 193 } 194 195 public void unparse(PrintWriter pw) { 196 if (nonEmpty) { 197 pw.print("NON EMPTY "); 198 } 199 if (exp != null) { 200 exp.unparse(pw); 201 } 202 if (dimensionProperties.length > 0) { 203 pw.print(" DIMENSION PROPERTIES "); 204 for (int i = 0; i < dimensionProperties.length; i++) { 205 Id dimensionProperty = dimensionProperties[i]; 206 if (i > 0) { 207 pw.print(", "); 208 } 209 dimensionProperty.unparse(pw); 210 } 211 } 212 if (axisOrdinal != AxisOrdinal.SLICER) { 213 pw.print(" ON " + axisOrdinal); 214 } 215 } 216 217 public void addLevel(Level level) { 218 Util.assertTrue(level != null, "addLevel needs level"); 219 exp = new UnresolvedFunCall("Crossjoin", Syntax.Function, new Exp[]{ 220 exp, 221 new UnresolvedFunCall("Members", Syntax.Property, new Exp[]{ 222 new LevelExpr(level)})}); 223 } 224 225 void setSubtotalVisibility(boolean bShowSubtotals) { 226 subtotalVisibility = bShowSubtotals ? 227 SubtotalVisibility.Show : 228 SubtotalVisibility.Hide; 229 } 230 231 public SubtotalVisibility getSubtotalVisibility() { 232 return subtotalVisibility; 233 } 234 235 public void resetSubtotalVisibility() { 236 this.subtotalVisibility = SubtotalVisibility.Undefined; 237 } 238 239 public void validate(Validator validator) { 240 if (axisOrdinal == AxisOrdinal.SLICER) { 241 if (exp != null) { 242 exp = validator.validate(exp, false); 243 } 244 } 245 } 246 247 public Id[] getDimensionProperties() { 248 return dimensionProperties; 249 } 250 251 255 public enum SubtotalVisibility { 256 Undefined, 257 Hide, 258 Show; 259 } 260 261 } 262 263 | Popular Tags |