KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > rolap > RolapLevel


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/rolap/RolapLevel.java#50 $
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 import mondrian.olap.*;
16 import mondrian.resource.MondrianResource;
17 import mondrian.rolap.agg.*;
18 import mondrian.rolap.sql.SqlQuery;
19
20 import org.apache.log4j.Logger;
21 import java.lang.reflect.Constructor JavaDoc;
22 import java.util.*;
23
24 /**
25  * <code>RolapLevel</code> implements {@link Level} for a ROLAP database.
26  *
27  * @author jhyde
28  * @since 10 August, 2001
29  * @version $Id: //open/mondrian/src/main/mondrian/rolap/RolapLevel.java#50 $
30  */

31 public class RolapLevel extends LevelBase {
32
33     private static final Logger LOGGER = Logger.getLogger(RolapEvaluator.class);
34
35     public static RolapLevel lookupLevel(RolapLevel[] levels, String JavaDoc levelName) {
36         for (RolapLevel level : levels) {
37             if (level.getName().equals(levelName)) {
38                 return level;
39             }
40         }
41         return null;
42     }
43
44     static final int ALL = 2;
45     static final int UNIQUE = 4;
46
47     /** The column or expression which yields the level's key. */
48     private final MondrianDef.Expression keyExp;
49     /** The column or expression which yields the level's ordinal. */
50     private final MondrianDef.Expression ordinalExp;
51     /** The column or expression which yields the level members' caption. */
52     private final MondrianDef.Expression captionExp;
53     /** For SQL generator. Whether values of "column" are unique globally
54      * unique (as opposed to unique only within the context of the parent
55      * member). */

56     private final boolean unique;
57     private final SqlQuery.Datatype datatype;
58     private final int flags;
59     private final RolapProperty[] properties;
60     private final RolapProperty[] inheritedProperties;
61
62     /**
63      * Ths expression which gives the name of members of this level. If null,
64      * members are named using the key expression.
65      */

66     private final MondrianDef.Expression nameExp;
67     /** The expression which joins to the parent member in a parent-child
68      * hierarchy, or null if this is a regular hierarchy. */

69     private final MondrianDef.Expression parentExp;
70     /** Value which indicates a null parent in a parent-child hierarchy. */
71     private final String JavaDoc nullParentValue;
72
73     /** Condition under which members are hidden. */
74     private final HideMemberCondition hideMemberCondition;
75     private final MondrianDef.Closure xmlClosure;
76
77     private LevelReader levelReader;
78
79     /**
80      * Creates a level.
81      *
82      * @pre parentExp != null || nullParentValue == null
83      * @pre properties != null
84      * @pre levelType != null
85      * @pre hideMemberCondition != null
86      */

87     RolapLevel(
88             RolapHierarchy hierarchy,
89             int depth,
90             String JavaDoc name,
91             MondrianDef.Expression keyExp,
92             MondrianDef.Expression nameExp,
93             MondrianDef.Expression captionExp,
94             MondrianDef.Expression ordinalExp,
95             MondrianDef.Expression parentExp,
96             String JavaDoc nullParentValue,
97             MondrianDef.Closure xmlClosure,
98             RolapProperty[] properties,
99             int flags,
100             SqlQuery.Datatype datatype,
101             HideMemberCondition
102             hideMemberCondition,
103             LevelType levelType, String JavaDoc approxRowCount)
104     {
105         super(hierarchy, name, depth, levelType);
106
107         Util.assertPrecondition(properties != null, "properties != null");
108         Util.assertPrecondition(hideMemberCondition != null,
109                 "hideMemberCondition != null");
110         Util.assertPrecondition(levelType != null, "levelType != null");
111
112         if (keyExp instanceof MondrianDef.Column) {
113             checkColumn((MondrianDef.Column) keyExp);
114         }
115         this.approxRowCount = loadApproxRowCount(approxRowCount);
116         this.flags = flags;
117         final boolean isAll = (flags & ALL) == ALL;
118         this.unique = (flags & UNIQUE) == UNIQUE;
119         this.datatype = datatype;
120         this.keyExp = keyExp;
121         if (nameExp != null) {
122             if (nameExp instanceof MondrianDef.Column) {
123                 checkColumn((MondrianDef.Column) nameExp);
124             }
125         }
126         this.nameExp = nameExp;
127         if (captionExp != null) {
128             if (captionExp instanceof MondrianDef.Column) {
129                 checkColumn((MondrianDef.Column) captionExp);
130             }
131         }
132         this.captionExp = captionExp;
133         if (ordinalExp != null) {
134             if (ordinalExp instanceof MondrianDef.Column) {
135                 checkColumn((MondrianDef.Column) ordinalExp);
136             }
137             this.ordinalExp = ordinalExp;
138         } else {
139             this.ordinalExp = this.keyExp;
140         }
141         this.parentExp = parentExp;
142         if (parentExp != null) {
143             Util.assertTrue(!isAll, "'All' level '" + this + "' must not be parent-child");
144             Util.assertTrue(unique, "Parent-child level '" + this + "' must have uniqueMembers=\"true\"");
145         }
146         this.nullParentValue = nullParentValue;
147         Util.assertPrecondition(parentExp != null || nullParentValue == null,
148                 "parentExp != null || nullParentValue == null");
149         this.xmlClosure = xmlClosure;
150         for (RolapProperty property : properties) {
151             if (property.getExp() instanceof MondrianDef.Column) {
152                 checkColumn((MondrianDef.Column) property.getExp());
153             }
154         }
155         this.properties = properties;
156         List<Property> list = new ArrayList<Property>();
157         for (Level level = this; level != null;
158                 level = level.getParentLevel()) {
159             final Property[] levelProperties = level.getProperties();
160             for (final Property levelProperty : levelProperties) {
161                 Property existingProperty = lookupProperty(
162                     list, levelProperty.getName());
163                 if (existingProperty == null) {
164                     list.add(levelProperty);
165                 } else if (existingProperty.getType() !=
166                     levelProperty.getType()) {
167                     throw Util.newError(
168                         "Property " + this.getName() + "." +
169                             levelProperty.getName() + " overrides a " +
170                             "property with the same name but different type");
171                 }
172             }
173         }
174         this.inheritedProperties = list.toArray(new RolapProperty[list.size()]);
175
176         Dimension dim = hierarchy.getDimension();
177         if (dim.getDimensionType() == DimensionType.TimeDimension) {
178             if (!levelType.isTime() && !isAll) {
179                 throw MondrianResource.instance()
180                         .NonTimeLevelInTimeHierarchy.ex(getUniqueName());
181            }
182         } else if (dim.getDimensionType() == null) {
183             // there was no dimension type assigned to the dimension
184
// - check later
185
} else {
186             if (levelType.isTime()) {
187                 throw MondrianResource.instance()
188                         .TimeLevelInNonTimeHierarchy.ex(getUniqueName());
189             }
190         }
191         this.hideMemberCondition = hideMemberCondition;
192     }
193
194
195     public RolapHierarchy getHierarchy() {
196         return (RolapHierarchy) hierarchy;
197     }
198
199     private int loadApproxRowCount(String JavaDoc approxRowCount) {
200         boolean notNullAndNumeric = approxRowCount != null && approxRowCount.matches("^\\d+$");
201         if(notNullAndNumeric){
202
203               return Integer.parseInt(approxRowCount);
204         } else {
205             // if approxRowCount is not set, return MIN_VALUE to indicate
206
return Integer.MIN_VALUE;
207         }
208     }
209
210     protected Logger getLogger() {
211         return LOGGER;
212     }
213
214     String JavaDoc getTableName() {
215         String JavaDoc tableName = null;
216
217         MondrianDef.Expression expr = getKeyExp();
218         if (expr instanceof MondrianDef.Column) {
219             MondrianDef.Column mc = (MondrianDef.Column) expr;
220             tableName = mc.getTableAlias();
221         }
222         return tableName;
223     }
224
225     LevelReader getLevelReader() {
226         return levelReader;
227     }
228
229     public MondrianDef.Expression getKeyExp() {
230         return keyExp;
231     }
232
233     MondrianDef.Expression getOrdinalExp() {
234         return ordinalExp;
235     }
236
237     public MondrianDef.Expression getCaptionExp() {
238         return captionExp;
239     }
240
241     public boolean hasCaptionColumn(){
242         return captionExp != null;
243     }
244
245     int getFlags() {
246         return flags;
247     }
248
249     HideMemberCondition getHideMemberCondition() {
250         return hideMemberCondition;
251     }
252
253     public boolean isUnique() {
254         return unique;
255     }
256
257     SqlQuery.Datatype getDatatype() {
258         return datatype;
259     }
260
261     String JavaDoc getNullParentValue() {
262         return nullParentValue;
263     }
264
265     /**
266      * Returns whether this level is parent-child.
267      */

268     public boolean isParentChild() {
269         return parentExp != null;
270     }
271
272     MondrianDef.Expression getParentExp() {
273         return parentExp;
274     }
275
276     // RME: this has to be public for two of the DrillThroughTest test.
277
public
278     MondrianDef.Expression getNameExp() {
279         return nameExp;
280     }
281
282     private Property lookupProperty(List<Property> list, String JavaDoc propertyName) {
283         for (Property property : list) {
284             if (property.getName().equals(propertyName)) {
285                 return property;
286             }
287         }
288         return null;
289     }
290
291     RolapLevel(RolapHierarchy hierarchy, int depth, MondrianDef.Level xmlLevel) {
292         this(
293             hierarchy, depth, xmlLevel.name, xmlLevel.getKeyExp(),
294             xmlLevel.getNameExp(), xmlLevel.getCaptionExp(), xmlLevel.getOrdinalExp(),
295             xmlLevel.getParentExp(), xmlLevel.nullParentValue,
296             xmlLevel.closure, createProperties(xmlLevel),
297             (xmlLevel.uniqueMembers ? UNIQUE : 0),
298             xmlLevel.getDatatype(),
299             HideMemberCondition.valueOf(xmlLevel.hideMemberIf),
300             LevelType.valueOf(xmlLevel.levelType), xmlLevel.approxRowCount);
301
302         if (!Util.isEmpty(xmlLevel.caption)) {
303             setCaption(xmlLevel.caption);
304         }
305         if (!Util.isEmpty(xmlLevel.formatter)) {
306             // there is a special member formatter class
307
try {
308                 Class JavaDoc<MemberFormatter> clazz =
309                     (Class JavaDoc<MemberFormatter>) Class.forName(xmlLevel.formatter);
310                 Constructor JavaDoc<MemberFormatter> ctor = clazz.getConstructor();
311                 memberFormatter = ctor.newInstance();
312             } catch (Exception JavaDoc e) {
313                 throw MondrianResource.instance().MemberFormatterLoadFailed.ex(
314                     xmlLevel.formatter, getUniqueName(), e);
315             }
316         }
317     }
318
319     // helper for constructor
320
private static RolapProperty[] createProperties(
321             MondrianDef.Level xmlLevel) {
322         List<RolapProperty> list = new ArrayList<RolapProperty>();
323         final MondrianDef.Expression nameExp = xmlLevel.getNameExp();
324
325         if (nameExp != null) {
326             list.add(new RolapProperty(
327                     Property.NAME.name, Property.Datatype.TYPE_STRING,
328                     nameExp, null, null));
329         }
330         for (int i = 0; i < xmlLevel.properties.length; i++) {
331             MondrianDef.Property property = xmlLevel.properties[i];
332             list.add(new RolapProperty(
333                     property.name,
334                     convertPropertyTypeNameToCode(property.type),
335                     xmlLevel.getPropertyExp(i),
336                     property.formatter, property.caption));
337         }
338         return list.toArray(new RolapProperty[list.size()]);
339     }
340
341     private static Property.Datatype convertPropertyTypeNameToCode(String JavaDoc type) {
342         if (type.equals("String")) {
343             return Property.Datatype.TYPE_STRING;
344         } else if (type.equals("Numeric")) {
345             return Property.Datatype.TYPE_NUMERIC;
346         } else if (type.equals("Boolean")) {
347             return Property.Datatype.TYPE_BOOLEAN;
348         } else {
349             throw Util.newError("Unknown property type '" + type + "'");
350         }
351     }
352
353     private void checkColumn(MondrianDef.Column nameColumn) {
354         final RolapHierarchy rolapHierarchy = (RolapHierarchy) hierarchy;
355         if (nameColumn.table == null) {
356             final MondrianDef.Relation table = rolapHierarchy.getUniqueTable();
357             if (table == null) {
358                 throw Util.newError(
359                         "must specify a table for level " +
360                         getUniqueName() +
361                         " because hierarchy has more than one table");
362             }
363             nameColumn.table = table.getAlias();
364         } else {
365             Util.assertTrue(rolapHierarchy.tableExists(nameColumn.table));
366         }
367     }
368
369     void init(RolapCube cube, MondrianDef.CubeDimension xmlDimension) {
370         if (isAll()) {
371             this.levelReader = new AllLevelReaderImpl();
372         } else if (levelType == LevelType.Null) {
373             this.levelReader = new NullLevelReader();
374         } else if (xmlClosure != null) {
375             final RolapDimension dimension = ((RolapHierarchy) hierarchy)
376                 .createClosedPeerDimension(this, xmlClosure, cube, xmlDimension);
377
378             dimension.init(cube, xmlDimension);
379             cube.registerDimension(dimension);
380             RolapLevel closedPeer =
381                     (RolapLevel) dimension.getHierarchies()[0].getLevels()[1];
382             this.levelReader = new ParentChildLevelReaderImpl(closedPeer);
383         } else {
384             this.levelReader = new RegularLevelReader();
385         }
386     }
387
388     public boolean isAll() {
389         return hierarchy.hasAll() && (depth == 0);
390     }
391
392     public boolean areMembersUnique() {
393         return (depth == 0) || (depth == 1) && hierarchy.hasAll();
394     }
395
396     public String JavaDoc getTableAlias() {
397         return keyExp.getTableAlias();
398     }
399
400     public RolapProperty[] getProperties() {
401         return properties;
402     }
403
404     public Property[] getInheritedProperties() {
405         return inheritedProperties;
406     }
407
408     public int getApproxRowCount() {
409         return approxRowCount;
410     }
411
412     /**
413      * Conditions under which a level's members may be hidden (thereby creating
414      * a <dfn>ragged hierarchy</dfn>).
415      */

416     public enum HideMemberCondition {
417         /** A member always appears. */
418         Never,
419
420         /** A member doesn't appear if its name is null or empty. */
421         IfBlankName,
422
423         /** A member appears unless its name matches its parent's. */
424         IfParentsName
425     }
426
427     public OlapElement lookupChild(SchemaReader schemaReader, String JavaDoc name) {
428         return lookupChild(schemaReader, name, MatchType.EXACT);
429     }
430
431     public OlapElement lookupChild(
432         SchemaReader schemaReader, String JavaDoc name, MatchType matchType)
433     {
434         Member[] levelMembers = schemaReader.getLevelMembers(this, true);
435         if (levelMembers.length > 0) {
436             Member parent = levelMembers[0].getParentMember();
437             return
438                 RolapUtil.findBestMemberMatch(
439                     Arrays.asList(levelMembers),
440                     (RolapMember) parent,
441                     this,
442                     name,
443                     matchType,
444                     false);
445         }
446         return null;
447     }
448
449     /**
450      * Returns true when the level is part of a parent/child hierarchy and has
451      * an equivalent closed level.
452      */

453     boolean hasClosedPeer() {
454         return levelReader instanceof ParentChildLevelReaderImpl;
455     }
456
457
458     interface LevelReader {
459         /**
460          * Adds constraints to a cell request for a member of this level.
461          *
462          * @param member Member to be constrained
463          * @param levelToColumnMap
464           *@param request Request to be constrained @return true if request is
465          * unsatisfiable (e.g. if the member is the null member)
466          */

467         boolean constrainRequest(
468             RolapMember member,
469             Map<RolapLevel, RolapStar.Column> levelToColumnMap,
470             CellRequest request);
471
472         /**
473          * Adds constraints to a cache region for a member of this level.
474          *
475          * @param predicate Predicate
476          * @param levelToColumnMap
477          * @param cacheRegion Cache region to be constrained
478          */

479         void constrainRegion(
480             StarColumnPredicate predicate,
481             Map<RolapLevel, RolapStar.Column> levelToColumnMap,
482             RolapCacheRegion cacheRegion);
483     }
484
485     /**
486      * Level reader for a regular level.
487      */

488     class RegularLevelReader implements LevelReader {
489         public boolean constrainRequest(
490                 RolapMember member,
491                 Map<RolapLevel, RolapStar.Column> levelToColumnMap,
492                 CellRequest request) {
493             assert member.getLevel() == RolapLevel.this;
494             if (member.getKey() == null) {
495                 if (member == member.getHierarchy().getNullMember()) {
496                     // cannot form a request if one of the members is null
497
return true;
498                 } else {
499                     throw Util.newInternal("why is key null?");
500                 }
501             }
502
503             RolapStar.Column column = levelToColumnMap.get(RolapLevel.this);
504             if (column == null) {
505                 // This hierarchy is not one which qualifies the starMeasure
506
// (this happens in virtual cubes). The starMeasure only has
507
// a value for the 'all' member of the hierarchy (or for the
508
// default member if the hierarchy has no 'all' member)
509
return member != hierarchy.getDefaultMember() ||
510                     hierarchy.hasAll();
511             }
512
513             final StarColumnPredicate predicate;
514             if (member.isCalculated()) {
515                 predicate = null;
516             } else {
517                 predicate = false ? new MemberColumnPredicate(column, member) :
518                     new ValueColumnPredicate(column, member.getSqlKey());
519             }
520
521             // use the member as constraint, this will give us some
522
// optimization potential
523
request.addConstrainedColumn(column, predicate);
524             if (request.extendedContext &&
525                     getNameExp() != null) {
526                 RolapStar.Column nameColumn = column.getNameColumn();
527
528                 Util.assertTrue(nameColumn != null);
529                 request.addConstrainedColumn(nameColumn, null);
530             }
531
532             if (member.isCalculated()) {
533                 return false;
534             }
535
536             // If member is unique without reference to its parent,
537
// no further constraint is required.
538
if (unique) {
539                 return false;
540             }
541
542             // Constrain the parent member, if any.
543
RolapMember parent = member.getParentMember();
544             while (true) {
545                 if (parent == null) {
546                     return false;
547                 }
548                 RolapLevel level = parent.getLevel();
549                 final LevelReader levelReader = level.levelReader;
550                 if (levelReader == this) {
551                     // We are looking at a parent in a parent-child hierarchy,
552
// for example, we have moved from Fred to Fred's boss,
553
// Wilma. We don't want to include Wilma's key in the
554
// request.
555
parent = parent.getParentMember();
556                     continue;
557                 }
558                 return levelReader.constrainRequest(
559                         parent, levelToColumnMap, request);
560             }
561         }
562
563         public void constrainRegion(
564             StarColumnPredicate predicate,
565             Map<RolapLevel, RolapStar.Column> levelToColumnMap,
566             RolapCacheRegion cacheRegion)
567         {
568             RolapStar.Column column = levelToColumnMap.get(RolapLevel.this);
569             if (column == null) {
570                 // This hierarchy is not one which qualifies the starMeasure
571
// (this happens in virtual cubes). The starMeasure only has
572
// a value for the 'all' member of the hierarchy (or for the
573
// default member if the hierarchy has no 'all' member)
574
return;
575             }
576
577             if (predicate instanceof MemberColumnPredicate) {
578                 MemberColumnPredicate memberColumnPredicate =
579                     (MemberColumnPredicate) predicate;
580                 RolapMember member = memberColumnPredicate.getMember();
581                 assert member.getLevel() == RolapLevel.this;
582                 assert !member.isCalculated();
583                 assert memberColumnPredicate.getMember().getKey() != null;
584                 assert !member.isNull();
585
586                 MemberTuplePredicate predicate2 =
587                     new MemberTuplePredicate(
588                         levelToColumnMap,
589                         member);
590
591                 // use the member as constraint, this will give us some
592
// optimization potential
593
cacheRegion.addPredicate(column, predicate);
594                 return;
595             } else if (predicate instanceof RangeColumnPredicate) {
596                 RangeColumnPredicate rangeColumnPredicate =
597                     (RangeColumnPredicate) predicate;
598                 final ValueColumnPredicate lowerBound =
599                     rangeColumnPredicate.getLowerBound();
600                 RolapMember lowerMember;
601                 if (lowerBound == null) {
602                     lowerMember = null;
603                 } else if (lowerBound instanceof MemberColumnPredicate) {
604                     MemberColumnPredicate memberColumnPredicate =
605                         (MemberColumnPredicate) lowerBound;
606                     lowerMember = memberColumnPredicate.getMember();
607                 } else {
608                     throw new UnsupportedOperationException JavaDoc();
609                 }
610                 final ValueColumnPredicate upperBound =
611                     rangeColumnPredicate.getUpperBound();
612                 RolapMember upperMember;
613                 if (upperBound == null) {
614                     upperMember = null;
615                 } else if (upperBound instanceof MemberColumnPredicate) {
616                     MemberColumnPredicate memberColumnPredicate =
617                         (MemberColumnPredicate) upperBound;
618                     upperMember = memberColumnPredicate.getMember();
619                 } else {
620                     throw new UnsupportedOperationException JavaDoc();
621                 }
622                 MemberTuplePredicate predicate2 =
623                     new MemberTuplePredicate(
624                         levelToColumnMap,
625                         lowerMember,
626                         !rangeColumnPredicate.getLowerInclusive(),
627                         upperMember,
628                         !rangeColumnPredicate.getUpperInclusive());
629                 // use the member as constraint, this will give us some
630
// optimization potential
631
cacheRegion.addPredicate(predicate2);
632                 return;
633             }
634
635             // Unknown type of constraint.
636
throw new UnsupportedOperationException JavaDoc();
637         }
638     }
639
640     /**
641      * Level reader for a parent-child level which has a closed peer level.
642      */

643     class ParentChildLevelReaderImpl extends RegularLevelReader {
644         /**
645          * For a parent-child hierarchy with a closure provided by the schema,
646          * the equivalent level in the closed hierarchy; otherwise null.
647          */

648         private final RolapLevel closedPeer;
649
650         ParentChildLevelReaderImpl(RolapLevel closedPeer) {
651             this.closedPeer = closedPeer;
652         }
653
654         public boolean constrainRequest(
655                 RolapMember member,
656                 Map<RolapLevel, RolapStar.Column> levelToColumnMap,
657                 CellRequest request) {
658
659             // Replace a parent/child level by its closed equivalent, when
660
// available; this is always valid, and improves performance by
661
// enabling the database to compute aggregates.
662
if (member.getDataMember() == null) {
663                 // Member has no data member because it IS the data
664
// member of a parent-child hierarchy member. Leave
665
// it be. We don't want to aggregate.
666
return super.constrainRequest(
667                         member, levelToColumnMap, request);
668             } else if (request.drillThrough) {
669                 member = (RolapMember) member.getDataMember();
670                 return super.constrainRequest(
671                         member, levelToColumnMap, request);
672             } else {
673                 RolapLevel level = closedPeer;
674                 final RolapMember allMember = (RolapMember)
675                         level.getHierarchy().getDefaultMember();
676                 assert allMember.isAll();
677                 member = new RolapMember(allMember, level,
678                         member.getKey());
679                 return level.getLevelReader().constrainRequest(
680                         member, levelToColumnMap, request);
681             }
682         }
683
684         public void constrainRegion(
685             StarColumnPredicate predicate,
686             Map<RolapLevel, RolapStar.Column> levelToColumnMap,
687             RolapCacheRegion cacheRegion)
688         {
689             throw new UnsupportedOperationException JavaDoc();
690         }
691     }
692
693     /**
694      * Level reader for the level which contains the 'all' member.
695      */

696     class AllLevelReaderImpl implements LevelReader {
697         public boolean constrainRequest(
698                 RolapMember member,
699                 Map<RolapLevel, RolapStar.Column> levelToColumnMap,
700                 CellRequest request) {
701             // We don't need to apply any constraints.
702
return false;
703         }
704
705         public void constrainRegion(
706             StarColumnPredicate predicate,
707             Map<RolapLevel, RolapStar.Column> levelToColumnMap,
708             RolapCacheRegion cacheRegion)
709         {
710             // We don't need to apply any constraints.
711
}
712     }
713
714     /**
715      * Level reader for the level which contains the null member.
716      */

717     class NullLevelReader implements LevelReader {
718         public boolean constrainRequest(
719                 RolapMember member,
720                 Map<RolapLevel, RolapStar.Column> levelToColumnMap,
721                 CellRequest request) {
722             return true;
723         }
724
725         public void constrainRegion(
726             StarColumnPredicate predicate,
727             Map<RolapLevel, RolapStar.Column> levelToColumnMap,
728             RolapCacheRegion cacheRegion)
729         {
730         }
731     }
732 }
733
734 // End RolapLevel.java
735
Popular Tags