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) 1998-2005 Julian Hyde
008// Copyright (C) 2005-2007 Pentaho and others
009// All Rights Reserved.
010*/
011package mondrian.mdx;
012
013import mondrian.calc.Calc;
014import mondrian.calc.ExpCompiler;
015import mondrian.olap.*;
016import mondrian.olap.fun.FunUtil;
017import mondrian.olap.type.Type;
018
019import java.io.PrintWriter;
020
021/**
022 * A <code>ResolvedFunCall</code> is a function applied to a list of operands,
023 * which has been validated and resolved to a
024 * {@link FunDef function definition}.
025 *
026 * @author jhyde
027 * @since Jan 6, 2006
028 */
029public final class ResolvedFunCall extends ExpBase implements FunCall {
030
031    /**
032     * The arguments to the function call.  Note that for methods, 0-th arg is
033     * 'this'.
034     */
035    private final Exp[] args;
036
037    /**
038     * Return type of this function call.
039     */
040    private final Type returnType;
041
042    /**
043     * Function definition.
044     */
045    private final FunDef funDef;
046
047    /**
048     * Creates a function call.
049     *
050     * @param funDef Function definition
051     * @param args Arguments
052     * @param returnType Return type
053     */
054    public ResolvedFunCall(FunDef funDef, Exp[] args, Type returnType) {
055        assert funDef != null;
056        assert args != null;
057        assert returnType != null;
058        this.funDef = funDef;
059        this.args = args;
060        this.returnType = returnType;
061    }
062
063    public String toString() {
064        return Util.unparse(this);
065    }
066
067    @SuppressWarnings({"CloneDoesntCallSuperClone"})
068    public ResolvedFunCall clone() {
069        return new ResolvedFunCall(
070            funDef, ExpBase.cloneArray(args), returnType);
071    }
072
073    /**
074     * Returns the Exp argument at the specified index.
075     *
076     * @param      index   the index of the Exp.
077     * @return     the Exp at the specified index of this array of Exp.
078     *             The first Exp is at index <code>0</code>.
079     * @see #getArgs()
080     */
081    public Exp getArg(int index) {
082        return args[index];
083    }
084
085    /**
086     * Returns the internal array of Exp arguments.
087     *
088     * <p>Note: this does NOT do a copy.
089     *
090     * @return the array of expressions
091     */
092    public Exp[] getArgs() {
093        return args;
094    }
095
096    /**
097     * Returns the number of arguments.
098     *
099     * @return number of arguments.
100     * @see #getArgs()
101     */
102    public final int getArgCount() {
103        return args.length;
104    }
105
106    public String getFunName() {
107        return funDef.getName();
108    }
109
110    public Syntax getSyntax() {
111        return funDef.getSyntax();
112    }
113
114    public Object[] getChildren() {
115        return args;
116    }
117
118    /**
119     * Returns the definition of the function which is being called.
120     *
121     * @return function definition
122     */
123    public FunDef getFunDef() {
124        return funDef;
125    }
126
127    public final int getCategory() {
128        return funDef.getReturnCategory();
129    }
130
131    public final Type getType() {
132        return returnType;
133    }
134
135    public Exp accept(Validator validator) {
136        // even though the function has already been validated, we need
137        // to walk through the arguments to determine which measures are
138        // referenced
139        Exp[] newArgs = new Exp[args.length];
140        FunUtil.resolveFunArgs(
141            validator, funDef, args, newArgs, getFunName(), getSyntax());
142
143        return this;
144    }
145
146    public void unparse(PrintWriter pw) {
147        funDef.unparse(args, pw);
148    }
149
150    public Calc accept(ExpCompiler compiler) {
151        return funDef.compileCall(this, compiler);
152    }
153
154    public Object accept(MdxVisitor visitor) {
155        final Object o = visitor.visit(this);
156        if (visitor.shouldVisitChildren()) {
157            // visit the call's arguments
158            for (Exp arg : args) {
159                arg.accept(visitor);
160            }
161        }
162        return o;
163    }
164}
165
166// End ResolvedFunCall.java