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