001 /* 002 // $Id: //open/mondrian/src/main/mondrian/rolap/NoCacheMemberReader.java#2 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2001-2002 Kana Software, Inc. 007 // Copyright (C) 2004-2005 TONBELLER AG 008 // Copyright (C) 2007-2008 StrateBI 009 // All Rights Reserved. 010 // You must accept the terms of that agreement to use this software. 011 // 012 */ 013 014 package mondrian.rolap; 015 import mondrian.olap.Util; 016 import mondrian.olap.Id; 017 import mondrian.olap.Member; 018 import mondrian.rolap.TupleReader.MemberBuilder; 019 import mondrian.rolap.sql.MemberChildrenConstraint; 020 import mondrian.rolap.sql.TupleConstraint; 021 022 import java.util.*; 023 import org.apache.log4j.Logger; 024 025 /** 026 * <code>NoCacheMemberReader</code> implements {@link MemberReader} but 027 * without doing any kind of caching and avoiding to read all members. 028 * 029 * @author jlopez, lcanals 030 * @since 06 October, 2007 031 * @version $Id: //open/mondrian/src/main/mondrian/rolap/NoCacheMemberReader.java#2 $ 032 */ 033 public class NoCacheMemberReader implements MemberReader, MemberCache { 034 private static final Logger LOGGER = 035 Logger.getLogger(NoCacheMemberReader.class); 036 037 private final SqlConstraintFactory sqlConstraintFactory = 038 SqlConstraintFactory.instance(); 039 040 private final MemberReader source; 041 042 043 NoCacheMemberReader(MemberReader source) { 044 this.source = source; 045 if (!source.setCache(this)) { 046 throw Util.newInternal( 047 "MemberSource (" + source + ", " + source.getClass() + 048 ") does not support cache-writeback"); 049 } 050 } 051 052 // implementes MemberCache 053 public boolean isMutable() { 054 return false; 055 } 056 057 // implementes MemberCache 058 public RolapMember removeMember(Object key) { 059 return null; 060 } 061 062 // implementes MemberCache 063 public RolapMember removeMemberAndDescendants(Object key) { 064 return null; 065 } 066 067 // implement MemberReader 068 public RolapHierarchy getHierarchy() { 069 return source.getHierarchy(); 070 } 071 072 // implement MemberCache 073 public boolean setCache(MemberCache cache) { 074 return false; 075 } 076 077 // implement MemberCache 078 public Object makeKey(final RolapMember parent, final Object key) { 079 LOGGER.debug("Entering makeKey"); 080 return new MemberKey(parent, key); 081 } 082 083 public synchronized RolapMember getMember(final Object key) { 084 return getMember(key, true); 085 } 086 087 public RolapMember getMember(final Object key, 088 final boolean mustCheckCacheStatus) { 089 LOGGER.debug("Returning null member: no cache"); 090 return null; 091 } 092 093 094 // implement MemberCache 095 public Object putMember(final Object key, final RolapMember value) { 096 LOGGER.debug("putMember void for no caching"); 097 return value; 098 } 099 100 // implement MemberReader 101 public List<RolapMember> getMembers() { 102 System.out.println("NoCache getMembers"); 103 List<RolapMember> v = new ArrayList<RolapMember>(); 104 RolapLevel[] levels = (RolapLevel[]) getHierarchy().getLevels(); 105 // todo: optimize by walking to children for members we know about 106 for (RolapLevel level : levels) { 107 List<RolapMember> membersInLevel = 108 getMembersInLevel(level, 0, Integer.MAX_VALUE); 109 v.addAll(membersInLevel); 110 } 111 return v; 112 } 113 114 public List<RolapMember> getRootMembers() { 115 LOGGER.debug("Getting root members"); 116 return source.getRootMembers(); 117 } 118 119 120 public List<RolapMember> getMembersInLevel( 121 final RolapLevel level, final int startOrdinal, 122 final int endOrdinal) { 123 TupleConstraint constraint = 124 sqlConstraintFactory.getLevelMembersConstraint(null); 125 return getMembersInLevel(level, startOrdinal, endOrdinal, constraint); 126 } 127 128 public List<RolapMember> getMembersInLevel( 129 final RolapLevel level, final int startOrdinal, 130 final int endOrdinal, final TupleConstraint constraint) { 131 LOGGER.debug("Entering getMembersInLevel"); 132 return source.getMembersInLevel( 133 level, startOrdinal, endOrdinal, constraint); 134 } 135 136 public void getMemberChildren( 137 final RolapMember parentMember, 138 final List<RolapMember> children) 139 { 140 MemberChildrenConstraint constraint = 141 sqlConstraintFactory.getMemberChildrenConstraint(null); 142 getMemberChildren(parentMember, children, constraint); 143 } 144 145 public void getMemberChildren( 146 final RolapMember parentMember, 147 final List<RolapMember> children, 148 final MemberChildrenConstraint constraint) 149 { 150 List<RolapMember> parentMembers = new ArrayList<RolapMember>(); 151 parentMembers.add(parentMember); 152 getMemberChildren(parentMembers, children, constraint); 153 } 154 155 public void getMemberChildren( 156 final List<RolapMember> parentMembers, 157 final List<RolapMember> children) 158 { 159 MemberChildrenConstraint constraint = 160 sqlConstraintFactory.getMemberChildrenConstraint(null); 161 getMemberChildren(parentMembers, children, constraint); 162 } 163 164 public void getMemberChildren( 165 final List<RolapMember> parentMembers, 166 final List<RolapMember> children, 167 final MemberChildrenConstraint constraint) 168 { 169 assert constraint != null; 170 LOGGER.debug("Entering getMemberChildren"); 171 source.getMemberChildren(parentMembers, children, constraint); 172 } 173 174 public RolapMember lookupMember( 175 final List<Id.Segment> uniqueNameParts, 176 final boolean failIfNotFound) 177 { 178 return RolapUtil.lookupMember(this, uniqueNameParts, failIfNotFound); 179 } 180 181 public List<RolapMember> getChildrenFromCache( 182 final RolapMember member, 183 final MemberChildrenConstraint constraint) 184 { 185 return null; 186 } 187 188 public List<RolapMember> getLevelMembersFromCache( 189 final RolapLevel level, 190 final TupleConstraint constraint) 191 { 192 return null; 193 } 194 195 public void putChildren( 196 final RolapMember member, 197 final MemberChildrenConstraint constraint, 198 final List<RolapMember> children) 199 { 200 } 201 202 public RolapMember getLeadMember(RolapMember member, int n) { 203 if (n == 0 || member.isNull()) { 204 return member; 205 } else { 206 SiblingIterator iter = new SiblingIterator(this, member); 207 if (n > 0) { 208 RolapMember sibling = null; 209 while (n-- > 0) { 210 if (!iter.hasNext()) { 211 return (RolapMember) member.getHierarchy() 212 .getNullMember(); 213 } 214 sibling = iter.nextMember(); 215 } 216 return sibling; 217 } else { 218 n = -n; 219 RolapMember sibling = null; 220 while (n-- > 0) { 221 if (!iter.hasPrevious()) { 222 return (RolapMember) member.getHierarchy() 223 .getNullMember(); 224 } 225 sibling = iter.previousMember(); 226 } 227 return sibling; 228 } 229 } 230 } 231 232 public void getMemberRange( 233 final RolapLevel level, 234 final RolapMember startMember, 235 final RolapMember endMember, 236 final List<RolapMember> list) 237 { 238 assert startMember != null : "pre"; 239 assert endMember != null : "pre"; 240 assert startMember.getLevel() == endMember.getLevel() 241 : "pre: startMember.getLevel() == endMember.getLevel()"; 242 243 if (compare(startMember, endMember, false) > 0) { 244 return; 245 } 246 list.add(startMember); 247 if (startMember == endMember) { 248 return; 249 } 250 SiblingIterator siblings = new SiblingIterator(this, startMember); 251 while (siblings.hasNext()) { 252 final RolapMember member = siblings.nextMember(); 253 list.add(member); 254 if (member == endMember) { 255 return; 256 } 257 } 258 throw Util.newInternal("sibling iterator did not hit end point, start=" 259 + startMember 260 + ", end=" 261 + endMember); 262 } 263 264 public int getMemberCount() { 265 return source.getMemberCount(); 266 } 267 268 public int compare(final RolapMember m1, final RolapMember m2, 269 final boolean siblingsAreEqual) { 270 if (m1 == m2) { 271 return 0; 272 } 273 if (m1.getParentMember() == m2.getParentMember()) { 274 // including case where both parents are null 275 if (siblingsAreEqual) { 276 return 0; 277 } else if (m1.getParentMember() == null) { 278 // at this point we know that both parent members are null. 279 int pos1 = -1, pos2 = -1; 280 List siblingList = getRootMembers(); 281 for (int i = 0, n = siblingList.size(); i < n; i++) { 282 RolapMember child = (RolapMember) siblingList.get(i); 283 if (child == m1) { 284 pos1 = i; 285 } 286 if (child == m2) { 287 pos2 = i; 288 } 289 } 290 if (pos1 == -1) { 291 throw Util.newInternal(m1 + " not found among siblings"); 292 } 293 if (pos2 == -1) { 294 throw Util.newInternal(m2 + " not found among siblings"); 295 } 296 Util.assertTrue(pos1 != pos2); 297 return pos1 < pos2 ? -1 : 1; 298 } else { 299 List<RolapMember> children = new ArrayList<RolapMember>(); 300 getMemberChildren(m1.getParentMember(), children); 301 int pos1 = -1, pos2 = -1; 302 for (int i = 0, n = children.size(); i < n; i++) { 303 RolapMember child = children.get(i); 304 if (child == m1) { 305 pos1 = i; 306 } 307 if (child == m2) { 308 pos2 = i; 309 } 310 } 311 if (pos1 == -1) { 312 throw Util.newInternal(m1 + " not found among siblings"); 313 } 314 if (pos2 == -1) { 315 throw Util.newInternal(m2 + " not found among siblings"); 316 } 317 Util.assertTrue(pos1 != pos2); 318 return pos1 < pos2 ? -1 : 1; 319 } 320 } 321 int levelDepth1 = m1.getLevel().getDepth(); 322 int levelDepth2 = m2.getLevel().getDepth(); 323 if (levelDepth1 < levelDepth2) { 324 final int c = compare(m1, m2.getParentMember(), false); 325 return (c == 0) ? -1 : c; 326 327 } else if (levelDepth1 > levelDepth2) { 328 final int c = compare(m1.getParentMember(), m2, false); 329 return (c == 0) ? 1 : c; 330 331 } else { 332 return compare(m1.getParentMember(), m2.getParentMember(), false); 333 } 334 } 335 336 /** 337 * <code>SiblingIterator</code> helps traverse a hierarchy of members, by 338 * remembering the position at each level. Each SiblingIterator has a 339 * parent, to which it defers when the last child of the current member is 340 * reached. 341 */ 342 class SiblingIterator { 343 private final MemberReader reader; 344 private final SiblingIterator parentIterator; 345 private List<? extends Member> siblings; 346 private int position; 347 348 SiblingIterator(MemberReader reader, RolapMember member) { 349 this.reader = reader; 350 RolapMember parent = member.getParentMember(); 351 List<RolapMember> siblingList; 352 if (parent == null) { 353 siblingList = reader.getRootMembers(); 354 this.parentIterator = null; 355 } else { 356 siblingList = new ArrayList<RolapMember>(); 357 reader.getMemberChildren(parent, siblingList); 358 this.parentIterator = new SiblingIterator(reader, parent); 359 } 360 this.siblings = siblingList; 361 this.position = -1; 362 for (int i = 0; i < this.siblings.size(); i++) { 363 if (siblings.get(i) == member) { 364 this.position = i; 365 break; 366 } 367 } 368 if (this.position == -1) { 369 throw Util.newInternal( 370 "member " + member + " not found among its siblings"); 371 } 372 } 373 boolean hasNext() { 374 return (this.position < this.siblings.size() - 1) || 375 (parentIterator != null) && 376 parentIterator.hasNext(); 377 } 378 Object next() { 379 return nextMember(); 380 } 381 RolapMember nextMember() { 382 if (++this.position >= this.siblings.size()) { 383 if (parentIterator == null) { 384 throw Util.newInternal("there is no next member"); 385 } 386 RolapMember parent = parentIterator.nextMember(); 387 List<RolapMember> siblingList = new ArrayList<RolapMember>(); 388 reader.getMemberChildren(parent, siblingList); 389 this.siblings = siblingList; 390 this.position = 0; 391 } 392 return (RolapMember) this.siblings.get(this.position); 393 } 394 boolean hasPrevious() { 395 return (this.position > 0) || 396 (parentIterator != null) && 397 parentIterator.hasPrevious(); 398 } 399 Object previous() { 400 return previousMember(); 401 } 402 RolapMember previousMember() { 403 if (--this.position < 0) { 404 if (parentIterator == null) { 405 throw Util.newInternal("there is no next member"); 406 } 407 RolapMember parent = parentIterator.previousMember(); 408 List<RolapMember> siblingList = new ArrayList<RolapMember>(); 409 reader.getMemberChildren(parent, siblingList); 410 this.siblings = siblingList; 411 this.position = this.siblings.size() - 1; 412 } 413 return (RolapMember) this.siblings.get(this.position); 414 } 415 } 416 417 public MemberBuilder getMemberBuilder() { 418 return source.getMemberBuilder(); 419 } 420 421 public RolapMember getDefaultMember() { 422 RolapMember defaultMember = 423 (RolapMember) getHierarchy().getDefaultMember(); 424 if (defaultMember != null) { 425 return defaultMember; 426 } 427 return (RolapMember) getRootMembers().get(0); 428 } 429 430 public int getLevelMemberCount(RolapLevel level) { 431 // No need to cache the result: the caller saves the result by calling 432 // RolapLevel.setApproxRowCount 433 return source.getLevelMemberCount(level); 434 } 435 436 public RolapMember desubstitute(RolapMember member) { 437 return (RolapMember) member; 438 } 439 440 public RolapMember substitute(RolapMember member) { 441 return (RolapMember) member; 442 } 443 444 public RolapMember getMemberParent(RolapMember member) { 445 // This method deals with ragged hierarchies but not access-controlled 446 // hierarchies - assume these have RestrictedMemberReader possibly 447 // wrapped in a SubstitutingMemberReader. 448 RolapMember parentMember = (RolapMember) member.getParentMember(); 449 // Skip over hidden parents. 450 while (parentMember != null && parentMember.isHidden()) { 451 parentMember = parentMember.getParentMember(); 452 } 453 return parentMember; 454 } 455 456 } 457 458 // End NoCacheMemberReader.java