001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2006-2009 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.olap.fun;
011
012import mondrian.calc.*;
013import mondrian.calc.impl.AbstractMemberCalc;
014import mondrian.mdx.ResolvedFunCall;
015import mondrian.olap.*;
016import mondrian.olap.type.*;
017
018/**
019 * Definition of the <code>&lt;Tuple&gt;.Item</code> MDX function.
020 *
021 * <p>Syntax:
022 * <blockquote><code>
023 * &lt;Tuple&gt;.Item(&lt;Index&gt;)<br/>
024 * </code></blockquote>
025 *
026 * @author jhyde
027 * @since Mar 23, 2006
028 */
029class TupleItemFunDef extends FunDefBase {
030    static final TupleItemFunDef instance = new TupleItemFunDef();
031
032    private TupleItemFunDef() {
033        super(
034            "Item",
035            "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>.",
036            "mmtn");
037    }
038
039    public Type getResultType(Validator validator, Exp[] args) {
040        // Suppose we are called as follows:
041        //   ([Gender].CurrentMember, [Store].CurrentMember).Item(n)
042        //
043        // We know that our result is a member type, but we don't
044        // know which dimension.
045        return MemberType.Unknown;
046    }
047
048    public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
049        final Type type = call.getArg(0).getType();
050        if (type instanceof MemberType) {
051            final MemberCalc memberCalc =
052                compiler.compileMember(call.getArg(0));
053            final IntegerCalc indexCalc =
054                compiler.compileInteger(call.getArg(1));
055            return new AbstractMemberCalc(
056                call, new Calc[] {memberCalc, indexCalc})
057            {
058                public Member evaluateMember(Evaluator evaluator) {
059                    final Member member =
060                            memberCalc.evaluateMember(evaluator);
061                    final int index =
062                            indexCalc.evaluateInteger(evaluator);
063                    if (index != 0) {
064                        return null;
065                    }
066                    return member;
067                }
068            };
069        } else {
070            final TupleCalc tupleCalc =
071                compiler.compileTuple(call.getArg(0));
072            final IntegerCalc indexCalc =
073                compiler.compileInteger(call.getArg(1));
074            return new AbstractMemberCalc(
075                call, new Calc[] {tupleCalc, indexCalc})
076            {
077                final Member[] nullTupleMembers =
078                        makeNullTuple((TupleType) tupleCalc.getType());
079                public Member evaluateMember(Evaluator evaluator) {
080                    final Member[] members =
081                            tupleCalc.evaluateTuple(evaluator);
082                    assert members == null
083                        || members.length == nullTupleMembers.length;
084                    final int index = indexCalc.evaluateInteger(evaluator);
085                    if (members == null) {
086                        return nullTupleMembers[index];
087                    }
088                    if (index >= members.length || index < 0) {
089                        return null;
090                    }
091                    return members[index];
092                }
093            };
094        }
095    }
096}
097
098// End TupleItemFunDef.java