001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap/fun/TupleItemFunDef.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.type.Type;
013    import mondrian.olap.type.MemberType;
014    import mondrian.olap.type.TupleType;
015    import mondrian.olap.Validator;
016    import mondrian.olap.Exp;
017    import mondrian.olap.Member;
018    import mondrian.olap.Evaluator;
019    import mondrian.calc.*;
020    import mondrian.calc.impl.AbstractMemberCalc;
021    import mondrian.mdx.ResolvedFunCall;
022    
023    /**
024     * Definition of the <code>&lt;Tuple&gt;.Item</code> MDX function.
025     *
026     * <p>Syntax:
027     * <blockquote><code>
028     * &lt;Tuple&gt;.Item(&lt;Index&gt;)<br/>
029     * </code></blockquote>
030     *
031     * @author jhyde
032     * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/TupleItemFunDef.java#4 $
033     * @since Mar 23, 2006
034     */
035    class TupleItemFunDef extends FunDefBase {
036        static final TupleItemFunDef instance = new TupleItemFunDef();
037    
038        private TupleItemFunDef() {
039            super(
040                "Item",
041                "Returns a member from the tuple specified in <Tuple>. The member to be returned is specified by the zero-based position of the member in the set in <Index>.",
042                "mmtn");
043        }
044    
045        public Type getResultType(Validator validator, Exp[] args) {
046            // Suppose we are called as follows:
047            //   ([Gender].CurrentMember, [Store].CurrentMember).Item(n)
048            //
049            // We know that our result is a member type, but we don't
050            // know which dimension.
051            return MemberType.Unknown;
052        }
053    
054        public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
055            final Type type = call.getArg(0).getType();
056            if (type instanceof MemberType) {
057                final MemberCalc memberCalc =
058                        compiler.compileMember(call.getArg(0));
059                final IntegerCalc indexCalc =
060                        compiler.compileInteger(call.getArg(1));
061                return new AbstractMemberCalc(call, new Calc[] {memberCalc, indexCalc}) {
062                    public Member evaluateMember(Evaluator evaluator) {
063                        final Member member =
064                                memberCalc.evaluateMember(evaluator);
065                        final int index =
066                                indexCalc.evaluateInteger(evaluator);
067                        if (index != 0) {
068                            return null;
069                        }
070                        return member;
071                    }
072                };
073            } else {
074                final TupleCalc tupleCalc =
075                        compiler.compileTuple(call.getArg(0));
076                final IntegerCalc indexCalc =
077                        compiler.compileInteger(call.getArg(1));
078                return new AbstractMemberCalc(call, new Calc[] {tupleCalc, indexCalc}) {
079                    final Member[] nullTupleMembers =
080                            makeNullTuple((TupleType) tupleCalc.getType());
081                    public Member evaluateMember(Evaluator evaluator) {
082                        final Member[] members =
083                                tupleCalc.evaluateTuple(evaluator);
084                        assert members == null ||
085                                members.length == nullTupleMembers.length;
086                        final int index = indexCalc.evaluateInteger(evaluator);
087                        if (members == null) {
088                            return nullTupleMembers[index];
089                        }
090                        if (index >= members.length || index < 0) {
091                            return null;
092                        }
093                        return members[index];
094                    }
095                };
096            }
097        }
098    }
099    
100    // End TupleItemFunDef.java