001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap/fun/LeadLagFunDef.java#3 $
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-2008 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.calc.Calc;
016    import mondrian.calc.ExpCompiler;
017    import mondrian.calc.MemberCalc;
018    import mondrian.calc.IntegerCalc;
019    import mondrian.calc.impl.AbstractMemberCalc;
020    import mondrian.mdx.ResolvedFunCall;
021    
022    /**
023     * Definition of the <code>Lead</code> and <code>Lag</code> MDX functions.
024     *
025     * @author jhyde
026     * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/LeadLagFunDef.java#3 $
027     * @since Mar 23, 2006
028     */
029    class LeadLagFunDef extends FunDefBase {
030        static final ReflectiveMultiResolver LagResolver = new ReflectiveMultiResolver(
031                "Lag",
032                "<Member>.Lag(<Numeric Expression>)",
033                "Returns a member further along the specified member's dimension.",
034                new String[]{"mmmn"},
035                LeadLagFunDef.class);
036    
037        static final ReflectiveMultiResolver LeadResolver = new ReflectiveMultiResolver(
038                "Lead",
039                "<Member>.Lead(<Numeric Expression>)",
040                "Returns a member further along the specified member's dimension.",
041                new String[]{"mmmn"},
042                LeadLagFunDef.class);
043    
044        public LeadLagFunDef(FunDef dummyFunDef) {
045            super(dummyFunDef);
046        }
047    
048        public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
049            final MemberCalc memberCalc =
050                    compiler.compileMember(call.getArg(0));
051            final IntegerCalc integerCalc =
052                    compiler.compileInteger(call.getArg(1));
053            final boolean lag = call.getFunName().equals("Lag");
054            return new AbstractMemberCalc(call, new Calc[] {memberCalc, integerCalc}) {
055                public Member evaluateMember(Evaluator evaluator) {
056                    Member member = memberCalc.evaluateMember(evaluator);
057                    int n = integerCalc.evaluateInteger(evaluator);
058                    if (lag) {
059                        if (n == Integer.MIN_VALUE) {
060                            // bump up lagValue by one
061                            // otherwise -n(used in the getLeadMember call below)is out of range
062                            // because Integer.MAX_VALUE == -(Integer.MIN_VALUE + 1)
063                            n += 1;
064                        }
065    
066                        n = -n;
067                    }
068                    return evaluator.getSchemaReader().getLeadMember(member, n);
069                }
070            };
071        }
072    }
073    
074    // End LeadLagFunDef.java