| 1 10 package mondrian.olap.fun; 11 12 import mondrian.olap.*; 13 import mondrian.olap.type.*; 14 import mondrian.spi.UserDefinedFunction; 15 import mondrian.calc.*; 16 import mondrian.calc.impl.GenericCalc; 17 import mondrian.mdx.ResolvedFunCall; 18 19 26 public class UdfResolver implements Resolver { 27 private final UserDefinedFunction udf; 28 private static final String [] emptyStringArray = new String [0]; 29 30 public UdfResolver(UserDefinedFunction udf) { 31 this.udf = udf; 32 } 33 public String getName() { 34 return udf.getName(); 35 } 36 37 public String getDescription() { 38 return udf.getDescription(); 39 } 40 41 public String getSignature() { 42 Type[] parameterTypes = udf.getParameterTypes(); 43 int[] parameterCategories = new int[parameterTypes.length]; 44 for (int i = 0; i < parameterCategories.length; i++) { 45 parameterCategories[i] = TypeUtil.typeToCategory(parameterTypes[i]); 46 } 47 Type returnType = udf.getReturnType(parameterTypes); 48 int returnCategory = TypeUtil.typeToCategory(returnType); 49 return getSyntax().getSignature( 50 getName(), 51 returnCategory, 52 parameterCategories); 53 } 54 55 public Syntax getSyntax() { 56 return udf.getSyntax(); 57 } 58 59 public FunDef getFunDef() { 60 Type[] parameterTypes = udf.getParameterTypes(); 61 int[] parameterCategories = new int[parameterTypes.length]; 62 for (int i = 0; i < parameterCategories.length; i++) { 63 parameterCategories[i] = TypeUtil.typeToCategory(parameterTypes[i]); 64 } 65 Type returnType = udf.getReturnType(parameterTypes); 66 int returnCategory = TypeUtil.typeToCategory(returnType); 67 return new UdfFunDef(returnCategory, parameterCategories); 68 } 69 70 public FunDef resolve( 71 Exp[] args, Validator validator, int[] conversionCount) { 72 final Type[] parameterTypes = udf.getParameterTypes(); 73 if (args.length != parameterTypes.length) { 74 return null; 75 } 76 int[] parameterCategories = new int[parameterTypes.length]; 77 Type[] argTypes = new Type[parameterTypes.length]; 78 for (int i = 0; i < parameterTypes.length; i++) { 79 Type parameterType = parameterTypes[i]; 80 final Exp arg = args[i]; 81 final Type argType = argTypes[i] = arg.getType(); 82 if (parameterType.equals(argType)) { 83 continue; 84 } 85 final int parameterCategory = TypeUtil.typeToCategory(parameterType); 86 if (!validator.canConvert( 87 arg, parameterCategory, conversionCount)) { 88 return null; 89 } 90 parameterCategories[i] = parameterCategory; 91 } 92 final Type returnType = udf.getReturnType(argTypes); 93 final int returnCategory = TypeUtil.typeToCategory(returnType); 94 return new UdfFunDef(returnCategory, parameterCategories); 95 } 96 97 public boolean requiresExpression(int k) { 98 return false; 99 } 100 101 public String [] getReservedWords() { 102 final String [] reservedWords = udf.getReservedWords(); 103 return reservedWords == null ? emptyStringArray : reservedWords; 104 } 105 106 110 private class UdfFunDef extends FunDefBase { 111 public UdfFunDef(int returnCategory, int[] parameterCategories) { 112 super(UdfResolver.this, returnCategory, parameterCategories); 113 } 114 115 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 116 final Exp[] args = call.getArgs(); 117 Calc[] calcs = new Calc[args.length]; 118 UserDefinedFunction.Argument[] expCalcs = 119 new UserDefinedFunction.Argument[args.length]; 120 for (int i = 0; i < args.length; i++) { 121 Exp arg = args[i]; 122 final Calc calc = compiler.compile(arg); 123 final Calc scalarCalc = compiler.compileScalar(arg, true); 124 expCalcs[i] = new CalcExp(calc, scalarCalc); 125 } 126 return new CalcImpl(call, calcs, udf, expCalcs); 127 } 128 } 129 130 133 private static class CalcImpl extends GenericCalc { 134 private final Calc[] calcs; 135 private final UserDefinedFunction udf; 136 private final UserDefinedFunction.Argument[] args; 137 138 public CalcImpl( 139 ResolvedFunCall call, 140 Calc[] calcs, 141 UserDefinedFunction udf, 142 UserDefinedFunction.Argument[] args) { 143 super(call); 144 this.calcs = calcs; 145 this.udf = udf; 146 this.args = args; 147 } 148 149 public Calc[] getCalcs() { 150 return calcs; 151 } 152 153 public Object evaluate(Evaluator evaluator) { 154 return udf.execute(evaluator, args); 155 } 156 157 public boolean dependsOn(Dimension dimension) { 158 return true; 160 } 161 } 162 163 169 private static class CalcExp implements UserDefinedFunction.Argument { 170 private final Calc calc; 171 private final Calc scalarCalc; 172 173 public CalcExp(Calc calc, Calc scalarCalc) { 174 this.calc = calc; 175 this.scalarCalc = scalarCalc; 176 } 177 178 public Type getType() { 179 return calc.getType(); 180 } 181 182 public Object evaluate(Evaluator evaluator) { 183 return calc.evaluate(evaluator); 184 } 185 186 public Object evaluateScalar(Evaluator evaluator) { 187 return scalarCalc.evaluate(evaluator); 188 } 189 } 190 191 } 192 193 | Popular Tags |