KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > rolap > Modulos


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/rolap/Modulos.java#3 $
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.rolap;
11
12 import mondrian.olap.Axis;
13
14 /**
15  * Modulos implementations encapsulate algorithms to map between integral
16  * ordinals and position arrays. There are particular implementations for
17  * the most likely cases where the number of axes is 1, 2 and 3
18  * as well as a general implementation.
19  * <p>
20  * Suppose the result is 4 x 3 x 2, then modulo = {1, 4, 12, 24}.
21  *
22  * <p>
23  * Then the ordinal of cell (3, 2, 1)
24  * <p><blockquote><pre>
25  * = (modulo[0] * 3) + (modulo[1] * 2) + (modulo[2] * 1)
26  * = (1 * 3) + (4 * 2) + (12 * 1)
27  * = 23
28  * </pre></blockquote><p>
29  * <p>
30  * Reverse calculation:
31  * <p><blockquote><pre>
32  * p[0] = (23 % modulo[1]) / modulo[0] = (23 % 4) / 1 = 3
33  * p[1] = (23 % modulo[2]) / modulo[1] = (23 % 12) / 4 = 2
34  * p[2] = (23 % modulo[3]) / modulo[2] = (23 % 24) / 12 = 1
35  * </pre></blockquote><p>
36  *
37  * @author jhyde
38  * @version $Id: //open/mondrian/src/main/mondrian/rolap/Modulos.java#3 $
39  */

40 public interface Modulos {
41     public class Generator {
42         public static Modulos create(Axis[] axes) {
43             switch (axes.length) {
44             case 0:
45                 return new Modulos.Zero(axes);
46             case 1:
47                 return new Modulos.One(axes);
48             case 2:
49                 return new Modulos.Two(axes);
50             case 3:
51                 return new Modulos.Three(axes);
52             default:
53                 return new Modulos.Many(axes);
54             }
55         }
56         // Used for testing only
57
public static Modulos createMany(Axis[] axes) {
58             return new Modulos.Many(axes);
59         }
60         public static Modulos createMany(int[] lengths) {
61             return new Modulos.Many(lengths);
62         }
63     }
64     public abstract class Base implements Modulos {
65         protected final int[] modulos;
66         protected Base(final Axis[] axes) {
67             this.modulos = new int[axes.length+1];
68             this.modulos[0] = 1;
69         }
70         protected Base(final int[] lengths) {
71             this.modulos = new int[lengths.length+1];
72             this.modulos[0] = 1;
73         }
74         public abstract int[] getCellPos(int cellOrdinal);
75         public abstract int getCellOrdinal(int[] pos);
76
77         public String JavaDoc toString() {
78             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
79             buf.append('(');
80             for (int i = 0; i < modulos.length; i++) {
81                 if (i > 0) {
82                     buf.append(',');
83                 }
84                 buf.append(modulos[i]);
85             }
86             buf.append(')');
87             return buf.toString();
88         }
89     }
90     public class Zero extends Base {
91         private Zero(final Axis[] axes) {
92             super(axes);
93         }
94         public final int[] getCellPos(final int cellOrdinal) {
95             int[] pos = new int[0];
96             return pos;
97         }
98         public final int getCellOrdinal(final int[] pos) {
99             return 0;
100         }
101     }
102     public class One extends Base {
103         private One(final Axis[] axes) {
104             super(axes);
105
106             this.modulos[1] = axes[0].getPositions().size();
107         }
108         public final int[] getCellPos(final int cellOrdinal) {
109             return new int[] {
110                 (cellOrdinal % this.modulos[1])
111             };
112         }
113         public final int getCellOrdinal(final int[] pos) {
114             return (pos[0] * modulos[0]);
115         }
116     }
117     public class Two extends Base {
118         private Two(final Axis[] axes) {
119             super(axes);
120
121             int modulo = axes[0].getPositions().size();
122             this.modulos[1] = modulo;
123             modulo *= axes[1].getPositions().size();
124             this.modulos[2] = modulo;
125         }
126         public final int[] getCellPos(final int cellOrdinal) {
127             final int[] modulos = this.modulos;
128             return new int[] {
129                 (cellOrdinal % modulos[1]),
130                 (cellOrdinal % modulos[2]) / modulos[1]
131             };
132         }
133         public final int getCellOrdinal(final int[] pos) {
134             final int[] modulos = this.modulos;
135             return (pos[0] * modulos[0]) +
136                    (pos[1] * modulos[1]);
137         }
138     }
139     public class Three extends Base {
140         private Three(final Axis[] axes) {
141             super(axes);
142
143             int modulo = axes[0].getPositions().size();
144             this.modulos[1] = modulo;
145             modulo *= axes[1].getPositions().size();
146             this.modulos[2] = modulo;
147             modulo *= axes[2].getPositions().size();
148             this.modulos[3] = modulo;
149         }
150         public final int[] getCellPos(final int cellOrdinal) {
151             final int[] modulos = this.modulos;
152             return new int[] {
153                 (cellOrdinal % modulos[1]),
154                 (cellOrdinal % modulos[2]) / modulos[1],
155                 (cellOrdinal % modulos[3]) / modulos[2]
156             };
157         }
158         public final int getCellOrdinal(final int[] pos) {
159             final int[] modulos = this.modulos;
160             return (pos[0] * modulos[0]) +
161                    (pos[1] * modulos[1]) +
162                    (pos[2] * modulos[2]);
163         }
164     }
165     public class Many extends Base {
166         private Many(final Axis[] axes) {
167             super(axes);
168
169             int modulo = 1;
170             for (int i = 0; i < axes.length; i++) {
171                 modulo *= axes[i].getPositions().size();
172                 this.modulos[i + 1] = modulo;
173             }
174         }
175         private Many(final int[] lengths) {
176             super(lengths);
177
178             int modulo = 1;
179             for (int i = 0; i < lengths.length; i++) {
180                 modulo *= lengths[i];
181                 this.modulos[i + 1] = modulo;
182             }
183         }
184         public int[] getCellPos(final int cellOrdinal) {
185             final int[] modulos = this.modulos;
186             final int size = modulos.length - 1;
187             final int[] pos = new int[size];
188             for (int i = 0; i < size; i++) {
189                 pos[i] = (cellOrdinal % modulos[i + 1]) / modulos[i];
190             }
191             return pos;
192         }
193         public int getCellOrdinal(final int[] pos) {
194             final int[] modulos = this.modulos;
195             final int size = modulos.length - 1;
196             int ordinal = 0;
197             for (int i = 0; i < size; i++) {
198                 ordinal += pos[i] * modulos[i];
199             }
200             return ordinal;
201         }
202     }
203
204     /**
205      * Converts a cell ordinal to a set of cell coordinates. Converse of
206      * {@link #getCellOrdinal}. For example, if this result is 10 x 10 x 10,
207      * then cell ordinal 537 has coordinates (5, 3, 7).
208      */

209     int[] getCellPos(int cellOrdinal);
210
211     /**
212      * Converts a set of cell coordinates to a cell ordinal. Converse of
213      * {@link #getCellPos}.
214      */

215     int getCellOrdinal(int[] pos);
216 }
217
Popular Tags