001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap/fun/PeriodsToDateFunDef.java#4 $
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.*;
013    import mondrian.olap.type.Type;
014    import mondrian.olap.type.SetType;
015    import mondrian.olap.type.MemberType;
016    import mondrian.resource.MondrianResource;
017    import mondrian.calc.Calc;
018    import mondrian.calc.ExpCompiler;
019    import mondrian.calc.LevelCalc;
020    import mondrian.calc.MemberCalc;
021    import mondrian.calc.impl.AbstractListCalc;
022    import mondrian.mdx.ResolvedFunCall;
023    
024    import java.util.List;
025    
026    /**
027     * Definition of the <code>PeriodsToDate</code> MDX function.
028     *
029     * @author jhyde
030     * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/PeriodsToDateFunDef.java#4 $
031     * @since Mar 23, 2006
032     */
033    class PeriodsToDateFunDef extends FunDefBase {
034        static final ReflectiveMultiResolver Resolver = new ReflectiveMultiResolver(
035                "PeriodsToDate",
036                "PeriodsToDate([<Level>[, <Member>]])",
037                "Returns a set of periods (members) from a specified level starting with the first period and ending with a specified member.",
038                new String[]{"fx", "fxl", "fxlm"},
039                PeriodsToDateFunDef.class);
040    
041        public PeriodsToDateFunDef(FunDef dummyFunDef) {
042            super(dummyFunDef);
043        }
044    
045        public Type getResultType(Validator validator, Exp[] args) {
046            if (args.length == 0) {
047                // With no args, the default implementation cannot
048                // guess the hierarchy.
049                Dimension defaultTimeDimension =
050                    validator.getQuery().getCube().getTimeDimension();
051                if (defaultTimeDimension == null) {
052                    throw MondrianResource.instance().
053                                NoTimeDimensionInCube.ex(getName());
054                }
055                Hierarchy hierarchy = defaultTimeDimension.getHierarchy();
056                return new SetType(
057                        MemberType.forHierarchy(hierarchy));
058            }
059            final Type type = args[0].getType();
060            if (type.getDimension() == null ||
061                type.getDimension().getDimensionType() !=
062                    mondrian.olap.DimensionType.TimeDimension) {
063                throw MondrianResource.instance().TimeArgNeeded.ex(getName());
064            }
065            return super.getResultType(validator, args);
066        }
067    
068        public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
069            final LevelCalc levelCalc =
070                    call.getArgCount() > 0 ?
071                    compiler.compileLevel(call.getArg(0)) :
072                    null;
073            final MemberCalc memberCalc =
074                    call.getArgCount() > 1 ?
075                    compiler.compileMember(call.getArg(1)) :
076                    null;
077            final Dimension timeDimension = compiler
078                    .getEvaluator().getCube().getTimeDimension();
079    
080            return new AbstractListCalc(call, new Calc[] {levelCalc, memberCalc}) {
081                public List evaluateList(Evaluator evaluator) {
082                    final Member member;
083                    final Level level;
084                    if (levelCalc == null) {
085                        if (timeDimension == null) {
086                            throw MondrianResource.instance().
087                                        NoTimeDimensionInCube.ex(getName());
088                        }
089                        member = evaluator.getContext(timeDimension);
090                        level = member.getLevel().getParentLevel();
091                    } else {
092                        level = levelCalc.evaluateLevel(evaluator);
093                        if (memberCalc == null) {
094                            member = evaluator.getContext(
095                                    level.getHierarchy().getDimension());
096                        } else {
097                            member = memberCalc.evaluateMember(evaluator);
098                        }
099                    }
100                    return periodsToDate(evaluator, level, member);
101                }
102    
103                public boolean dependsOn(Dimension dimension) {
104                    if (super.dependsOn(dimension)) {
105                        return true;
106                    }
107                    if (memberCalc != null) {
108                        return false;
109                    } else if (levelCalc != null) {
110                        return levelCalc.getType().usesDimension(dimension, true) ;
111                    } else {
112                        if (timeDimension == null) {
113                            throw MondrianResource.instance().
114                                        NoTimeDimensionInCube.ex(getName());
115                        }
116                        return dimension == timeDimension;
117                    }
118                }
119            };
120        }
121    }
122    
123    // End PeriodsToDateFunDef.java