001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap/fun/AncestorFunDef.java#1 $
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-2006 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;
011    
012    import mondrian.olap.FunDef;
013    import mondrian.olap.Member;
014    import mondrian.olap.Evaluator;
015    import mondrian.olap.Level;
016    import mondrian.olap.type.Type;
017    import mondrian.olap.type.LevelType;
018    import mondrian.calc.*;
019    import mondrian.calc.impl.AbstractMemberCalc;
020    import mondrian.mdx.ResolvedFunCall;
021    
022    /**
023     * Definition of the <code>Ancestor</code> MDX function.
024     *
025     * @author jhyde
026     * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/AncestorFunDef.java#1 $
027     * @since Mar 23, 2006
028     */
029    class AncestorFunDef extends FunDefBase {
030        static final ReflectiveMultiResolver Resolver = new ReflectiveMultiResolver(
031                "Ancestor",
032                "Ancestor(<Member>, {<Level>|<Numeric Expression>})",
033                "Returns the ancestor of a member at a specified level.",
034                new String[] {"fmml", "fmmn"},
035                AncestorFunDef.class);
036    
037        public AncestorFunDef(FunDef dummyFunDef) {
038            super(dummyFunDef);
039        }
040    
041        public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
042            final MemberCalc memberCalc =
043                    compiler.compileMember(call.getArg(0));
044            final Type type1 = call.getArg(1).getType();
045            if (type1 instanceof LevelType) {
046                final LevelCalc levelCalc =
047                        compiler.compileLevel(call.getArg(1));
048                return new AbstractMemberCalc(call, new Calc[] {memberCalc, levelCalc}) {
049                    public Member evaluateMember(Evaluator evaluator) {
050                        Level level = levelCalc.evaluateLevel(evaluator);
051                        Member member = memberCalc.evaluateMember(evaluator);
052                        int distance = member.getLevel().getDepth() - level.getDepth();
053                        return ancestor(evaluator, member, distance, level);
054                    }
055                };
056            } else {
057                final IntegerCalc distanceCalc =
058                        compiler.compileInteger(call.getArg(1));
059                return new AbstractMemberCalc(call, new Calc[] {memberCalc, distanceCalc}) {
060                    public Member evaluateMember(Evaluator evaluator) {
061                        int distance = distanceCalc.evaluateInteger(evaluator);
062                        Member member = memberCalc.evaluateMember(evaluator);
063                        return ancestor(evaluator, member, distance, null);
064                    }
065                };
066            }
067        }
068    }
069    
070    // End AncestorFunDef.java