001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2003-2005 Julian Hyde 008// Copyright (C) 2005-2012 Pentaho 009// All Rights Reserved. 010*/ 011package mondrian.olap; 012 013import mondrian.calc.Calc; 014import mondrian.rolap.RolapHierarchy; 015import mondrian.rolap.RolapSchema; 016 017import java.util.List; 018import java.util.Map; 019 020import javax.sql.DataSource; 021 022/** 023 * A <code>SchemaReader</code> queries schema objects ({@link Schema}, 024 * {@link Cube}, {@link Dimension}, {@link Hierarchy}, {@link Level}, 025 * {@link Member}). 026 * 027 * <p>It is generally created using {@link Connection#getSchemaReader}, 028 * but also via {@link Cube#getSchemaReader(Role)}.</p> 029 * 030 * <p>SchemaReader is deprecated for code outside of mondrian. For new code, 031 * use the metadata provided by olap4j, for example 032 * {@link mondrian.olap4j.MondrianOlap4jSchema#getCubes()}. 033 * 034 * <p>If you use a SchemaReader from outside of a mondrian statement, you may 035 * get a {@link java.util.EmptyStackException} indicating that mondrian cannot 036 * deduce the current locus (statement context). If you get that error, call 037 * {@link #withLocus()} to create a SchemaReader that automatically provides a 038 * locus whenever a call is made.</p> 039 * 040 * @author jhyde 041 * @since Feb 24, 2003 042 */ 043public interface SchemaReader { 044 /** 045 * Returns the schema. 046 * 047 * @return Schema, never null 048 */ 049 RolapSchema getSchema(); 050 051 /** 052 * Returns the access-control profile that this <code>SchemaReader</code> 053 * is implementing. 054 */ 055 Role getRole(); 056 057 /** 058 * Returns the accessible dimensions of a cube. 059 * 060 * @pre dimension != null 061 * @post return != null 062 */ 063 List<Dimension> getCubeDimensions(Cube cube); 064 065 /** 066 * Returns the accessible hierarchies of a dimension. 067 * 068 * @pre dimension != null 069 * @post return != null 070 */ 071 List<Hierarchy> getDimensionHierarchies(Dimension dimension); 072 073 /** 074 * Returns an array of the root members of <code>hierarchy</code>. 075 * 076 * @param hierarchy Hierarchy 077 * @see #getCalculatedMembers(Hierarchy) 078 */ 079 List<Member> getHierarchyRootMembers(Hierarchy hierarchy); 080 081 /** 082 * Returns number of children parent of a member, 083 * if the information can be retrieved from cache, otherwise -1. 084 */ 085 int getChildrenCountFromCache(Member member); 086 087 /** 088 * Returns the number of members in a level, returning an approximation if 089 * acceptable. 090 * 091 * @param level Level 092 * @param approximate Whether an approximation is acceptable 093 * @param materialize Whether to go to disk if no approximation 094 * for the count is available and the members are not in 095 * cache. If false, returns {@link Integer#MIN_VALUE} if value 096 * is not in cache. 097 */ 098 int getLevelCardinality( 099 Level level, boolean approximate, boolean materialize); 100 101 /** 102 * Substitutes a member with an equivalent member which enforces the 103 * access control policy of this SchemaReader. 104 */ 105 Member substitute(Member member); 106 107 /** 108 * Returns direct children of <code>member</code>. 109 * @pre member != null 110 * @post return != null 111 */ 112 List<Member> getMemberChildren(Member member); 113 114 /** 115 * Returns direct children of <code>member</code>, optimized 116 * for NON EMPTY. 117 * <p> 118 * If <code>context == null</code> then 119 * there is no context and all members are returned - then 120 * its identical to {@link #getMemberChildren(Member)}. 121 * If <code>context</code> is not null, the resulting members 122 * <em>may</em> be restricted to those members that have a 123 * non empty row in the fact table for <code>context</code>. 124 * Wether or not optimization is possible depends 125 * on the SchemaReader implementation. 126 */ 127 List<Member> getMemberChildren(Member member, Evaluator context); 128 129 /** 130 * Returns direct children of each element of <code>members</code>. 131 * 132 * @param members Array of members 133 * @return array of child members 134 * 135 * @pre members != null 136 * @post return != null 137 */ 138 List<Member> getMemberChildren(List<Member> members); 139 140 /** 141 * Returns direct children of each element of <code>members</code> 142 * which is not empty in <code>context</code>. 143 * 144 * @param members Array of members 145 * @param context Evaluation context 146 * @return array of child members 147 * 148 * @pre members != null 149 * @post return != null 150 */ 151 List<Member> getMemberChildren(List<Member> members, Evaluator context); 152 153 /** 154 * Returns a list of contributing children of a member of a parent-child 155 * hierarchy. 156 * 157 * @param dataMember Data member for a member of the parent-child hierarcy 158 * @param hierarchy Hierarchy 159 * @param list List of members to populate 160 */ 161 void getParentChildContributingChildren( 162 Member dataMember, 163 Hierarchy hierarchy, 164 List<Member> list); 165 166 /** 167 * Returns the parent of <code>member</code>. 168 * 169 * @param member Member 170 * @pre member != null 171 * @return null if member is a root member 172 */ 173 Member getMemberParent(Member member); 174 175 /** 176 * Returns a list of ancestors of <code>member</code>, in depth order. 177 * 178 * <p>For example, for [Store].[USA].[CA], returns 179 * {[Store].[USA], [Store].[All Stores]}. 180 * 181 * @param member Member 182 * @param ancestorList List of ancestors 183 */ 184 void getMemberAncestors(Member member, List<Member> ancestorList); 185 186 /** 187 * Returns the depth of a member. 188 * 189 * <p>This may not be the same as 190 * <code>member.{@link Member#getLevel getLevel}(). 191 * {@link Level#getDepth getDepth}()</code> 192 * for three reasons:<ol> 193 * <li><b>Access control</b>. The most senior <em>visible</em> member has 194 * level 0. If the client is not allowed to see the "All" and "Nation" 195 * levels of the "Store" hierarchy, then members of the "State" level will 196 * have depth 0.</li> 197 * <li><b>Parent-child hierarchies</b>. Suppose Fred reports to Wilma, and 198 * Wilma reports to no one. "All Employees" has depth 0, Wilma has depth 199 * 1, and Fred has depth 2. Fred and Wilma are both in the "Employees" 200 * level, which has depth 1.</li> 201 * <li><b>Ragged hierarchies</b>. If Israel has only one, hidden, province 202 * then the depth of Tel Aviv, Israel is 2, whereas the depth of another 203 * city, San Francisco, CA, USA is 3.</li> 204 * </ol> 205 */ 206 int getMemberDepth(Member member); 207 208 /** 209 * Finds a member based upon its unique name. 210 * 211 * @param uniqueNameParts Unique name of member 212 * @param failIfNotFound Whether to throw an error, as opposed to returning 213 * <code>null</code>, if there is no such member. 214 * @param matchType indicates the match mode; if not specified, EXACT 215 * @return The member, or null if not found 216 */ 217 Member getMemberByUniqueName( 218 List<Id.Segment> uniqueNameParts, 219 boolean failIfNotFound, 220 MatchType matchType); 221 222 /** 223 * Finds a member based upon its unique name, requiring an exact match. 224 * 225 * <p>This method is equivalent to calling 226 * {@link #getMemberByUniqueName(java.util.List, boolean, MatchType)} 227 * with {@link MatchType#EXACT}. 228 * 229 * @param uniqueNameParts Unique name of member 230 * @param failIfNotFound Whether to throw an error, as opposed to returning 231 * <code>null</code>, if there is no such member. 232 * @return The member, or null if not found 233 */ 234 Member getMemberByUniqueName( 235 List<Id.Segment> uniqueNameParts, 236 boolean failIfNotFound); 237 238 /** 239 * Looks up an MDX object by name, specifying how to 240 * match if no object exactly matches the name. 241 * 242 * <p>Resolves a name such as 243 * '[Products].[Product Department].[Produce]' by resolving the 244 * components ('Products', and so forth) one at a time. 245 * 246 * @param parent Parent element to search in 247 * @param names Exploded compound name, such as {"Products", 248 * "Product Department", "Produce"} 249 * @param failIfNotFound If the element is not found, determines whether 250 * to return null or throw an error 251 * @param category Type of returned element, a {@link Category} value; 252 * {@link Category#Unknown} if it doesn't matter. 253 * @param matchType indicates the match mode; if not specified, EXACT 254 * 255 * @pre parent != null 256 * @post !(failIfNotFound && return == null) 257 */ 258 OlapElement lookupCompound( 259 OlapElement parent, 260 List<Id.Segment> names, 261 boolean failIfNotFound, 262 int category, 263 MatchType matchType); 264 265 /** 266 * Looks up an MDX object by name. 267 * 268 * <p>Resolves a name such as 269 * '[Products].[Product Department].[Produce]' by resolving the 270 * components ('Products', and so forth) one at a time. 271 * 272 * @param parent Parent element to search in 273 * @param names Exploded compound name, such as {"Products", 274 * "Product Department", "Produce"} 275 * @param failIfNotFound If the element is not found, determines whether 276 * to return null or throw an error 277 * @param category Type of returned element, a {@link Category} value; 278 * {@link Category#Unknown} if it doesn't matter. 279 * 280 * @pre parent != null 281 * @post !(failIfNotFound && return == null) 282 */ 283 OlapElement lookupCompound( 284 OlapElement parent, 285 List<Id.Segment> names, 286 boolean failIfNotFound, 287 int category); 288 289 /** 290 * Should only be called by implementations of 291 * {@link #lookupCompound(OlapElement, java.util.List, boolean, int, MatchType)}. 292 * 293 * @param parent Parent element to search in 294 * @param names Exploded compound name, such as {"Products", 295 * "Product Department", "Produce"} 296 * @param failIfNotFound If the element is not found, determines whether 297 * to return null or throw an error 298 * @param category Type of returned element, a {@link Category} value; 299 * {@link Category#Unknown} if it doesn't matter. 300 * @param matchType indicates the match mode; if not specified, EXACT 301 * @return Found element 302 303 OlapElement lookupCompoundInternal( 304 OlapElement parent, 305 List<Id.Segment> names, 306 boolean failIfNotFound, 307 int category, 308 MatchType matchType); 309 */ 310 311 /** 312 * Looks up a calculated member by name. If the name is not found in the 313 * current scope, returns null. 314 */ 315 Member getCalculatedMember(List<Id.Segment> nameParts); 316 317 /** 318 * Looks up a set by name. If the name is not found in the current scope, 319 * returns null. 320 */ 321 NamedSet getNamedSet(List<Id.Segment> nameParts); 322 323 /** 324 * Appends to <code>list</code> all members between <code>startMember</code> 325 * and <code>endMember</code> (inclusive) which belong to 326 * <code>level</code>. 327 */ 328 void getMemberRange( 329 Level level, Member startMember, Member endMember, List<Member> list); 330 331 /** 332 * Returns a member <code>n</code> further along in the same level from 333 * <code>member</code>. 334 * 335 * @pre member != null 336 */ 337 Member getLeadMember(Member member, int n); 338 339 /** 340 * Compares a pair of {@link Member}s according to their order in a prefix 341 * traversal. (that is, it 342 * is an ancestor or a earlier), is a sibling, or comes later in a prefix 343 * traversal. 344 * @return A negative integer if <code>m1</code> is an ancestor, an earlier 345 * sibling of an ancestor, or a descendent of an earlier sibling, of 346 * <code>m2</code>; 347 * zero if <code>m1</code> is a sibling of <code>m2</code>; 348 * a positive integer if <code>m1</code> comes later in the prefix 349 * traversal then <code>m2</code>. 350 */ 351 int compareMembersHierarchically(Member m1, Member m2); 352 353 /** 354 * Looks up the child of <code>parent</code> called <code>name</code>, or 355 * an approximation according to <code>matchType</code>, returning 356 * null if no element is found. 357 * 358 * @param parent Parent element to search in 359 * @param name Compound in compound name, such as "[Product]" or "&[1]" 360 * @param matchType Match type 361 * 362 * @return Element with given name, or null 363 */ 364 OlapElement getElementChild( 365 OlapElement parent, 366 Id.Segment name, 367 MatchType matchType); 368 369 /** 370 * Looks up the child of <code>parent</code> <code>name</code>, returning 371 * null if no element is found. 372 * 373 * <p>Always equivalent to 374 * <code>getElementChild(parent, name, MatchType.EXACT)</code>. 375 * 376 * @param parent Parent element to search in 377 * @param name Compound in compound name, such as "[Product]" or "&[1]" 378 * 379 * @return Element with given name, or null 380 */ 381 OlapElement getElementChild( 382 OlapElement parent, 383 Id.Segment name); 384 385 /** 386 * Returns the members of a level, optionally including calculated members. 387 */ 388 List<Member> getLevelMembers( 389 Level level, 390 boolean includeCalculated); 391 392 /** 393 * Returns the members of a level, optionally filtering out members which 394 * are empty. 395 * 396 * @param level Level 397 * @param context Context for filtering 398 * @return Members of this level 399 */ 400 List<Member> getLevelMembers( 401 Level level, 402 Evaluator context); 403 404 /** 405 * Returns the accessible levels of a hierarchy. 406 * 407 * @param hierarchy Hierarchy 408 * 409 * @pre hierarchy != null 410 * @post return.length >= 1 411 */ 412 List<Level> getHierarchyLevels(Hierarchy hierarchy); 413 414 /** 415 * Returns the default member of a hierarchy. If the default member is in 416 * an inaccessible level, returns the nearest ascendant/descendant member. 417 * 418 * @param hierarchy Hierarchy 419 * 420 * @return Default member of hierarchy 421 */ 422 Member getHierarchyDefaultMember(Hierarchy hierarchy); 423 424 /** 425 * Returns whether a member has visible children. 426 */ 427 boolean isDrillable(Member member); 428 429 /** 430 * Returns whether a member is visible. 431 */ 432 boolean isVisible(Member member); 433 434 /** 435 * Returns the list of accessible cubes. 436 */ 437 Cube[] getCubes(); 438 439 /** 440 * Returns a list of calculated members in a given hierarchy. 441 */ 442 List<Member> getCalculatedMembers(Hierarchy hierarchy); 443 444 /** 445 * Returns a list of calculated members in a given level. 446 */ 447 List<Member> getCalculatedMembers(Level level); 448 449 /** 450 * Returns the list of calculated members. 451 */ 452 List<Member> getCalculatedMembers(); 453 454 /** 455 * Finds a child of a member with a given name. 456 */ 457 Member lookupMemberChildByName( 458 Member parent, 459 Id.Segment childName, 460 MatchType matchType); 461 462 /** 463 * Returns an object which can evaluate an expression in native SQL, or 464 * null if this is not possible. 465 * 466 * @param fun Function 467 * @param args Arguments to the function 468 * @param evaluator Evaluator, provides context 469 * @param calc 470 */ 471 NativeEvaluator getNativeSetEvaluator( 472 FunDef fun, 473 Exp[] args, 474 Evaluator evaluator, 475 Calc calc); 476 477 /** 478 * Returns the definition of a parameter with a given name, or null if not 479 * found. 480 */ 481 Parameter getParameter(String name); 482 483 /** 484 * Returns the data source. 485 * 486 * @return data source 487 */ 488 DataSource getDataSource(); 489 490 /** 491 * Returns a similar schema reader that has no access control. 492 * 493 * @return Schema reader that has a similar perspective (e.g. cube) but 494 * no access control 495 */ 496 SchemaReader withoutAccessControl(); 497 498 /** 499 * Returns the default cube in which to look for dimensions etc. 500 * 501 * @return Default cube 502 */ 503 Cube getCube(); 504 505 /** 506 * Returns a schema reader that automatically assigns a locus to each 507 * operation. 508 * 509 * <p>It is less efficient; use this only if the operation is occurring 510 * outside the context of a statement. If you get the internal error 511 * "no locus", that's a sign you should use this method.</p> 512 * 513 * @return Schema reader that assigns a locus to each operation 514 */ 515 SchemaReader withLocus(); 516 517 /** 518 * Returns a list of namespaces to search when resolving elements by name. 519 * 520 * <p>For example, a schema reader from the perspective of a cube will 521 * return cube and schema namespaces.</p> 522 * 523 * @return List of namespaces 524 */ 525 List<NameResolver.Namespace> getNamespaces(); 526 527 /** 528 * Similar to {@link #getMemberChildren(Member, Evaluator)} 529 * but returns a map of the grand-children and their access details 530 * and costs more to invoke because of the access controls. 531 * 532 * Called by {@link RolapHierarchy} when determining the lowest access 533 * level of a Role within a hierarchy. 534 */ 535 Map<? extends Member, Access> 536 getMemberChildrenWithDetails(Member member, Evaluator evaluator); 537} 538 539// End SchemaReader.java