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) 2009-2011 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.rolap; 011 012import mondrian.calc.Calc; 013import mondrian.mdx.ResolvedFunCall; 014import mondrian.olap.Exp; 015import mondrian.olap.fun.AggregateFunDef; 016 017/** 018 * Implementation of {@link mondrian.rolap.RolapCalculation} 019 * that wraps a {@link RolapMember calculated member}. 020 * 021 * @author jhyde 022 * @since May 15, 2009 023 */ 024class RolapMemberCalculation implements RolapCalculation { 025 private final RolapMember member; 026 private final int solveOrder; 027 private Boolean containsAggregateFunction; 028 029 /** 030 * Creates a RolapMemberCalculation. 031 * 032 * @param member Calculated member 033 */ 034 public RolapMemberCalculation(RolapMember member) { 035 this.member = member; 036 // compute and solve order: it is used frequently 037 solveOrder = this.member.getSolveOrder(); 038 assert member.isEvaluated(); 039 } 040 041 public int hashCode() { 042 return member.hashCode(); 043 } 044 045 public boolean equals(Object obj) { 046 return obj instanceof RolapMemberCalculation 047 && member == ((RolapMemberCalculation) obj).member; 048 } 049 050 public void setContextIn(RolapEvaluator evaluator) { 051 final RolapMember defaultMember = 052 evaluator.root.defaultMembers[getHierarchyOrdinal()]; 053 054 // This method does not need to call RolapEvaluator.removeCalcMember. 055 // That happens implicitly in setContext. 056 evaluator.setContext(defaultMember); 057 evaluator.setExpanding(member); 058 } 059 060 public int getSolveOrder() { 061 return solveOrder; 062 } 063 064 public int getHierarchyOrdinal() { 065 return member.getHierarchy().getOrdinalInCube(); 066 } 067 068 public Calc getCompiledExpression(RolapEvaluatorRoot root) { 069 final Exp exp = member.getExpression(); 070 return root.getCompiled(exp, true, null); 071 } 072 073 public boolean isCalculatedInQuery() { 074 return member.isCalculatedInQuery(); 075 } 076 077 public boolean containsAggregateFunction() { 078 // searching for agg functions is expensive, so cache result 079 if (containsAggregateFunction == null) { 080 containsAggregateFunction = 081 foundAggregateFunction(member.getExpression()); 082 } 083 return containsAggregateFunction; 084 } 085 086 /** 087 * Returns whether an expression contains a call to an aggregate 088 * function such as "Aggregate" or "Sum". 089 * 090 * @param exp Expression 091 * @return Whether expression contains a call to an aggregate function. 092 */ 093 private static boolean foundAggregateFunction(Exp exp) { 094 if (exp instanceof ResolvedFunCall) { 095 ResolvedFunCall resolvedFunCall = (ResolvedFunCall) exp; 096 if (resolvedFunCall.getFunDef() instanceof AggregateFunDef) { 097 return true; 098 } else { 099 for (Exp argExp : resolvedFunCall.getArgs()) { 100 if (foundAggregateFunction(argExp)) { 101 return true; 102 } 103 } 104 } 105 } 106 return false; 107 } 108} 109 110// End RolapMemberCalculation.java