KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > rolap > RolapDimension


1 /*
2  // $Id: //open/mondrian/src/main/mondrian/rolap/RolapDimension.java#23 $
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-2006 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 org.apache.log4j.Logger;
17 import mondrian.olap.*;
18 import mondrian.resource.MondrianResource;
19
20 /**
21  * <code>RolapDimension</code> implements {@link Dimension}for a ROLAP
22  * database.
23  *
24  * <h2><a name="topic_ordinals">Topic: Dimension ordinals </a></h2>
25  *
26  * {@link RolapEvaluator} needs each dimension to have an ordinal, so that it
27  * can store the evaluation context as an array of members. When virtual cubes
28  * and shared dimensions enter the picture, we find that dimensions' ordinals
29  * must be unique within the whole schema, not just their cube.
30  *
31  * <p>
32  * The ordinal of a dimension <em>within a particular cube</em> is found by
33  * calling {@link #getOrdinal(Cube)}, which is implemented in terms of the
34  * {@link RolapCube#localDimensionOrdinals} map. This map converts a
35  * dimension's global ordinal into a local one within the cube. Local ordinals
36  * are contiguous and zero-based. Zero is always the <code>[Measures]</code>
37  * dimension.
38  *
39  * <p>
40  * A dimension may be either shared or private to a particular cube. The
41  * dimension object doesn't actually know which; {@link Schema} has a list of
42  * shared hierarchies ({@link Schema#getSharedHierarchies}), and {@link Cube}
43  * has a list of dimensions ({@link Cube#getDimensions}).
44  *
45  * <p>
46  * If a dimension is shared between several cubes, the {@link Dimension}objects
47  * which represent them may (or may not be) the same. (That's why there's no
48  * <code>getCube()</code> method.)
49  *
50  * <p>
51  * Furthermore, since members are created by a {@link MemberReader}which
52  * belongs to the {@link RolapHierarchy}, you will the members will be the same
53  * too. For example, if you query <code>[Product].[Beer]</code> from the
54  * <code>Sales</code> and <code>Warehouse</code> cubes, you will get the
55  * same {@link RolapMember}object.
56  * ({@link RolapSchema#mapSharedHierarchyToReader} holds the mapping. I don't
57  * know whether it's still necessary.)
58  *
59  * @author jhyde
60  * @since 10 August, 2001
61  * @version $Id: //open/mondrian/src/main/mondrian/rolap/RolapDimension.java#23 $
62  */

63 class RolapDimension extends DimensionBase {
64
65     private static final Logger LOGGER = Logger.getLogger(RolapDimension.class);
66
67     /** Generator for {@link #globalOrdinal}. * */
68     synchronized int getNextOrdinal() {
69         return schema.getNextDimensionOrdinal();
70     }
71
72     private final Schema schema;
73
74     RolapDimension(Schema schema,
75                    String JavaDoc name,
76                    int globalOrdinal,
77                    DimensionType dimensionType) {
78         super(
79                 name,
80                 globalOrdinal,
81                 // todo: recognition of a time dimension should be improved
82
// allow multiple time dimensions
83
dimensionType);
84
85         this.schema = schema;
86         Util.assertTrue((globalOrdinal == 0) == name.equals(MEASURES_NAME));
87         this.hierarchies = new RolapHierarchy[0];
88     }
89
90     /**
91      * Creates a dimension from an XML definition.
92      *
93      * @pre schema != null
94      */

95     RolapDimension(RolapSchema schema,
96                    RolapCube cube,
97                    MondrianDef.Dimension xmlDimension,
98                    MondrianDef.CubeDimension xmlCubeDimension) {
99         this(schema,
100              xmlDimension.name,
101              chooseOrdinal(cube, xmlCubeDimension),
102              xmlDimension.getDimensionType());
103
104         Util.assertPrecondition(schema != null);
105
106         if (cube != null) {
107             Util.assertTrue(cube.getSchema() == schema);
108         }
109
110         if (!Util.isEmpty(xmlDimension.caption)) {
111             setCaption(xmlDimension.caption);
112         }
113         this.hierarchies = new RolapHierarchy[xmlDimension.hierarchies.length];
114         for (int i = 0; i < xmlDimension.hierarchies.length; i++) {
115             RolapHierarchy hierarchy = new RolapHierarchy(
116                 cube, this, xmlDimension.hierarchies[i],
117                 xmlCubeDimension);
118             hierarchies[i] = hierarchy;
119         }
120
121         // if there was no dimension type assigned, determine now.
122
if (dimensionType == null) {
123             for (int i = 0; i < hierarchies.length; i++) {
124                 Level[] levels = hierarchies[i].getLevels();
125                 LevLoop:
126                 for (int j = 0; j < levels.length; j++) {
127                     Level lev = levels[j];
128                     if (lev.isAll()) {
129                         continue LevLoop;
130                     }
131                     if (dimensionType == null) {
132                         // not set yet - set it according to current level
133
dimensionType = (lev.getLevelType().isTime())
134                             ? DimensionType.TimeDimension
135                             : DimensionType.StandardDimension;
136
137                     } else {
138                         // Dimension type was set according to first level.
139
// Make sure that other levels fit to definition.
140
if (dimensionType == DimensionType.TimeDimension &&
141                             !lev.getLevelType().isTime() &&
142                             !lev.isAll()) {
143                             throw MondrianResource.instance().NonTimeLevelInTimeHierarchy.ex(
144                                     getUniqueName());
145                         }
146                         if (dimensionType != DimensionType.TimeDimension &&
147                             lev.getLevelType().isTime()) {
148                             throw MondrianResource.instance().TimeLevelInNonTimeHierarchy.ex(
149                                     getUniqueName());
150                         }
151                     }
152                 }
153             }
154         }
155     }
156
157     protected Logger getLogger() {
158         return LOGGER;
159     }
160
161     /**
162      * Assigns an ordinal for a dimension usage; also assigns the join-level of
163      * the usage.
164      */

165     private static int chooseOrdinal(RolapCube cube,
166                             MondrianDef.CubeDimension xmlCubeDimension) {
167
168         if (xmlCubeDimension.name.equals(MEASURES_NAME)) {
169             return 0;
170         }
171         RolapSchema schema = (RolapSchema) cube.getSchema();
172         if (xmlCubeDimension instanceof MondrianDef.DimensionUsage) {
173             MondrianDef.DimensionUsage usage =
174                 (MondrianDef.DimensionUsage) xmlCubeDimension;
175             RolapHierarchy hierarchy = schema.getSharedHierarchy(usage.source);
176             if (hierarchy != null) {
177                 cube.createUsage(hierarchy, usage);
178
179                 RolapDimension dimension =
180                     (RolapDimension) hierarchy.getDimension();
181                 return dimension.getGlobalOrdinal();
182             }
183         }
184         return schema.getNextDimensionOrdinal();
185     }
186
187     /**
188      * Initializes a dimension within the context of a cube.
189      */

190     void init(RolapCube cube, MondrianDef.CubeDimension xmlDimension) {
191         for (int i = 0; i < hierarchies.length; i++) {
192             if (hierarchies[i] != null) {
193                 ((RolapHierarchy) hierarchies[i]).init(cube, xmlDimension);
194             }
195         }
196     }
197
198     RolapHierarchy newHierarchy(String JavaDoc subName, boolean hasAll) {
199         RolapHierarchy hierarchy = new RolapHierarchy(this, subName, hasAll);
200         this.hierarchies = (RolapHierarchy[])
201             RolapUtil.addElement(this.hierarchies, hierarchy);
202         return hierarchy;
203     }
204
205     /**
206      * Returns the hierarchy of an expression.
207      *
208      * <p>In this case, the expression is a dimension, so the hierarchy is the
209      * dimension's default hierarchy (its first).
210      */

211     public Hierarchy getHierarchy() {
212         return hierarchies[0];
213     }
214
215     public int getOrdinal(Cube cube) {
216         return ((RolapCube) cube).getOrdinal(this.globalOrdinal);
217     }
218
219     public Schema getSchema() {
220         return schema;
221     }
222
223     /**
224      * Returns the ordinal of this dimension, unique within its schema.
225      */

226     int getGlobalOrdinal() {
227         return globalOrdinal;
228     }
229
230     /**
231      * Returns a copy of this dimension with a different name.
232      *
233      * @param cube
234      * @param name Name for the new dimension.
235      * @param xmlCubeDimension
236      */

237     public RolapDimension copy(
238             RolapCube cube,
239             String JavaDoc name,
240             MondrianDef.CubeDimension xmlCubeDimension) {
241         RolapDimension dimension = new RolapDimension(
242             schema,
243             name,
244             getNextOrdinal(),
245             dimensionType);
246         dimension.hierarchies = (Hierarchy[]) hierarchies.clone();
247         for (int i = 0; i < hierarchies.length; i++) {
248             final RolapHierarchy hierarchy = (RolapHierarchy) hierarchies[i];
249             dimension.hierarchies[i] = new RolapHierarchy(cube, dimension,
250                 hierarchy.xmlHierarchy, xmlCubeDimension);
251         }
252         return dimension;
253     }
254 }
255
256 // End RolapDimension.java
257
Popular Tags