| 1 13 package mondrian.olap.fun; 14 import mondrian.olap.*; 15 import mondrian.olap.type.*; 16 import mondrian.resource.MondrianResource; 17 import mondrian.calc.*; 18 import mondrian.calc.impl.AbstractTupleCalc; 19 import mondrian.mdx.ResolvedFunCall; 20 21 import java.io.PrintWriter ; 22 23 32 public class TupleFunDef extends FunDefBase { 33 private final int[] argTypes; 34 static final ResolverImpl Resolver = new ResolverImpl(); 35 36 private TupleFunDef(int[] argTypes) { 37 super( 38 "()", 39 "(<Member> [, <Member>]...)", 40 "Parenthesis operator constructs a tuple. If there is only one member, the expression is equivalent to the member expression.", 41 Syntax.Parentheses, 42 Category.Tuple, 43 argTypes); 44 this.argTypes = argTypes; 45 } 46 47 public int getReturnCategory() { 48 return Category.Tuple; 49 } 50 51 public int[] getParameterCategories() { 52 return argTypes; 53 } 54 55 public void unparse(Exp[] args, PrintWriter pw) { 56 ExpBase.unparseList(pw, args, "(", ", ", ")"); 57 } 58 59 public Type getResultType(Validator validator, Exp[] args) { 60 if (args.length == 1) { 66 return TypeUtil.toMemberType(args[0].getType()); 67 } else { 68 MemberType[] types = new MemberType[args.length]; 69 for (int i = 0; i < args.length; i++) { 70 Exp arg = args[i]; 71 types[i] = TypeUtil.toMemberType(arg.getType()); 72 } 73 checkDimensions(types); 74 return new TupleType(types); 75 } 76 } 77 78 public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) { 79 final Exp[] args = call.getArgs(); 80 final MemberCalc[] memberCalcs = new MemberCalc[args.length]; 81 for (int i = 0; i < args.length; i++) { 82 memberCalcs[i] = compiler.compileMember(args[i]); 83 } 84 return new CalcImpl(call, memberCalcs); 85 } 86 87 private void checkDimensions(MemberType[] memberTypes) { 88 for (int i = 0; i < memberTypes.length; i++) { 89 MemberType memberType = memberTypes[i]; 90 for (int j = 0; j < i; j++) { 91 MemberType member1 = memberTypes[j]; 92 final Dimension dimension = memberType.getDimension(); 93 final Dimension dimension1 = member1.getDimension(); 94 if (dimension == dimension1) { 95 throw MondrianResource.instance().DupDimensionsInTuple.ex( 96 dimension.getUniqueName()); 97 } 98 } 99 } 100 } 101 102 public static class CalcImpl extends AbstractTupleCalc { 103 private final MemberCalc[] memberCalcs; 104 105 public CalcImpl(ResolvedFunCall call, MemberCalc[] memberCalcs) { 106 super(call, memberCalcs); 107 this.memberCalcs = memberCalcs; 108 } 109 110 public Member[] evaluateTuple(Evaluator evaluator) { 111 final Member[] members = new Member[memberCalcs.length]; 112 for (int i = 0; i < members.length; i++) { 113 final Member member = members[i] 114 = memberCalcs[i].evaluateMember(evaluator); 115 if (member == null || member.isNull()) { 116 return null; 117 } 118 } 119 return members; 120 } 121 122 public MemberCalc[] getMemberCalcs() { 123 return memberCalcs; 124 } 125 } 126 127 private static class ResolverImpl extends ResolverBase { 128 public ResolverImpl() { 129 super("()", null, null, Syntax.Parentheses); 130 } 131 132 public FunDef resolve( 133 Exp[] args, Validator validator, int[] conversionCount) { 134 if (args.length == 1) { 141 return new ParenthesesFunDef(args[0].getCategory()); 142 } else { 143 final int[] argTypes = new int[args.length]; 144 for (int i = 0; i < args.length; i++) { 145 Exp arg = args[i]; 146 if (!validator.canConvert( 151 arg, Category.Member, conversionCount)) { 152 return null; 153 } 154 argTypes[i] = Category.Member; 155 } 156 return new TupleFunDef(argTypes); 157 } 158 } 159 } 160 } 161 162 | Popular Tags |