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