KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/olap/fun/ParameterFunDef.java#14 $
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) 2003-2006 Julian Hyde
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 //
10 // jhyde, Feb 14, 2003
11 */

12 package mondrian.olap.fun;
13
14 import mondrian.olap.*;
15 import mondrian.olap.type.*;
16 import mondrian.mdx.*;
17
18 /**
19  * A <code>ParameterFunDef</code> is a pseudo-function describing calls to
20  * <code>Parameter</code> and <code>ParamRef</code> functions. It exists only
21  * fleetingly, and is then converted into a {@link mondrian.olap.Parameter}.
22  * For internal use only.
23  *
24  * @author jhyde
25  * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/ParameterFunDef.java#14 $
26  * @since Feb 14, 2003
27  */

28 public class ParameterFunDef extends FunDefBase {
29     public final String JavaDoc parameterName;
30     private final Type type;
31     public final Exp exp;
32     public final String JavaDoc parameterDescription;
33
34     ParameterFunDef(
35             FunDef funDef,
36             String JavaDoc parameterName,
37             Type type,
38             int returnCategory,
39             Exp exp,
40             String JavaDoc description) {
41         super(funDef.getName(),
42                 funDef.getSignature(),
43                 funDef.getDescription(),
44                 funDef.getSyntax(),
45                 returnCategory,
46                 funDef.getParameterCategories());
47         assertPrecondition(getName().equals("Parameter") ||
48                 getName().equals("ParamRef"));
49         this.parameterName = parameterName;
50         this.type = type;
51         this.exp = exp;
52         this.parameterDescription = description;
53     }
54
55     public Exp createCall(Validator validator, Exp[] args) {
56         Parameter parameter = validator.createOrLookupParam(
57             this.getName().equals("Parameter"),
58             parameterName, type, exp, parameterDescription);
59         return new ParameterExpr(parameter);
60     }
61
62     public Type getResultType(Validator validator, Exp[] args) {
63         return type;
64     }
65
66     private static boolean isConstant(Exp typeArg) {
67         if (typeArg instanceof LevelExpr) {
68             // e.g. "[Time].[Quarter]"
69
return true;
70         }
71         if (typeArg instanceof HierarchyExpr) {
72             // e.g. "[Time].[By Week]"
73
return true;
74         }
75         if (typeArg instanceof DimensionExpr) {
76             // e.g. "[Time]"
77
return true;
78         }
79         if (typeArg instanceof FunCall) {
80             // e.g. "[Time].CurrentMember.Hierarchy". They probably wrote
81
// "[Time]", and the automatic type conversion did the rest.
82
FunCall hierarchyCall = (FunCall) typeArg;
83             if (hierarchyCall.getFunName().equals("Hierarchy") &&
84                     hierarchyCall.getArgCount() > 0 &&
85                     hierarchyCall.getArg(0) instanceof FunCall) {
86                 FunCall currentMemberCall = (FunCall) hierarchyCall.getArg(0);
87                 if (currentMemberCall.getFunName().equals("CurrentMember") &&
88                         currentMemberCall.getArgCount() > 0 &&
89                         currentMemberCall.getArg(0) instanceof DimensionExpr) {
90                     return true;
91                 }
92             }
93         }
94         return false;
95     }
96
97     public static String JavaDoc getParameterName(Exp[] args) {
98         if (args[0] instanceof Literal &&
99                 args[0].getCategory() == Category.String) {
100             return (String JavaDoc) ((Literal) args[0]).getValue();
101         } else {
102             throw Util.newInternal("Parameter name must be a string constant");
103         }
104     }
105
106     /**
107      * Returns an approximate type for a parameter, based upon the 1'th
108      * argument. Does not use the default value expression, so this method
109      * can safely be used before the expression has been validated.
110      */

111     public static Type getParameterType(Exp[] args) {
112         if (args[1] instanceof Id) {
113             Id id = (Id) args[1];
114             String JavaDoc[] names = id.toStringArray();
115             if (names.length == 1) {
116                 final String JavaDoc name = names[0];
117                 if (name.equals("NUMERIC")) {
118                     return new NumericType();
119                 }
120                 if (name.equals("STRING")) {
121                     return new StringType();
122                 }
123             }
124         } else if (args[1] instanceof Literal) {
125             final Literal literal = (Literal) args[1];
126             if (literal.getValue().equals("NUMERIC")) {
127                 return new NumericType();
128             } else if (literal.getValue().equals("STRING")) {
129                 return new StringType();
130             }
131         } else if (args[1] instanceof MemberExpr) {
132             return new MemberType(null,null,null,null);
133         }
134         return new StringType();
135     }
136
137     /**
138      * Resolves calls to the <code>Parameter</code> MDX function.
139      */

140     public static class ParameterResolver extends MultiResolver {
141         private static final String JavaDoc[] SIGNATURES =
142                 new String JavaDoc[]{
143                     // Parameter(string const, symbol, string[, string const]): string
144
"fS#yS#", "fS#yS",
145                     // Parameter(string const, symbol, numeric[, string const]): numeric
146
"fn#yn#", "fn#yn",
147                     // Parameter(string const, hierarchy constant, member[, string const]): member
148
"fm#hm#", "fm#hm",
149                 };
150
151         public ParameterResolver() {
152             super("Parameter",
153                     "Parameter(<Name>, <Type>, <DefaultValue>, <Description>)",
154                     "Returns default value of parameter.", SIGNATURES);
155         }
156
157         public String JavaDoc[] getReservedWords() {
158             return new String JavaDoc[]{"NUMERIC", "STRING"};
159         }
160
161         protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) {
162             String JavaDoc parameterName = getParameterName(args);
163             Exp typeArg = args[1];
164             int category;
165             Type type = typeArg.getType();
166             switch (typeArg.getCategory()) {
167             case Category.Dimension:
168             case Category.Hierarchy:
169             case Category.Level:
170                 Dimension dimension = type.getDimension();
171                 if (!isConstant(typeArg)) {
172                     throw newEvalException(
173                             dummyFunDef,
174                             "Invalid parameter '" + parameterName +
175                             "'. Type must be a NUMERIC, STRING, or a dimension, hierarchy or level");
176                 }
177                 if (dimension == null) {
178                     throw newEvalException(
179                             dummyFunDef,
180                             "Invalid dimension for parameter '" +
181                             parameterName + "'");
182                 }
183                 type = new MemberType(
184                         type.getDimension(),
185                         type.getHierarchy(),
186                         type.getLevel(),
187                         null);
188                 category = Category.Member;
189                 break;
190
191             case Category.Symbol:
192                 String JavaDoc s = (String JavaDoc) ((Literal) typeArg).getValue();
193                 if (s.equalsIgnoreCase("NUMERIC")) {
194                     category = Category.Numeric;
195                     type = new NumericType();
196                     break;
197                 } else if (s.equalsIgnoreCase("STRING")) {
198                     category = Category.String;
199                     type = new StringType();
200                     break;
201                 }
202                 // fall through and throw error
203
default:
204                 // Error is internal because the function call has already been
205
// type-checked.
206
throw newEvalException(
207                         dummyFunDef,
208                         "Invalid type for parameter '" + parameterName +
209                         "'; expecting NUMERIC, STRING or a hierarchy");
210             }
211             Exp exp = args[2];
212             if (exp.getCategory() != category) {
213                 String JavaDoc typeName =
214                         Category.instance.getName(category).toUpperCase();
215                 throw newEvalException(
216                         dummyFunDef,
217                         "Default value of parameter '" + parameterName +
218                         "' is inconsistent with its type, " + typeName);
219             }
220             if (category == Category.Member) {
221                 final Type expType = exp.getType();
222                 if (type.getDimension() != null &&
223                         expType.getDimension() != type.getDimension() ||
224                         type.getHierarchy() != null &&
225                         expType.getHierarchy() != type.getHierarchy() ||
226                         type.getLevel() != null &&
227                         expType.getLevel() != type.getLevel()) {
228                     throw newEvalException(
229                             dummyFunDef,
230                             "Default value of parameter '" + parameterName +
231                             "' is not consistent with the parameter type '" +
232                             type);
233                 }
234             }
235             String JavaDoc parameterDescription = null;
236             if (args.length > 3) {
237                 if (args[3] instanceof Literal &&
238                         args[3].getCategory() == Category.String) {
239                     parameterDescription =
240                             (String JavaDoc) ((Literal) args[3]).getValue();
241                 } else {
242                     throw newEvalException(
243                             dummyFunDef,
244                             "Description of parameter '" + parameterName +
245                             "' must be a string constant");
246                 }
247             }
248
249             return new ParameterFunDef(
250                     dummyFunDef, parameterName, type, category,
251                     exp, parameterDescription);
252         }
253     }
254
255     /**
256      * Resolves calls to the <code>ParamRef</code> MDX function.
257      */

258     public static class ParamRefResolver extends MultiResolver {
259         public ParamRefResolver() {
260             super(
261                     "ParamRef",
262                     "ParamRef(<Name>)",
263                     "Returns the current value of this parameter. If it is null, returns the default value.",
264                     new String JavaDoc[]{"fv#"});
265         }
266
267         protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) {
268             String JavaDoc parameterName = getParameterName(args);
269             return new ParameterFunDef(
270                     dummyFunDef, parameterName, null, Category.Unknown, null,
271                     null);
272         }
273     }
274 }
275
276 // End ParameterFunDef.java
277
Popular Tags