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-2009 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.olap.fun.extra; 011 012import mondrian.calc.*; 013import mondrian.calc.impl.AbstractMemberCalc; 014import mondrian.mdx.ResolvedFunCall; 015import mondrian.olap.*; 016import mondrian.olap.fun.FunDefBase; 017 018import java.util.List; 019 020/** 021 * Definition of the <code>CalculatedChild</code> MDX function. 022 * 023 * <p>Syntax: 024 * <blockquote><code><Member> 025 * CalculatedChild(<String>)</code></blockquote> 026 * 027 * @author bchow 028 * @since 2006/4/12 029 */ 030public class CalculatedChildFunDef extends FunDefBase { 031 public static final CalculatedChildFunDef instance = 032 new CalculatedChildFunDef(); 033 034 CalculatedChildFunDef() { 035 super( 036 "CalculatedChild", 037 "Returns an existing calculated child member with name <String> from the specified <Member>.", 038 "mmmS"); 039 } 040 041 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 042 final MemberCalc memberCalc = compiler.compileMember(call.getArg(0)); 043 final StringCalc stringCalc = compiler.compileString(call.getArg(1)); 044 045 return new AbstractMemberCalc( 046 call, 047 new Calc[] {memberCalc, stringCalc}) 048 { 049 public Member evaluateMember(Evaluator evaluator) { 050 Member member = memberCalc.evaluateMember(evaluator); 051 String name = stringCalc.evaluateString(evaluator); 052 return getCalculatedChild(member, name, evaluator); 053 } 054 }; 055 } 056 057 private Member getCalculatedChild( 058 Member parent, 059 String childName, 060 Evaluator evaluator) 061 { 062 final SchemaReader schemaReader = 063 evaluator.getQuery().getSchemaReader(true); 064 Level childLevel = parent.getLevel().getChildLevel(); 065 if (childLevel == null) { 066 return parent.getHierarchy().getNullMember(); 067 } 068 List<Member> calcMemberList = 069 schemaReader.getCalculatedMembers(childLevel); 070 071 for (Member child : calcMemberList) { 072 // the parent check is required in case there are parallel children 073 // with the same names 074 if (child.getParentMember().equals(parent) 075 && child.getName().equals(childName)) 076 { 077 return child; 078 } 079 } 080 081 return parent.getHierarchy().getNullMember(); 082 } 083} 084 085 086// End CalculatedChildFunDef.java