001 /*
002 // $Id: //open/mondrian-release/3.2/src/main/mondrian/olap/CubeBase.java#1 $
003 // This software is subject to the terms of the Eclipse Public License v1.0
004 // Agreement, available at the following URL:
005 // http://www.eclipse.org/legal/epl-v10.html.
006 // Copyright (C) 2001-2002 Kana Software, Inc.
007 // Copyright (C) 2001-2009 Julian Hyde and others
008 // All Rights Reserved.
009 // You must accept the terms of that agreement to use this software.
010 //
011 // jhyde, 6 August, 2001
012 */
013
014 package mondrian.olap;
015
016 import mondrian.resource.MondrianResource;
017
018 import java.util.List;
019
020 /**
021 * <code>CubeBase</code> is an abstract implementation of {@link Cube}.
022 *
023 * @author jhyde
024 * @since 6 August, 2001
025 * @version $Id: //open/mondrian-release/3.2/src/main/mondrian/olap/CubeBase.java#1 $
026 */
027 public abstract class CubeBase extends OlapElementBase implements Cube {
028
029 /** constraints indexes for adSchemaMembers
030 *
031 * http://msdn.microsoft.com/library/psdk/dasdk/mdx8h4k.htm
032 * check "Restrictions in the MEMBER Rowset" under MEMBER Rowset section
033 */
034 public static final int CATALOG_NAME = 0;
035 public static final int SCHEMA_NAME = 1;
036 public static final int CUBE_NAME = 2;
037 public static final int DIMENSION_UNIQUE_NAME = 3;
038 public static final int HIERARCHY_UNIQUE_NAME = 4;
039 public static final int LEVEL_UNIQUE_NAME = 5;
040 public static final int LEVEL_NUMBER = 6;
041 public static final int MEMBER_NAME = 7;
042 public static final int MEMBER_UNIQUE_NAME = 8;
043 public static final int MEMBER_CAPTION = 9;
044 public static final int MEMBER_TYPE = 10;
045 public static final int Tree_Operator = 11;
046 public static final int maxNofConstraintsForAdSchemaMember = 12;
047 public static final int MDTREEOP_SELF = 0;
048 public static final int MDTREEOP_CHILDREN = 1;
049 public static final int MDPROP_USERDEFINED0 = 19;
050
051 protected final String name;
052 private final String uniqueName;
053 private final String description;
054 protected Dimension[] dimensions;
055
056 /**
057 * Creates a CubeBase.
058 *
059 * @param name Name
060 * @param caption Caption
061 * @param description Description
062 * @param dimensions List of dimensions
063 */
064 protected CubeBase(
065 String name,
066 String caption,
067 String description,
068 Dimension[] dimensions)
069 {
070 this.name = name;
071 this.caption = caption;
072 this.description = description;
073 this.dimensions = dimensions;
074 this.uniqueName = Util.quoteMdxIdentifier(name);
075 }
076
077 // implement OlapElement
078 public String getName() {
079 return name;
080 }
081
082 public String getUniqueName() {
083 // return e.g. '[Sales Ragged]'
084 return uniqueName;
085 }
086
087 public String getQualifiedName() {
088 return MondrianResource.instance().MdxCubeName.str(getName());
089 }
090
091 public Dimension getDimension() {
092 return null;
093 }
094
095 public Hierarchy getHierarchy() {
096 return null;
097 }
098
099 public String getDescription() {
100 return description;
101 }
102
103 public Dimension[] getDimensions() {
104 return dimensions;
105 }
106
107 public Hierarchy lookupHierarchy(Id.Segment s, boolean unique) {
108 for (Dimension dimension : dimensions) {
109 Hierarchy[] hierarchies = dimension.getHierarchies();
110 for (Hierarchy hierarchy : hierarchies) {
111 String name = unique
112 ? hierarchy.getUniqueName() : hierarchy.getName();
113 if (name.equals(s.name)) {
114 return hierarchy;
115 }
116 }
117 }
118 return null;
119 }
120
121 public OlapElement lookupChild(
122 SchemaReader schemaReader,
123 Id.Segment s,
124 MatchType matchType)
125 {
126 Dimension mdxDimension = lookupDimension(s);
127 if (mdxDimension != null) {
128 return mdxDimension;
129 }
130
131 final List<Dimension> dimensions = schemaReader.getCubeDimensions(this);
132
133 // Look for hierarchies named '[dimension.hierarchy]'.
134 if (MondrianProperties.instance().SsasCompatibleNaming.get()
135 && s.name.contains("."))
136 {
137 for (Dimension dimension : dimensions) {
138 if (!s.name.startsWith(dimension.getName())) {
139 // Rough check to save time.
140 continue;
141 }
142 for (Hierarchy hierarchy
143 : schemaReader.getDimensionHierarchies(dimension))
144 {
145 if (Util.equalName(
146 s.name,
147 dimension.getName()
148 + "."
149 + hierarchy.getName()))
150 {
151 return hierarchy;
152 }
153 }
154 }
155 }
156
157 // Try hierarchies, levels and members.
158 for (Dimension dimension : dimensions) {
159 OlapElement mdxElement = dimension.lookupChild(
160 schemaReader, s, matchType);
161 if (mdxElement != null) {
162 if (mdxElement instanceof Member
163 && MondrianProperties.instance().NeedDimensionPrefix.get())
164 {
165 // With this property setting, don't allow members to be
166 // referenced without at least a dimension prefix. We
167 // allow [Store].[USA].[CA] or even [Store].[CA] but not
168 // [USA].[CA].
169 continue;
170 }
171 return mdxElement;
172 }
173 }
174 return null;
175 }
176
177 /**
178 * Looks up a dimension in this cube based on a component of its name.
179 *
180 * @param s Name segment
181 * @return Dimension, or null if not found
182 */
183 public Dimension lookupDimension(Id.Segment s) {
184 for (Dimension dimension : dimensions) {
185 if (Util.equalName(dimension.getName(), s.name)) {
186 return dimension;
187 }
188 }
189 return null;
190 }
191
192 // ------------------------------------------------------------------------
193
194 /**
195 * Returns the first level of a given type in this cube.
196 *
197 * @param levelType Level type
198 * @return First level of given type, or null
199 */
200 private Level getTimeLevel(LevelType levelType) {
201 for (Dimension dimension : dimensions) {
202 if (dimension.getDimensionType() == DimensionType.TimeDimension) {
203 Hierarchy[] hierarchies = dimension.getHierarchies();
204 for (Hierarchy hierarchy : hierarchies) {
205 Level[] levels = hierarchy.getLevels();
206 for (Level level : levels) {
207 if (level.getLevelType() == levelType) {
208 return level;
209 }
210 }
211 }
212 }
213 }
214 return null;
215 }
216
217 public Level getYearLevel() {
218 return getTimeLevel(LevelType.TimeYears);
219 }
220
221 public Level getQuarterLevel() {
222 return getTimeLevel(LevelType.TimeQuarters);
223 }
224
225 public Level getMonthLevel() {
226 return getTimeLevel(LevelType.TimeMonths);
227 }
228
229 public Level getWeekLevel() {
230 return getTimeLevel(LevelType.TimeWeeks);
231 }
232 }
233
234 // End CubeBase.java