KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > udf > LastNonEmptyUdf


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

10 package mondrian.udf;
11
12 import mondrian.olap.*;
13 import mondrian.olap.type.*;
14 import mondrian.rolap.RolapUtil;
15 import mondrian.spi.UserDefinedFunction;
16
17 import java.util.List JavaDoc;
18
19 /**
20  * Definition of the user-defined function "LastNonEmpty".
21  *
22  * @author jhyde
23  * @version $Id: //open/mondrian/src/main/mondrian/udf/LastNonEmptyUdf.java#8 $
24  */

25 public class LastNonEmptyUdf implements UserDefinedFunction {
26
27     public String JavaDoc getName() {
28         return "LastNonEmpty";
29     }
30
31     public String JavaDoc getDescription() {
32         return "Returns the last member of a set whose value is not empty";
33     }
34
35     public Syntax getSyntax() {
36         return Syntax.Function;
37     }
38
39     public Type getReturnType(Type[] parameterTypes) {
40         // Return type is the same as the elements of the first parameter.
41
// For example,
42
// LastNonEmpty({[Time].[1997], [Time].[1997].[Q1]},
43
// [Measures].[Unit Sales])
44
// will return a member of the [Time] dimension.
45
SetType setType = (SetType) parameterTypes[0];
46         MemberType memberType = (MemberType) setType.getElementType();
47         return memberType;
48     }
49
50     public Type[] getParameterTypes() {
51         return new Type[] {
52             // The first argument must be a set of members (of any hierarchy).
53
new SetType(MemberType.Unknown),
54             // The second argument must be a member.
55
MemberType.Unknown,
56         };
57     }
58
59     public Object JavaDoc execute(Evaluator evaluator, Argument[] arguments) {
60         final Argument memberListExp = arguments[0];
61         final List JavaDoc memberList = (List JavaDoc) memberListExp.evaluate(evaluator);
62         final Argument exp = arguments[1];
63         int nullCount = 0;
64         int missCount = 0;
65         for (int i = memberList.size() - 1; i >= 0; --i) {
66             Member member = (Member) memberList.get(i);
67             // Create an evaluator with the member as its context.
68
Evaluator subEvaluator = evaluator.push(member);
69             int missCountBefore = subEvaluator.getMissCount();
70             final Object JavaDoc o = exp.evaluateScalar(subEvaluator);
71             int missCountAfter = subEvaluator.getMissCount();
72             if (Util.isNull(o)) {
73                 ++nullCount;
74                 continue;
75             }
76             if (missCountAfter > missCountBefore) {
77                 // There was a cache miss while evaluating the expression, so
78
// the result is bogus. It would be a mistake to give up after
79
// one cache miss, because then it would take us N
80
// evaluate/fetch passes to move back through N members, which
81
// is way too many.
82
//
83
// Carry on until we have seen as many misses as we have seen
84
// null cells. The effect of this policy is that each pass
85
// examines twice as many cells as the previous pass. Thus
86
// we can move back through N members in log2(N) passes.
87
++missCount;
88                 if (missCount < 2*nullCount+1) {
89                     continue;
90                 }
91             }
92             if (o == RolapUtil.valueNotReadyException) {
93                 // Value is not in the cache yet, so we don't know whether
94
// it will be empty. Carry on...
95
continue;
96             }
97             if (o instanceof RuntimeException JavaDoc) {
98                 RuntimeException JavaDoc runtimeException = (RuntimeException JavaDoc) o;
99                 if (o == RolapUtil.valueNotReadyException) {
100                     // Value is not in the cache yet, so we don't know whether
101
// it will be empty. Carry on...
102
continue;
103                 }
104                 return runtimeException;
105             }
106             return member;
107         }
108         // Not found. Return the hierarchy's 'null member'.
109
// It is possible that a MemberType has a Dimension but
110
// no hierarchy, so we have to just get the type's Dimension's
111
// default hierarchy and return it's null member.
112
final Hierarchy hierarchy = memberListExp.getType().getHierarchy();
113         return (hierarchy == null)
114             ? memberListExp.getType().getDimension().
115                 getHierarchies()[0].getNullMember()
116             : hierarchy.getNullMember();
117     }
118
119     public String JavaDoc[] getReservedWords() {
120         // This function does not require any reserved words.
121
return null;
122     }
123 }
124
125 // End LastNonEmptyUdf.java
126
Popular Tags