KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/olap/fun/TupleFunDef.java#17 $
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) 2002-2002 Kana Software, Inc.
7 // Copyright (C) 2002-2006 Julian Hyde and others
8 // All Rights Reserved.
9 // You must accept the terms of that agreement to use this software.
10 //
11 // jhyde, 3 March, 2002
12 */

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 JavaDoc;
22
23 /**
24  * <code>TupleFunDef</code> implements the '( ... )' operator which builds
25  * tuples, as in <code>([Time].CurrentMember,
26  * [Stores].[USA].[California])</code>.
27  *
28  * @author jhyde
29  * @since 3 March, 2002
30  * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/TupleFunDef.java#17 $
31  */

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 JavaDoc pw) {
56         ExpBase.unparseList(pw, args, "(", ", ", ")");
57     }
58
59     public Type getResultType(Validator validator, Exp[] args) {
60         // _Tuple(<Member1>[,<MemberI>]...), which is written
61
// (<Member1>[,<MemberI>]...), has type [Hie1] x ... x [HieN].
62
//
63
// If there is only one member, it merely represents a parenthesized
64
// expression, whose Hierarchy is that of the member.
65
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             // Compare with TupleFunDef.getReturnCategory(). For example,
135
// ([Gender].members) is a set,
136
// ([Gender].[M]) is a member,
137
// (1 + 2) is a numeric,
138
// but
139
// ([Gender].[M], [Marital Status].[S]) is a tuple.
140
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                     // Arg must be a member:
147
// OK: ([Gender].[S], [Time].[1997]) (member, member)
148
// OK: ([Gender], [Time]) (dimension, dimension)
149
// Not OK: ([Gender].[S], [Store].[Store City]) (member, level)
150
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 // End TupleFunDef.java
163
Popular Tags