KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > olap > fun > UdfResolver


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/olap/fun/UdfResolver.java#12 $
3 // This software is subject to the terms of the Common Public License
4 // Agreement, available at the following URL:
5 // http://www.opensource.org/licenses/cpl.html.
6 // Copyright (C) 2005-2006 Julian Hyde
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 */

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 /**
20  * Resolver for user-defined functions.
21  *
22  * @author jhyde
23  * @since 2.0
24  * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/UdfResolver.java#12 $
25  */

26 public class UdfResolver implements Resolver {
27     private final UserDefinedFunction udf;
28     private static final String JavaDoc[] emptyStringArray = new String JavaDoc[0];
29
30     public UdfResolver(UserDefinedFunction udf) {
31         this.udf = udf;
32     }
33     public String JavaDoc getName() {
34         return udf.getName();
35     }
36
37     public String JavaDoc getDescription() {
38         return udf.getDescription();
39     }
40
41     public String JavaDoc 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 JavaDoc[] getReservedWords() {
102         final String JavaDoc[] reservedWords = udf.getReservedWords();
103         return reservedWords == null ? emptyStringArray : reservedWords;
104     }
105
106     /**
107      * Adapter which converts a {@link UserDefinedFunction} into a
108      * {@link FunDef}.
109      */

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     /**
131      * Expression which evaluates a user-defined function.
132      */

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 JavaDoc evaluate(Evaluator evaluator) {
154             return udf.execute(evaluator, args);
155         }
156
157         public boolean dependsOn(Dimension dimension) {
158             // Be pessimistic. This effectively disables expression caching.
159
return true;
160         }
161     }
162
163     /**
164      * Wrapper around a {@link Calc} to make it appear as an {@link Exp}.
165      * Only the {@link #evaluate(mondrian.olap.Evaluator)}
166      * and {@link #evaluateScalar(mondrian.olap.Evaluator)} methods are
167      * supported.
168      */

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 JavaDoc evaluate(Evaluator evaluator) {
183             return calc.evaluate(evaluator);
184         }
185
186         public Object JavaDoc evaluateScalar(Evaluator evaluator) {
187             return scalarCalc.evaluate(evaluator);
188         }
189     }
190
191 }
192
193 // End UdfResolver.java
194
Popular Tags