KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > calc > impl > AbstractCalc


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/calc/impl/AbstractCalc.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) 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.calc.impl;
11
12 import mondrian.olap.*;
13 import mondrian.olap.type.Type;
14 import mondrian.calc.Calc;
15 import mondrian.calc.CalcWriter;
16 import mondrian.calc.ExpCompiler;
17 import mondrian.mdx.ResolvedFunCall;
18
19 import java.io.PrintWriter JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Collections JavaDoc;
22
23 /**
24  * Abstract implementation of the {@link mondrian.calc.Calc} interface.
25  *
26  * @author jhyde
27  * @version $Id: //open/mondrian/src/main/mondrian/calc/impl/AbstractCalc.java#8 $
28  * @since Sep 27, 2005
29  */

30 public abstract class AbstractCalc implements Calc {
31     protected final Type type;
32     protected final Exp exp;
33
34     protected AbstractCalc(Exp exp) {
35         assert exp != null;
36         this.exp = exp;
37         this.type = exp.getType();
38     }
39
40     public Type getType() {
41         return type;
42     }
43
44     public void accept(CalcWriter calcWriter) {
45         final PrintWriter JavaDoc pw = calcWriter.getWriter();
46         String JavaDoc name = getName();
47         pw.print(name);
48         final Calc[] calcs = getCalcs();
49         final List JavaDoc<Object JavaDoc> argumentList = getArguments();
50         if (calcs.length > 0 || !argumentList.isEmpty()) {
51            pw.print("(");
52             int k = 0;
53             for (Calc calc : calcs) {
54                 if (k++ > 0) {
55                     pw.print(", ");
56                 }
57                 calc.accept(calcWriter);
58             }
59             for (Object JavaDoc o : argumentList) {
60                 if (k++ > 0) {
61                     pw.print(", ");
62                 }
63                 pw.print(o);
64             }
65             pw.print(")");
66         }
67     }
68
69     /**
70      * Returns the name of this expression type, used when serializing an
71      * expression to a string.
72      *
73      * <p>The default implementation tries to extract a name from a function call,
74      * if any, then prints the last part of the class name.
75      */

76     protected String JavaDoc getName() {
77         String JavaDoc name;
78         if (exp instanceof ResolvedFunCall) {
79             ResolvedFunCall funCall = (ResolvedFunCall) exp;
80             name = funCall.getFunDef().getName();
81         } else {
82             name = getClass().getName();
83             int dot = name.lastIndexOf('.');
84             int dollar = name.lastIndexOf('$');
85             int dotDollar = Math.max(dot, dollar);
86             if (dotDollar >= 0) {
87                 name = name.substring(dotDollar + 1);
88             }
89         }
90         return name;
91     }
92
93     /**
94      * Returns this expression's child expressions.
95      */

96     public abstract Calc[] getCalcs();
97
98     public boolean dependsOn(Dimension dimension) {
99         return anyDepends(getCalcs(), dimension);
100     }
101
102     /**
103      * Returns true if one of the calcs depends on the given dimension.
104      */

105     public static boolean anyDepends(Calc[] calcs, Dimension dimension) {
106         for (Calc calc : calcs) {
107             if (calc != null && calc.dependsOn(dimension)) {
108                 return true;
109             }
110         }
111         return false;
112     }
113
114     /**
115      * Returns true if calc[0] depends on dimension,
116      * else false if calc[0] returns dimension,
117      * else true if any of the other calcs depend on dimension.
118      *
119      * <p>Typical application: <code>Aggregate({Set}, {Value Expression})</code>
120      * depends upon everything {Value Expression} depends upon, except the
121      * dimensions of {Set}.
122      */

123     public static boolean anyDependsButFirst(
124             Calc[] calcs, Dimension dimension) {
125         if (calcs.length == 0) {
126             return false;
127         }
128         if (calcs[0].dependsOn(dimension)) {
129             return true;
130         }
131         if (calcs[0].getType().usesDimension(dimension, true)) {
132             return false;
133         }
134         for (int i = 1; i < calcs.length; i++) {
135             Calc calc = calcs[i];
136             if (calc != null && calc.dependsOn(dimension)) {
137                 return true;
138             }
139         }
140         return false;
141     }
142
143     /**
144      * Returns true if any of the calcs depend on dimension,
145      * else false if any of the calcs return dimension,
146      * else true.
147      */

148     public static boolean butDepends(
149             Calc[] calcs, Dimension dimension) {
150         boolean result = true;
151         for (Calc calc : calcs) {
152             if (calc != null) {
153                 if (calc.dependsOn(dimension)) {
154                     return true;
155                 }
156                 if (calc.getType().usesDimension(dimension, true)) {
157                     result = false;
158                 }
159             }
160         }
161         return result;
162     }
163
164     /**
165      * Returns any other arguments to this calc.
166      * The default implementation returns the empty list.
167      */

168     public List JavaDoc<Object JavaDoc> getArguments() {
169         return Collections.emptyList();
170     }
171
172     /**
173      * Returns a simplified evalator whose context is the same for every
174      * dimension which an expression depends on, and the default member for
175      * every dimension which it does not depend on.
176      *
177      * <p>The default member is oftne the 'all' member, so this evaluator is
178      * usually the most efficient context in which to evaluate the expression.
179      *
180      * @param calc
181      * @param evaluator
182      */

183     public static Evaluator simplifyEvaluator(Calc calc, Evaluator evaluator) {
184         if (evaluator.isNonEmpty()) {
185             // If NON EMPTY is present, we cannot simplify the context, because
186
// we have to assume that the expression depends on everything.
187
// TODO: Bug 1456418: Convert 'NON EMPTY Crossjoin' to
188
// 'NonEmptyCrossJoin'.
189
return evaluator;
190         }
191         int changeCount = 0;
192         Evaluator ev = evaluator;
193         final Dimension[] dimensions = evaluator.getCube().getDimensions();
194         for (Dimension dimension : dimensions) {
195             final Member member = ev.getContext(dimension);
196             if (member.isAll()) {
197                 continue;
198             }
199             if (calc.dependsOn(dimension)) {
200                 continue;
201             }
202             final Member unconstrainedMember =
203                 member.getHierarchy().getDefaultMember();
204             if (member == unconstrainedMember) {
205                 // This is a hierarchy without an 'all' member, and the context
206
// is already the default member.
207
continue;
208             }
209             if (changeCount++ == 0) {
210                 ev = evaluator.push(unconstrainedMember);
211             } else {
212                 ev.setContext(unconstrainedMember);
213             }
214         }
215         return ev;
216     }
217
218     public ExpCompiler.ResultStyle getResultStyle() {
219         return ExpCompiler.ResultStyle.VALUE;
220     }
221 }
222
223 // End AbstractCalc.java
224
Popular Tags