KickJava   Java API By Example, From Geeks To Geeks.

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


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

10 package mondrian.olap.fun;
11
12 import mondrian.olap.type.*;
13 import mondrian.olap.*;
14 import mondrian.calc.*;
15 import mondrian.calc.impl.AbstractTupleCalc;
16 import mondrian.calc.impl.AbstractMemberCalc;
17 import mondrian.mdx.ResolvedFunCall;
18
19 import java.util.List JavaDoc;
20 import java.util.ArrayList JavaDoc;
21
22 /**
23  * Definition of the <code>&lt;Set&gt;.Item(&lt;Index&gt;)</code> MDX function.
24  *
25  * @author jhyde
26  * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/SetItemFunDef.java#4 $
27  * @since Mar 23, 2006
28  */

29 class SetItemFunDef extends FunDefBase {
30     static final Resolver intResolver = new ReflectiveMultiResolver(
31             "Item",
32             "<Set>.Item(<Index>)",
33             "Returns a tuple from the set specified in <Set>. The tuple to be returned is specified by the zero-based position of the tuple in the set in <Index>.",
34             new String JavaDoc[] {"mmxn"},
35             SetItemFunDef.class);
36
37     static final Resolver stringResolver = new ResolverBase(
38             "Item",
39             "<Set>.Item(<String> [, ...])",
40             "Returns a tuple from the set specified in <Set>. The tuple to be returned is specified by the member name (or names) in <String>.",
41             Syntax.Method) {
42
43         public FunDef resolve(
44                 Exp[] args, Validator validator, int[] conversionCount) {
45             if (args.length < 1) {
46                 return null;
47             }
48             final Exp setExp = args[0];
49             if (!(setExp.getType() instanceof SetType)) {
50                 return null;
51             }
52             final SetType setType = (SetType) setExp.getType();
53             int arity;
54             if (setType.getElementType() instanceof TupleType) {
55                 arity = ((TupleType) setType.getElementType()).elementTypes.length;
56             } else {
57                 arity = 1;
58             }
59             // All args must be strings.
60
for (int i = 1; i < args.length; i++) {
61                 if (!validator.canConvert(
62                         args[i], Category.String, conversionCount)) {
63                     return null;
64                 }
65             }
66             if (args.length - 1 != arity) {
67                 throw Util.newError("Argument count does not match set's cardinality " + arity);
68             }
69             final int category = arity == 1 ? Category.Member : Category.Tuple;
70             FunDef dummy = createDummyFunDef(this, category, args);
71             return new SetItemFunDef(dummy);
72         }
73     };
74
75     public SetItemFunDef(FunDef dummyFunDef) {
76         super(dummyFunDef);
77     }
78
79     public Type getResultType(Validator validator, Exp[] args) {
80         SetType setType = (SetType) args[0].getType();
81         return setType.getElementType();
82     }
83
84     public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
85         final ListCalc listCalc =
86                 compiler.compileList(call.getArg(0));
87         final Type elementType = ((SetType) listCalc.getType()).getElementType();
88         final boolean isString = call.getArgCount() < 2 ||
89                         call.getArg(1).getType() instanceof StringType;
90         final IntegerCalc indexCalc;
91         final StringCalc[] stringCalcs;
92         List JavaDoc<Calc> calcList = new ArrayList JavaDoc<Calc>();
93         calcList.add(listCalc);
94         if (isString) {
95             indexCalc = null;
96             stringCalcs = new StringCalc[call.getArgCount() - 1];
97             for (int i = 0; i < stringCalcs.length; i++) {
98                 stringCalcs[i] = compiler.compileString(call.getArg(i + 1));
99                 calcList.add(stringCalcs[i]);
100             }
101         } else {
102             stringCalcs = null;
103             indexCalc = compiler.compileInteger(call.getArg(1));
104             calcList.add(indexCalc);
105         }
106         Calc[] calcs = calcList.toArray(new Calc[calcList.size()]);
107         if (elementType instanceof TupleType) {
108             final TupleType tupleType = (TupleType) elementType;
109             final Member[] nullTuple = makeNullTuple(tupleType);
110             if (isString) {
111                 return new AbstractTupleCalc(call, calcs) {
112                     public Member[] evaluateTuple(Evaluator evaluator) {
113                         final List JavaDoc<Member[]> list = listCalc.evaluateList(evaluator);
114                         assert list != null;
115                         String JavaDoc[] results = new String JavaDoc[stringCalcs.length];
116                         for (int i = 0; i < stringCalcs.length; i++) {
117                             results[i] =
118                                     stringCalcs[i].evaluateString(evaluator);
119                         }
120                         listLoop:
121                         for (Member[] members : list) {
122                             for (int j = 0; j < results.length; j++) {
123                                 String JavaDoc result = results[j];
124                                 final Member member = members[j];
125                                 if (!matchMember(member, result)) {
126                                     continue listLoop;
127                                 }
128                             }
129                             // All members match. Return the current one.
130
return members;
131                         }
132                         // We use 'null' to represent the null tuple. Don't
133
// know why.
134
return null;
135                     }
136                 };
137             } else {
138                 return new AbstractTupleCalc(call, calcs) {
139                     public Member[] evaluateTuple(Evaluator evaluator) {
140                         final List JavaDoc list = listCalc.evaluateList(evaluator);
141                         assert list != null;
142                         final int index = indexCalc.evaluateInteger(evaluator);
143                         int listSize = list.size();
144                         if (index >= listSize || index < 0) {
145                             return nullTuple;
146                         } else {
147                             return (Member[]) list.get(index);
148                         }
149                     }
150                 };
151             }
152         } else {
153             final MemberType memberType = (MemberType) elementType;
154             final Member nullMember = makeNullMember(memberType);
155             if (isString) {
156                 return new AbstractMemberCalc(call, calcs) {
157                     public Member evaluateMember(Evaluator evaluator) {
158                         final List JavaDoc<Member> list = listCalc.evaluateList(evaluator);
159                         assert list != null;
160                         final String JavaDoc result =
161                                 stringCalcs[0].evaluateString(evaluator);
162                         for (Member member : list) {
163                             if (matchMember(member, result)) {
164                                 return member;
165                             }
166                         }
167                         return nullMember;
168                     }
169                 };
170             } else {
171                 return new AbstractMemberCalc(call, calcs) {
172                     public Member evaluateMember(Evaluator evaluator) {
173                         final List JavaDoc list = listCalc.evaluateList(evaluator);
174                         assert list != null;
175                         final int index = indexCalc.evaluateInteger(evaluator);
176                         int listSize = list.size();
177                         if (index >= listSize || index < 0) {
178                             return nullMember;
179                         } else {
180                             return (Member) list.get(index);
181                         }
182                     }
183                 };
184             }
185         }
186     }
187
188     private static boolean matchMember(final Member member, String JavaDoc name) {
189         return member.getName().equals(name);
190     }
191
192     Object JavaDoc makeNullMember(Evaluator evaluator, Exp[] args) {
193         final Type elementType = ((SetType) args[0].getType()).getElementType();
194         return makeNullMemberOrTuple(elementType);
195     }
196
197     Object JavaDoc makeNullMemberOrTuple(final Type elementType) {
198         if (elementType instanceof MemberType) {
199             MemberType memberType = (MemberType) elementType;
200             return makeNullMember(memberType);
201         } else if (elementType instanceof TupleType) {
202             return makeNullTuple((TupleType) elementType);
203         } else {
204             throw Util.newInternal("bad type " + elementType);
205         }
206     }
207 }
208
209 // End SetItemFunDef.java
210
Popular Tags