001 /* 002 // $Id: //open/mondrian/src/main/mondrian/calc/impl/MemberValueCalc.java#7 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2006-2007 Julian Hyde 007 // All Rights Reserved. 008 // You must accept the terms of that agreement to use this software. 009 */ 010 package mondrian.calc.impl; 011 012 import mondrian.calc.Calc; 013 import mondrian.calc.MemberCalc; 014 import mondrian.olap.Dimension; 015 import mondrian.olap.Evaluator; 016 import mondrian.olap.Exp; 017 import mondrian.olap.Member; 018 import mondrian.olap.type.ScalarType; 019 import mondrian.olap.type.Type; 020 021 /** 022 * Expression which evaluates a few member expressions, 023 * sets the dimensional context to the result of those expressions, 024 * then yields the value of the current measure in the current 025 * dimensional context. 026 * 027 * <p>The evaluator's context is preserved. 028 * 029 * <p>Note that a MemberValueCalc with 0 member expressions is equivalent to a 030 * {@link mondrian.calc.impl.ValueCalc}; see also {@link mondrian.calc.impl.TupleValueCalc}. 031 * 032 * @author jhyde 033 * @version $Id: //open/mondrian/src/main/mondrian/calc/impl/MemberValueCalc.java#7 $ 034 * @since Sep 27, 2005 035 */ 036 public class MemberValueCalc extends GenericCalc { 037 private final MemberCalc[] memberCalcs; 038 private final Member[] savedMembers; 039 040 public MemberValueCalc(Exp exp, MemberCalc[] memberCalcs) { 041 super(exp); 042 final Type type = exp.getType(); 043 assert type instanceof ScalarType : exp; 044 this.memberCalcs = memberCalcs; 045 this.savedMembers = new Member[memberCalcs.length]; 046 } 047 048 public Object evaluate(Evaluator evaluator) { 049 Member[] members = new Member[memberCalcs.length]; 050 for (int i = 0; i < memberCalcs.length; i++) { 051 MemberCalc memberCalc = memberCalcs[i]; 052 final Member member = memberCalc.evaluateMember(evaluator); 053 if (member == null || 054 member.isNull()) { 055 // This method needs to leave the evaluator in the same state 056 // it found it. 057 for (int j = 0; j < i; j++) { 058 evaluator.setContext(savedMembers[j]); 059 } 060 return null; 061 } 062 savedMembers[i] = evaluator.setContext(member); 063 members[i] = member; 064 } 065 final boolean needToReturnNull = 066 evaluator.needToReturnNullForUnrelatedDimension(members); 067 if (needToReturnNull) { 068 evaluator.setContext(savedMembers); 069 return null; 070 } 071 072 final Object result = evaluator.evaluateCurrent(); 073 evaluator.setContext(savedMembers); 074 return result; 075 } 076 077 public Calc[] getCalcs() { 078 return memberCalcs; 079 } 080 081 public boolean dependsOn(Dimension dimension) { 082 if (super.dependsOn(dimension)) { 083 return true; 084 } 085 for (MemberCalc memberCalc : memberCalcs) { 086 // If the expression definitely includes the dimension (in this 087 // case, that means it is a member of that dimension) then we 088 // do not depend on the dimension. For example, the scalar value of 089 // [Store].[USA] 090 // does not depend on [Store]. 091 // 092 // If the dimensionality of the expression is unknown, then the 093 // expression MIGHT include the dimension, so to be safe we have to 094 // say that it depends on the given dimension. For example, 095 // Dimensions(3).CurrentMember.Parent 096 // may depend on [Store]. 097 if (memberCalc.getType().usesDimension(dimension, true)) { 098 return false; 099 } 100 } 101 return true; 102 } 103 } 104 105 // End MemberValueCalc.java