001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2006-2011 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.mdx; 011 012import mondrian.calc.*; 013import mondrian.calc.impl.AbstractIterCalc; 014import mondrian.olap.*; 015import mondrian.olap.type.Type; 016 017import java.util.List; 018 019/** 020 * Usage of a {@link mondrian.olap.NamedSet} in an MDX expression. 021 * 022 * @author jhyde 023 * @since Sep 26, 2005 024 */ 025public class NamedSetExpr extends ExpBase implements Exp { 026 private final NamedSet namedSet; 027 028 /** 029 * Creates a usage of a named set. 030 * 031 * @param namedSet namedSet 032 * @pre NamedSet != null 033 */ 034 public NamedSetExpr(NamedSet namedSet) { 035 Util.assertPrecondition(namedSet != null, "namedSet != null"); 036 this.namedSet = namedSet; 037 } 038 039 /** 040 * Returns the named set. 041 * 042 * @post return != null 043 */ 044 public NamedSet getNamedSet() { 045 return namedSet; 046 } 047 048 public String toString() { 049 return namedSet.getUniqueName(); 050 } 051 052 public NamedSetExpr clone() { 053 return new NamedSetExpr(namedSet); 054 } 055 056 public int getCategory() { 057 return Category.Set; 058 } 059 060 public Exp accept(Validator validator) { 061 // A set is sometimes used in more than one cube. So, clone the 062 // expression and re-validate every time it is used. 063 // 064 // But keep the expression wrapped in a NamedSet, so that the 065 // expression is evaluated once per query. (We don't want the 066 // expression to be evaluated context-sensitive.) 067 NamedSet namedSet2 = namedSet.validate(validator); 068 if (namedSet2 == namedSet) { 069 return this; 070 } 071 return new NamedSetExpr(namedSet2); 072 } 073 074 public Calc accept(ExpCompiler compiler) { 075 // This is a deliberate breach of the usual rules for interpreting 076 // acceptable result styles. Usually the caller gets to call the shots: 077 // the callee iterates over the acceptable styles and implements in the 078 // first style it is able to. But in this case, we return iterable if 079 // the caller can handle it, even if it isn't the caller's first choice. 080 // This is because the .current and .currentOrdinal functions only 081 // work correctly on iterators. 082 final List<ResultStyle> styleList = 083 compiler.getAcceptableResultStyles(); 084 if (!styleList.contains(ResultStyle.ITERABLE) 085 && !styleList.contains(ResultStyle.ANY)) 086 { 087 return null; 088 } 089 090 return new AbstractIterCalc( 091 this, 092 new Calc[]{/* todo: compile namedSet.getExp() */}) 093 { 094 public TupleIterable evaluateIterable( 095 Evaluator evaluator) 096 { 097 final Evaluator.NamedSetEvaluator eval = getEval(evaluator); 098 return eval.evaluateTupleIterable(evaluator); 099 } 100 101 public boolean dependsOn(Hierarchy hierarchy) { 102 // Given that a named set is never re-evaluated within the 103 // scope of a query, effectively it's independent of all 104 // dimensions. 105 return false; 106 } 107 }; 108 } 109 110 public Evaluator.NamedSetEvaluator getEval(Evaluator evaluator) { 111 return evaluator.getNamedSetEvaluator(namedSet, true); 112 } 113 114 public Object accept(MdxVisitor visitor) { 115 Object o = visitor.visit(this); 116 if (visitor.shouldVisitChildren()) { 117 namedSet.getExp().accept(visitor); 118 } 119 return o; 120 } 121 122 public Type getType() { 123 return namedSet.getType(); 124 } 125 126} 127 128// End NamedSetExpr.java