KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > rolap > agg > CellRequest


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/rolap/agg/CellRequest.java#18 $
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-2007 Julian Hyde and others
8 // All Rights Reserved.
9 // You must accept the terms of that agreement to use this software.
10 //
11 // jhyde, 21 March, 2002
12 */

13
14 package mondrian.rolap.agg;
15
16 import mondrian.rolap.*;
17 import mondrian.olap.Util;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.List JavaDoc;
21
22
23 /**
24  * A <code>CellRequest</code> contains the context necessary to get a cell
25  * value from a star.
26  *
27  * @author jhyde
28  * @since 21 March, 2002
29  * @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/CellRequest.java#18 $
30  */

31 public class CellRequest {
32     private final RolapStar.Measure measure;
33     public final boolean extendedContext;
34     public final boolean drillThrough;
35     /**
36      * List of {@link mondrian.rolap.RolapStar.Column}s being which have values
37      * in this request. The 0th entry is a dummy entry: the star, which ensures
38      * that 2 requests for the same columns on measures in the same star get
39      * put into the same batch.
40      */

41     private final List JavaDoc constrainedColumnList = new ArrayList JavaDoc();
42     private List JavaDoc<StarColumnPredicate> valueList =
43         new ArrayList JavaDoc<StarColumnPredicate>();
44
45     /**
46      * After all of the columns are loaded into the constrainedColumnList instance
47      * variable, this columnsCache is created the first time the getColumns
48      * method is called.
49      * <p>
50      * It is assumed that the call to all additional columns,
51      * {@link #addConstrainedColumn}, will not be called after the first call to
52      * the {@link #getConstrainedColumns()} method.
53      */

54     private RolapStar.Column[] columnsCache = null;
55
56     /**
57      * A bit is set for each column in the column list. Allows us to rapidly
58      * figure out whether two requests are for the same column set.
59      * These are all of the columns that are involved with a query, that is, all
60      * required to be present in an aggregate table for the table be used to
61      * fulfill the query.
62      */

63     private final BitKey constrainedColumnsBitKey;
64
65     /**
66      * Whether the request is impossible to satisfy. This is set to 'true' if
67      * contradictory constraints are applied to the same column. For example,
68      * the levels [Customer].[City] and [Cities].[City] map to the same column
69      * via the same join-path, and one constraint sets city = 'Burbank' and
70      * another sets city = 'Los Angeles'.
71      */

72     private boolean unsatisfiable;
73
74     /**
75      * The valueList and columnsCache must be set after all constraints
76      * have been added. This is used by access methods to determine if
77      * both valueList and columnsCache need to be generated.
78      */

79     private boolean isDirty = true;
80
81     /**
82      * Creates a {@link CellRequest}.
83      */

84     public CellRequest(
85             RolapStar.Measure measure,
86             boolean extendedContext,
87             boolean drillThrough) {
88         this.measure = measure;
89         this.extendedContext = extendedContext;
90         this.drillThrough = drillThrough;
91         this.constrainedColumnList.add(measure.getStar());
92         this.constrainedColumnsBitKey =
93             BitKey.Factory.makeBitKey(measure.getStar().getColumnCount());
94     }
95
96     /**
97      * Adds a constraint to this request.
98      *
99      * @param column Column to constraint
100      * @param predicate Constraint to apply, or null to add column to the
101      * output without applying constraint
102      */

103     public void addConstrainedColumn(
104             RolapStar.Column column,
105             StarColumnPredicate predicate) {
106
107         assert columnsCache == null;
108
109         final int bitPosition = column.getBitPosition();
110         if (this.constrainedColumnsBitKey.get(bitPosition)) {
111             // This column is already constrained. Unless the value is the same,
112
// or this value or the previous value is null (meaning
113
// unconstrained) the request will never return any results.
114
int index = constrainedColumnList.indexOf(column);
115             Util.assertTrue(index >= 0);
116             // column list has RolapStar as its first element
117
--index;
118             final StarColumnPredicate prevValue = valueList.get(index);
119             if (prevValue == null) {
120                 // Previous column was unconstrained. Constrain on new value.
121
} else if (predicate == null) {
122                 // Previous column was constrained. Nothing to do.
123
return;
124             } else if (predicate.equalConstraint(prevValue)) {
125                 // Same constraint again. Nothing to do.
126
return;
127             } else {
128                 // Different constraint. Request is impossible to satisfy.
129
predicate = null;
130                 unsatisfiable = true;
131             }
132             valueList.set(index, predicate);
133
134         } else {
135             this.constrainedColumnList.add(column);
136             this.constrainedColumnsBitKey.set(bitPosition);
137             this.valueList.add(predicate);
138         }
139     }
140
141     public RolapStar.Measure getMeasure() {
142         return measure;
143     }
144
145     public RolapStar.Column[] getConstrainedColumns() {
146         if (this.columnsCache == null) {
147             // This is called more than once so caching the value makes
148
// sense.
149
check();
150         }
151         return this.columnsCache;
152     }
153
154     /**
155      * Returns the BitKey for the list of columns.
156      */

157     public BitKey getConstrainedColumnsBitKey() {
158         return constrainedColumnsBitKey;
159     }
160
161     /**
162      * This method builds both the columnsCache and reorders the valueList
163      * based upon bit key position of the columns.
164      */

165     private void check() {
166         if (isDirty) {
167             final int size = constrainedColumnList.size();
168             this.columnsCache = new RolapStar.Column[size - 1];
169             List JavaDoc<StarColumnPredicate> vl = new ArrayList JavaDoc<StarColumnPredicate>();
170             int cnt = 0;
171             for (int bitPos : constrainedColumnsBitKey) {
172                 // NOTE: If the RolapStar.Column were stored in maybe a Map
173
// rather than the constrainedColumnList List, we would
174
// not have to for-loop over the list for each bit position.
175
for (int j = 1; j < size; j++) {
176                     RolapStar.Column rc =
177                             (RolapStar.Column) constrainedColumnList.get(j);
178                     if (rc.getBitPosition() == bitPos) {
179                         int index = constrainedColumnList.indexOf(rc) - 1;
180                         final StarColumnPredicate value = valueList.get(index);
181                         vl.add(value);
182                         columnsCache[cnt++] = rc;
183                         break;
184                     }
185                 }
186             }
187             valueList = vl;
188
189             isDirty = false;
190         }
191     }
192     public List JavaDoc<StarColumnPredicate> getValueList() {
193         check();
194         return valueList;
195     }
196
197     public Object JavaDoc[] getSingleValues() {
198         check();
199         // Currently, this is called only once per CellRequest instance
200
// so there is no need to cache the value.
201
Object JavaDoc[] a = new Object JavaDoc[valueList.size()];
202         for (int i = 0, n = valueList.size(); i < n; i++) {
203             ValueColumnPredicate constr =
204                 (ValueColumnPredicate) valueList.get(i);
205             a[i] = constr.getValue();
206         }
207         return a;
208     }
209
210     /**
211      * Returns whether this cell request is impossible to satisfy.
212      * This occurs when the same column has two or more inconsistent
213      * constraints.
214      */

215     public boolean isUnsatisfiable() {
216         return unsatisfiable;
217     }
218 }
219
220 // End CellRequest.java
221
Popular Tags