1 12 package mondrian.olap.fun; 13 14 import mondrian.olap.*; 15 import mondrian.olap.type.*; 16 import mondrian.mdx.*; 17 18 28 public class ParameterFunDef extends FunDefBase { 29 public final String parameterName; 30 private final Type type; 31 public final Exp exp; 32 public final String parameterDescription; 33 34 ParameterFunDef( 35 FunDef funDef, 36 String parameterName, 37 Type type, 38 int returnCategory, 39 Exp exp, 40 String 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 return true; 70 } 71 if (typeArg instanceof HierarchyExpr) { 72 return true; 74 } 75 if (typeArg instanceof DimensionExpr) { 76 return true; 78 } 79 if (typeArg instanceof FunCall) { 80 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 getParameterName(Exp[] args) { 98 if (args[0] instanceof Literal && 99 args[0].getCategory() == Category.String) { 100 return (String ) ((Literal) args[0]).getValue(); 101 } else { 102 throw Util.newInternal("Parameter name must be a string constant"); 103 } 104 } 105 106 111 public static Type getParameterType(Exp[] args) { 112 if (args[1] instanceof Id) { 113 Id id = (Id) args[1]; 114 String [] names = id.toStringArray(); 115 if (names.length == 1) { 116 final String 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 140 public static class ParameterResolver extends MultiResolver { 141 private static final String [] SIGNATURES = 142 new String []{ 143 "fS#yS#", "fS#yS", 145 "fn#yn#", "fn#yn", 147 "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 [] getReservedWords() { 158 return new String []{"NUMERIC", "STRING"}; 159 } 160 161 protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) { 162 String 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 s = (String ) ((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 default: 204 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 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 parameterDescription = null; 236 if (args.length > 3) { 237 if (args[3] instanceof Literal && 238 args[3].getCategory() == Category.String) { 239 parameterDescription = 240 (String ) ((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 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 []{"fv#"}); 265 } 266 267 protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) { 268 String parameterName = getParameterName(args); 269 return new ParameterFunDef( 270 dummyFunDef, parameterName, null, Category.Unknown, null, 271 null); 272 } 273 } 274 } 275 276 | Popular Tags |