KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > rolap > CellKey


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/rolap/CellKey.java#9 $
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) 2001-2002 Kana Software, Inc.
7 // Copyright (C) 2001-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, 10 August, 2001
12 */

13
14 package mondrian.rolap;
15
16 import java.util.Arrays JavaDoc;
17
18 /**
19  * A <code>CellKey<code> is used as a key in maps which access cells by their
20  * position.
21  *
22  * <p>CellKey is also used within
23  * {@link mondrian.rolap.agg.SparseSegmentDataset} to store values within
24  * aggregations.
25  *
26  * <p>It is important that CellKey is memory-efficient, and that the
27  * {@link Object#hashCode} and {@link Object#equals} methods are extremely
28  * efficient. There are particular implementations for the
29  * most likely cases where the number of axes is 1, 2 and 3 as well as a general
30  * implementation.
31  *
32  * <p>To create a key, call the
33  * {@link mondrian.rolap.CellKey.Generator#newCellKey(int[])} method.
34  *
35  * @author jhyde
36  * @since 10 August, 2001
37  * @version $Id: //open/mondrian/src/main/mondrian/rolap/CellKey.java#9 $
38  */

39 public interface CellKey {
40     /**
41      * Returns the number of axes.
42      *
43      * @return number of axes
44      */

45     int size();
46
47     /**
48      * Returns the axis keys as an array.
49      *
50      * <p>Note: caller should treat the array as immutable. If the contents of
51      * the array are modified, behavior is unspecified.
52      *
53      * @return Array of axis keys
54      */

55     int[] getOrdinals();
56
57     /**
58      * This method make a copy of the int array parameter.
59      * Throws a RuntimeException if the int array size is not the
60      * size of the CellKey.
61      *
62      * @param pos Array of axis keys
63      */

64     void setOrdinals(int[] pos);
65
66     /**
67      * Returns the <code>axis</code>th axis value.
68      *
69      * @param axis Axis ordinal
70      * @return Value of the <code>axis</code>th axis
71      * @throws ArrayIndexOutOfBoundsException if axis is out of range
72      */

73     int getAxis(int axis);
74
75     /**
76      * Sets a given axis.
77      *
78      * @param axis Axis ordinal
79      * @param value Value
80      * @throws RuntimeException if axis parameter is larger than {@link #size()}
81      */

82     void setAxis(int axis, int value);
83
84     /**
85      * Returns a mutable copy of this CellKey.
86      *
87      * @return Mutable copy
88      */

89     CellKey copy();
90
91     public class Generator {
92         /**
93          * Creates a CellKey with a given number of axes.
94          *
95          * @param size Number of axes
96          * @return new CellKey
97          */

98         public static CellKey newCellKey(int size) {
99             switch (size) {
100             case 0:
101                 return new Zero();
102             case 1:
103                 return new One(0);
104             case 2:
105                 return new Two(0, 0);
106             case 3:
107                 return new Three(0, 0, 0);
108             default:
109                 return new Many(new int[size]);
110             }
111         }
112
113         /**
114          * Creates a CellKey populated with the given coordinates.
115          *
116          * @param pos Coordinate array
117          * @return CellKey
118          */

119         public static CellKey newCellKey(int[] pos) {
120             switch (pos.length) {
121             case 0:
122                 return new Zero();
123             case 1:
124                 return new One(pos[0]);
125             case 2:
126                 return new Two(pos[0], pos[1]);
127             case 3:
128                 return new Three(pos[0], pos[1], pos[2]);
129             default:
130                 return new Many(pos.clone());
131             }
132         }
133
134         /**
135          * Creates a CellKey based on a reference to the given coordinate
136          * array. Whenever the contents of the coordinate array change, the
137          * CellKey will also.
138          *
139          * @param pos Coordinate array
140          * @return CellKey
141          */

142         public static CellKey newRefCellKey(int[] pos) {
143             // don't clone pos!
144
return new Many(pos);
145         }
146
147         /**
148          * Creates a CellKey implemented by an array to hold the coordinates,
149          * regardless of the size. This is used for testing only.
150          *
151          * @param size Number of coordinates
152          * @return CallKey
153          */

154         static CellKey newManyCellKey(int size) {
155             return new Many(new int[size]);
156         }
157     }
158
159     public class Zero implements CellKey {
160         private static final int[] EMPTY_INT_ARRAY = new int[0];
161         public static final Zero INSTANCE = new Zero();
162
163         /**
164          * Use singleton {@link #INSTANCE}.
165          */

166         private Zero() {
167         }
168
169         public Zero copy() {
170             // no need to make copy since there is no state
171
return this;
172         }
173
174         public boolean equals(Object JavaDoc o) {
175             return o instanceof Zero;
176         }
177
178
179         public int size() {
180             return 0;
181         }
182
183         public int[] getOrdinals() {
184             return EMPTY_INT_ARRAY;
185         }
186
187         public void setOrdinals(int[] pos) {
188             if (pos.length != 0) {
189                 throw new IllegalArgumentException JavaDoc();
190             }
191         }
192
193         public int getAxis(int axis) {
194             throw new ArrayIndexOutOfBoundsException JavaDoc(axis);
195         }
196
197         public void setAxis(int axis, int value) {
198             throw new ArrayIndexOutOfBoundsException JavaDoc(axis);
199         }
200     }
201
202     public class One implements CellKey {
203         private int ordinal0;
204
205         /**
206          * Creates a One.
207          *
208          * @param ordinal0 Ordinate #0
209          */

210         private One(int ordinal0) {
211             this.ordinal0 = ordinal0;
212         }
213
214         public int size() {
215             return 1;
216         }
217
218         public int[] getOrdinals() {
219             return new int[] {ordinal0};
220         }
221
222         public void setOrdinals(int[] pos) {
223             if (pos.length != 1) {
224                 throw new IllegalArgumentException JavaDoc();
225             }
226             ordinal0 = pos[0];
227         }
228
229         public int getAxis(int axis) {
230             switch (axis) {
231             case 0:
232                 return ordinal0;
233             default:
234                 throw new ArrayIndexOutOfBoundsException JavaDoc(axis);
235             }
236         }
237
238         public void setAxis(int axis, int value) {
239             switch (axis) {
240             case 0:
241                 ordinal0 = value;
242                 break;
243             default:
244                 throw new ArrayIndexOutOfBoundsException JavaDoc(axis);
245             }
246         }
247
248         public One copy() {
249             return new One(ordinal0);
250         }
251
252         public boolean equals(Object JavaDoc o) {
253             // here we cheat, we know that all CellKey's will be the same size
254
if (o instanceof One) {
255                 One other = (One) o;
256                 return (this.ordinal0 == other.ordinal0);
257             } else if (o instanceof Many) {
258                 Many many = (Many) o;
259                 return many.ordinals.length == 1 &&
260                     many.ordinals[0] == this.ordinal0;
261             } else {
262                 return false;
263             }
264         }
265
266         public String JavaDoc toString() {
267             return "(" + ordinal0 + ")";
268         }
269
270         public int hashCode() {
271             return 17 + ordinal0;
272         }
273     }
274
275     public class Two implements CellKey {
276         private int ordinal0;
277         private int ordinal1;
278
279         /**
280          * Creates a Two.
281          *
282          * @param ordinal0 Ordinate #0
283          * @param ordinal1 Ordinate #1
284          */

285         private Two(int ordinal0, int ordinal1) {
286             this.ordinal0 = ordinal0;
287             this.ordinal1 = ordinal1;
288         }
289
290         public String JavaDoc toString() {
291             return "(" + ordinal0 + ", " + ordinal1 + ")";
292         }
293
294         public Two copy() {
295             return new Two(ordinal0, ordinal1);
296         }
297
298         public boolean equals(Object JavaDoc o) {
299             if (o instanceof Two) {
300                 Two other = (Two) o;
301                 return (other.ordinal0 == this.ordinal0) &&
302                        (other.ordinal1 == this.ordinal1);
303             } else if (o instanceof Many) {
304                 Many many = (Many) o;
305                 return many.ordinals.length == 2 &&
306                     many.ordinals[0] == this.ordinal0 &&
307                     many.ordinals[1] == this.ordinal1;
308             } else {
309                 return false;
310             }
311         }
312
313         public int hashCode() {
314             int h0 = 17 + ordinal0;
315             return h0 * 37 + ordinal1;
316         }
317
318         public int size() {
319             return 2;
320         }
321
322         public int[] getOrdinals() {
323             return new int[] {ordinal0, ordinal1};
324         }
325
326         public void setOrdinals(int[] pos) {
327             if (pos.length != 2) {
328                 throw new IllegalArgumentException JavaDoc();
329             }
330             ordinal0 = pos[0];
331             ordinal1 = pos[1];
332         }
333
334         public int getAxis(int axis) {
335             switch (axis) {
336             case 0:
337                 return ordinal0;
338             case 1:
339                 return ordinal1;
340             default:
341                 throw new ArrayIndexOutOfBoundsException JavaDoc(axis);
342             }
343         }
344
345         public void setAxis(int axis, int value) {
346             switch (axis) {
347             case 0:
348                 ordinal0 = value;
349                 break;
350             case 1:
351                 ordinal1 = value;
352                 break;
353             default:
354                 throw new ArrayIndexOutOfBoundsException JavaDoc(axis);
355             }
356         }
357     }
358
359     class Three implements CellKey {
360         private int ordinal0;
361         private int ordinal1;
362         private int ordinal2;
363
364         /**
365          * Creates a Three.
366          *
367          * @param ordinal0 Ordinate #0
368          * @param ordinal1 Ordinate #1
369          * @param ordinal2 Ordinate #2
370          */

371         private Three(int ordinal0, int ordinal1, int ordinal2) {
372             this.ordinal0 = ordinal0;
373             this.ordinal1 = ordinal1;
374             this.ordinal2 = ordinal2;
375         }
376
377         public String JavaDoc toString() {
378             return "(" + ordinal0 + ", " + ordinal1 + ", " + ordinal2 + ")";
379         }
380
381         public Three copy() {
382             return new Three(ordinal0, ordinal1, ordinal2);
383         }
384
385         public boolean equals(Object JavaDoc o) {
386             // here we cheat, we know that all CellKey's will be the same size
387
if (o instanceof Three) {
388                 Three other = (Three) o;
389                 return (other.ordinal0 == this.ordinal0) &&
390                        (other.ordinal1 == this.ordinal1) &&
391                        (other.ordinal2 == this.ordinal2);
392             } else if (o instanceof Many) {
393                 Many many = (Many) o;
394                 return many.ordinals.length == 3 &&
395                     many.ordinals[0] == this.ordinal0 &&
396                     many.ordinals[1] == this.ordinal1 &&
397                     many.ordinals[2] == this.ordinal2;
398             } else {
399                 return false;
400             }
401         }
402
403         public int hashCode() {
404             int h0 = 17 + ordinal0;
405             int h1 = h0 * 37 + ordinal1;
406             return h1 * 37 + ordinal2;
407         }
408
409         public int getAxis(int axis) {
410             switch (axis) {
411             case 0:
412                 return ordinal0;
413             case 1:
414                 return ordinal1;
415             case 2:
416                 return ordinal2;
417             default:
418                 throw new ArrayIndexOutOfBoundsException JavaDoc(axis);
419             }
420         }
421
422         public void setAxis(int axis, int value) {
423             switch (axis) {
424             case 0:
425                 ordinal0 = value;
426                 break;
427             case 1:
428                 ordinal1 = value;
429                 break;
430             case 2:
431                 ordinal2 = value;
432                 break;
433             default:
434                 throw new ArrayIndexOutOfBoundsException JavaDoc(axis);
435             }
436         }
437
438         public int size() {
439             return 3;
440         }
441
442         public int[] getOrdinals() {
443             return new int[] {ordinal0, ordinal1, ordinal2};
444         }
445
446         public void setOrdinals(int[] pos) {
447             if (pos.length != 3) {
448                 throw new IllegalArgumentException JavaDoc();
449             }
450             ordinal0 = pos[0];
451             ordinal1 = pos[1];
452             ordinal2 = pos[2];
453         }
454     }
455
456     public class Many implements CellKey {
457         private final int[] ordinals;
458
459         /**
460          * Creates a Many.
461          * @param ordinals Ordinates
462          */

463         protected Many(int[] ordinals) {
464             this.ordinals = ordinals;
465         }
466
467         public final int size() {
468             return this.ordinals.length;
469         }
470
471         public final void setOrdinals(int[] pos) {
472             if (ordinals.length != pos.length) {
473                 throw new IllegalArgumentException JavaDoc();
474             }
475             System.arraycopy(pos, 0, this.ordinals, 0, ordinals.length);
476         }
477         public final int[] getOrdinals() {
478             return this.ordinals;
479         }
480
481         public void setAxis(int axis, int value) {
482             this.ordinals[axis] = value;
483         }
484
485         public int getAxis(int axis) {
486             return this.ordinals[axis];
487         }
488
489         public String JavaDoc toString() {
490             StringBuilder JavaDoc buf = new StringBuilder JavaDoc();
491             buf.append('(');
492             for (int i = 0; i < ordinals.length; i++) {
493                 if (i > 0) {
494                     buf.append(',');
495                 }
496                 buf.append(ordinals[i]);
497             }
498             buf.append(')');
499             return buf.toString();
500         }
501
502         public Many copy() {
503             return new Many(this.ordinals.clone());
504         }
505
506         public int hashCode() {
507             int h = 17;
508             for (int ordinal : ordinals) {
509                 h = (h * 37) + ordinal;
510             }
511             return h;
512         }
513
514         public boolean equals(Object JavaDoc o) {
515             if (o instanceof Many) {
516                 Many that = (Many) o;
517                 return Arrays.equals(this.ordinals, that.ordinals);
518             } else {
519                 // Use symmetric logic in One, Two, Three.
520
return o.equals(this);
521             }
522         }
523     }
524 }
525
526 // End CellKey.java
527
Popular Tags