1 13 package mondrian.olap.fun; 14 15 import mondrian.olap.*; 16 import mondrian.olap.type.*; 17 import mondrian.olap.type.LevelType; 18 import mondrian.olap.type.DimensionType; 19 import mondrian.calc.Calc; 20 import mondrian.calc.ExpCompiler; 21 import mondrian.mdx.ResolvedFunCall; 22 23 import java.io.PrintWriter ; 24 25 81 public abstract class FunDefBase extends FunUtil implements FunDef { 82 protected final int flags; 83 private final String name; 84 private final String description; 85 protected final int returnCategory; 86 protected final int[] parameterCategories; 87 88 103 FunDefBase( 104 String name, 105 String signature, 106 String description, 107 Syntax syntax, 108 int returnCategory, 109 int[] parameterCategories) { 110 this.name = name; 111 Util.discard(signature); 112 this.description = description; 113 this.flags = syntax.ordinal(); 114 this.returnCategory = returnCategory; 115 this.parameterCategories = parameterCategories; 116 } 117 118 135 protected FunDefBase(String name, 136 String signature, 137 String description, 138 String flags) { 139 this(name, 140 signature, 141 description, 142 decodeSyntacticType(flags), 143 decodeReturnCategory(flags), 144 decodeParameterCategories(flags)); 145 } 146 147 150 FunDefBase(Resolver resolver, int returnType, int[] parameterTypes) { 151 this(resolver.getName(), 152 null, 153 null, 154 resolver.getSyntax(), 155 returnType, 156 parameterTypes); 157 } 158 159 162 FunDefBase(FunDef funDef) { 163 this(funDef.getName(), funDef.getSignature(), 164 funDef.getDescription(), funDef.getSyntax(), 165 funDef.getReturnCategory(), funDef.getParameterCategories()); 166 } 167 168 public String getName() { 169 return name; 170 } 171 172 public String getDescription() { 173 return description; 174 } 175 176 public Syntax getSyntax() { 177 return Syntax.class.getEnumConstants()[flags]; 178 } 179 180 public int getReturnCategory() { 181 return returnCategory; 182 } 183 184 public int[] getParameterCategories() { 185 return parameterCategories; 186 } 187 188 public Exp createCall(Validator validator, Exp[] args) { 189 int[] categories = getParameterCategories(); 190 Util.assertTrue(categories.length == args.length); 191 for (int i = 0; i < args.length; i++) { 192 args[i] = validateArg(validator, args, i, categories[i]); 193 } 194 final Type type = getResultType(validator, args); 195 if (type == null) { 196 throw Util.newInternal("could not derive type"); 197 } 198 return new ResolvedFunCall(this, args, type); 199 } 200 201 213 protected Exp validateArg( 214 Validator validator, 215 Exp[] args, 216 int i, 217 int category) { 218 return args[i]; 219 } 220 221 242 static Type guessResultType(Exp[] args, int category, String name) { 243 switch (category) { 244 case Category.Logical: 245 return new BooleanType(); 246 case Category.Numeric: 247 return new NumericType(); 248 case Category.Numeric | Category.Integer: 249 return new DecimalType(Integer.MAX_VALUE, 0); 250 case Category.String: 251 return new StringType(); 252 case Category.Symbol: 253 return new SymbolType(); 254 case Category.Value: 255 return new ScalarType(); 256 case Category.Cube: 257 if (args.length > 0 && args[0] instanceof Cube) { 258 return new CubeType((Cube) args[0]); 259 } 260 break; 261 case Category.Dimension: 262 if (args.length > 0) { 263 final Type type = args[0].getType(); 264 return DimensionType.forType(type); 265 } 266 break; 267 case Category.Hierarchy: 268 if (args.length > 0) { 269 final Type type = args[0].getType(); 270 return HierarchyType.forType(type); 271 } 272 break; 273 case Category.Level: 274 if (args.length > 0) { 275 final Type type = args[0].getType(); 276 return LevelType.forType(type); 277 } 278 break; 279 case Category.Member: 280 if (args.length > 0) { 281 final Type type = args[0].getType(); 282 final MemberType memberType = TypeUtil.toMemberType(type); 283 if (memberType != null) { 284 return memberType; 285 } 286 } 287 return MemberType.Unknown; 289 case Category.Tuple: 290 if (args.length > 0) { 291 final Type type = args[0].getType(); 292 final Type memberType = TypeUtil.toMemberOrTupleType(type); 293 if (memberType != null) { 294 return memberType; 295 } 296 } 297 break; 298 case Category.Set: 299 if (args.length > 0) { 300 final Type type = args[0].getType(); 301 final Type memberType = TypeUtil.toMemberOrTupleType(type); 302 if (memberType != null) { 303 return new SetType(memberType); 304 } 305 } 306 break; 307 default: 308 throw Category.instance.badValue(category); 309 } 310 throw Util.newInternal("Cannot deduce type of call to function '" + 311 name + "'"); 312 } 313 314 318 public Type getResultType(Validator validator, Exp[] args) { 319 return guessResultType(args, getReturnCategory(), this.name); 320 } 321 322 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 323 throw Util.newInternal("function '" + getSignature() + 324 "' has not been implemented"); 325 } 326 327 public String getSignature() { 328 return getSyntax().getSignature(getName(), getReturnCategory(), 329 getParameterCategories()); 330 } 331 332 public void unparse(Exp[] args, PrintWriter pw) { 333 getSyntax().unparse(getName(), args, pw); 334 } 335 } 336 337 | Popular Tags |