1 14 15 package mondrian.rolap; 16 import mondrian.olap.Util; 17 import mondrian.rolap.TupleReader.MemberBuilder; 18 import mondrian.rolap.cache.SmartCache; 19 import mondrian.rolap.cache.SoftSmartCache; 20 import mondrian.rolap.sql.MemberChildrenConstraint; 21 import mondrian.rolap.sql.TupleConstraint; 22 23 import mondrian.spi.DataSourceChangeListener; 24 25 import java.util.*; 26 27 48 public class SmartMemberReader implements MemberReader, MemberCache { 49 private final SqlConstraintFactory sqlConstraintFactory = 50 SqlConstraintFactory.instance(); 51 52 53 private final MemberReader source; 54 55 56 final SmartMemberListCache<RolapMember, List<RolapMember>> mapMemberToChildren; 57 58 59 SmartCache<Object , RolapMember> mapKeyToMember; 60 61 62 final SmartMemberListCache<RolapLevel, List<RolapMember>> mapLevelToMembers; 63 64 DataSourceChangeListener changeListener; 65 66 private List<RolapMember> rootMembers; 67 68 SmartMemberReader(MemberReader source) { 69 this.source = source; 70 if (!source.setCache(this)) { 71 throw Util.newInternal( 72 "MemberSource (" + source + ", " + source.getClass() + 73 ") does not support cache-writeback"); 74 } 75 this.mapLevelToMembers = 76 new SmartMemberListCache<RolapLevel, List<RolapMember>>(); 77 this.mapKeyToMember = new SoftSmartCache<Object , RolapMember>(); 78 this.mapMemberToChildren = 79 new SmartMemberListCache<RolapMember, List<RolapMember>>(); 80 81 if (source.getHierarchy() != null) { 82 changeListener = source.getHierarchy().getRolapSchema().getDataSourceChangeListener(); 83 } 84 else { 85 changeListener = null; 86 } 87 } 88 89 public RolapHierarchy getHierarchy() { 91 return source.getHierarchy(); 92 } 93 94 public boolean setCache(MemberCache cache) { 96 return false; 99 } 100 101 private synchronized void checkCacheStatus() { 102 103 if (changeListener != null) { 104 if (changeListener.isHierarchyChanged(getHierarchy())) { 105 106 mapMemberToChildren.clear(); 107 mapKeyToMember.clear(); 108 mapLevelToMembers.clear(); 109 } 110 } 111 } 112 113 public Object makeKey(RolapMember parent, Object key) { 115 return new MemberKey(parent, key); 116 } 117 118 public synchronized RolapMember getMember(Object key) { 121 return getMember(key, true); 122 } 123 124 public synchronized RolapMember getMember(Object key, boolean mustCheckCacheStatus) { 127 128 if (mustCheckCacheStatus) { 129 checkCacheStatus(); 130 } 131 132 return mapKeyToMember.get(key); 133 } 134 135 136 public synchronized Object putMember(Object key, RolapMember value) { 139 return mapKeyToMember.put(key, value); 140 } 141 142 public RolapMember[] getMembers() { 144 List<RolapMember> v = new ArrayList<RolapMember>(); 145 RolapLevel[] levels = (RolapLevel[]) getHierarchy().getLevels(); 146 for (RolapLevel level : levels) { 148 List<RolapMember> membersInLevel = getMembersInLevel( 149 level, 150 0, 151 Integer.MAX_VALUE); 152 v.addAll(membersInLevel); 153 } 154 return v.toArray(new RolapMember[v.size()]); 155 } 156 157 public List<RolapMember> getRootMembers() { 158 if (rootMembers == null) { 159 rootMembers = source.getRootMembers(); 160 } 161 return rootMembers; 162 } 163 164 165 public synchronized List<RolapMember> getMembersInLevel( 167 RolapLevel level, 168 int startOrdinal, 169 int endOrdinal) { 170 TupleConstraint constraint = 171 sqlConstraintFactory.getLevelMembersConstraint(null); 172 return getMembersInLevel(level, startOrdinal, endOrdinal, constraint); 173 } 174 175 public synchronized List<RolapMember> getMembersInLevel( 176 RolapLevel level, 177 int startOrdinal, 178 int endOrdinal, 179 TupleConstraint constraint) 180 { 181 checkCacheStatus(); 182 183 List<RolapMember> members = mapLevelToMembers.get(level, constraint); 184 if (members != null) { 185 return members; 186 } 187 188 members = 189 source.getMembersInLevel( 190 level, startOrdinal, endOrdinal, constraint); 191 mapLevelToMembers.put(level, constraint, members); 192 return members; 193 } 194 195 public void getMemberChildren( 196 RolapMember parentMember, 197 List<RolapMember> children) 198 { 199 MemberChildrenConstraint constraint = 200 sqlConstraintFactory.getMemberChildrenConstraint(null); 201 getMemberChildren(parentMember, children, constraint); 202 } 203 204 public void getMemberChildren( 205 RolapMember parentMember, 206 List<RolapMember> children, 207 MemberChildrenConstraint constraint) 208 { 209 List<RolapMember> parentMembers = new ArrayList<RolapMember>(); 210 parentMembers.add(parentMember); 211 getMemberChildren(parentMembers, children, constraint); 212 } 213 214 public synchronized void getMemberChildren( 215 List<RolapMember> parentMembers, 216 List<RolapMember> children) { 217 MemberChildrenConstraint constraint = 218 sqlConstraintFactory.getMemberChildrenConstraint(null); 219 getMemberChildren(parentMembers, children, constraint); 220 } 221 222 public synchronized void getMemberChildren( 223 List<RolapMember> parentMembers, 224 List<RolapMember> children, 225 MemberChildrenConstraint constraint) { 226 227 checkCacheStatus(); 228 229 List<RolapMember> missed = new ArrayList<RolapMember>(); 230 for (RolapMember parentMember : parentMembers) { 231 List<RolapMember> list = 232 mapMemberToChildren.get(parentMember, constraint); 233 if (list == null) { 234 if (parentMember.isNull()) { 235 } else { 237 missed.add(parentMember); 238 } 239 } else { 240 children.addAll(list); 241 } 242 } 243 if (missed.size() > 0) { 244 readMemberChildren(missed, children, constraint); 245 } 246 } 247 248 public RolapMember lookupMember( 249 String [] uniqueNameParts, 250 boolean failIfNotFound) { 251 return RolapUtil.lookupMember(this, uniqueNameParts, failIfNotFound); 252 } 253 254 263 private void readMemberChildren( 264 List<RolapMember> members, 265 List<RolapMember> result, 266 MemberChildrenConstraint constraint) 267 { 268 if (false) { 269 Util.assertPrecondition(isSorted(members), "isSorted(members)"); 277 } 278 List<RolapMember> children = new ArrayList<RolapMember>(); 279 source.getMemberChildren(members, children, constraint); 280 Map<RolapMember, List<RolapMember>> tempMap = 283 new HashMap<RolapMember, List<RolapMember>>(); 284 for (RolapMember member1 : members) { 285 tempMap.put(member1, Collections.EMPTY_LIST); 286 } 287 for (int i = 0, childrenCount = children.size(); i < childrenCount; i++) { 288 RolapMember child = children.get(i); 295 assert child != null : "child"; 296 assert tempMap != null : "tempMap"; 297 final RolapMember parentMember = child.getParentMember(); 298 List<RolapMember> list = tempMap.get(parentMember); 299 if (list == null) { 300 continue; 305 } else if (list == Collections.EMPTY_LIST) { 306 list = new ArrayList<RolapMember>(); 307 tempMap.put(parentMember, list); 308 } 309 list.add(child); 310 result.add(child); 311 } 312 synchronized (this) { 313 for (RolapMember member : tempMap.keySet()) { 314 if (getChildrenFromCache(member, constraint) == null) { 315 List<RolapMember> list = tempMap.get(member); 316 putChildren(member, constraint, list); 317 } 318 } 319 } 320 } 321 322 326 public boolean isSorted(List<RolapMember> members) { 327 final int count = members.size(); 328 if (count == 0) { 329 return true; 330 } 331 RolapMember m1 = members.get(0); 332 if (m1 == null) { 333 return false; 335 } 336 for (int i = 1; i < count; i++) { 337 RolapMember m0 = m1; 338 m1 = members.get(i); 339 if (m1 == null || compare(m0, m1, false) >= 0) { 340 return false; 341 } 342 } 343 return true; 344 } 345 346 public synchronized List<RolapMember> getChildrenFromCache( 347 RolapMember member, 348 MemberChildrenConstraint constraint) { 349 if (constraint == null) { 350 constraint = sqlConstraintFactory.getMemberChildrenConstraint(null); 351 } 352 return mapMemberToChildren.get(member, constraint); 353 } 354 355 public synchronized List getLevelMembersFromCache( 356 RolapLevel level, 357 TupleConstraint constraint) { 358 if (constraint == null) { 359 constraint = sqlConstraintFactory.getLevelMembersConstraint(null); 360 } 361 return mapLevelToMembers.get(level, constraint); 362 } 363 364 public synchronized void putChildren( 365 RolapMember member, 366 MemberChildrenConstraint constraint, 367 List<RolapMember> children) 368 { 369 if (constraint == null) { 370 constraint = sqlConstraintFactory.getMemberChildrenConstraint(null); 371 } 372 mapMemberToChildren.put(member, constraint, children); 373 } 374 375 public synchronized RolapMember getLeadMember(RolapMember member, int n) { 377 if (n == 0 || member.isNull()) { 378 return member; 379 } else { 380 SiblingIterator iter = new SiblingIterator(this, member); 381 if (n > 0) { 382 RolapMember sibling = null; 383 while (n-- > 0) { 384 if (!iter.hasNext()) { 385 return (RolapMember) member.getHierarchy().getNullMember(); 386 } 387 sibling = iter.nextMember(); 388 } 389 return sibling; 390 } else { 391 n = -n; 392 RolapMember sibling = null; 393 while (n-- > 0) { 394 if (!iter.hasPrevious()) { 395 return (RolapMember) member.getHierarchy().getNullMember(); 396 } 397 sibling = iter.previousMember(); 398 } 399 return sibling; 400 } 401 } 402 } 403 404 public void getMemberRange(RolapLevel level, 405 RolapMember startMember, 406 RolapMember endMember, 407 List<RolapMember> list) { 408 Util.assertPrecondition(startMember != null, "startMember != null"); 409 Util.assertPrecondition(endMember != null, "endMember != null"); 410 Util.assertPrecondition(startMember.getLevel() == endMember.getLevel(), 411 "startMember.getLevel() == endMember.getLevel()"); 412 413 if (compare(startMember, endMember, false) > 0) { 414 return; 415 } 416 list.add(startMember); 417 if (startMember == endMember) { 418 return; 419 } 420 SiblingIterator siblings = new SiblingIterator(this, startMember); 421 while (siblings.hasNext()) { 422 final RolapMember member = siblings.nextMember(); 423 list.add(member); 424 if (member == endMember) { 425 return; 426 } 427 } 428 throw Util.newInternal("sibling iterator did not hit end point, start=" 429 + startMember 430 + ", end=" 431 + endMember); 432 } 433 434 public int getMemberCount() { 435 return source.getMemberCount(); 436 } 437 438 public int compare(RolapMember m1, 439 RolapMember m2, 440 boolean siblingsAreEqual) { 441 if (m1 == m2) { 442 return 0; 443 } 444 if (m1.getParentMember() == m2.getParentMember()) { 445 if (siblingsAreEqual) { 447 return 0; 448 } else if (m1.getParentMember() == null) { 449 int pos1 = -1, pos2 = -1; 451 List siblingList = getRootMembers(); 452 for (int i = 0, n = siblingList.size(); i < n; i++) { 453 RolapMember child = (RolapMember) siblingList.get(i); 454 if (child == m1) { 455 pos1 = i; 456 } 457 if (child == m2) { 458 pos2 = i; 459 } 460 } 461 if (pos1 == -1) { 462 throw Util.newInternal(m1 + " not found among siblings"); 463 } 464 if (pos2 == -1) { 465 throw Util.newInternal(m2 + " not found among siblings"); 466 } 467 Util.assertTrue(pos1 != pos2); 468 return pos1 < pos2 ? -1 : 1; 469 } else { 470 List<RolapMember> children = new ArrayList<RolapMember>(); 471 getMemberChildren(m1.getParentMember(), children); 472 int pos1 = -1, pos2 = -1; 473 for (int i = 0, n = children.size(); i < n; i++) { 474 RolapMember child = children.get(i); 475 if (child == m1) { 476 pos1 = i; 477 } 478 if (child == m2) { 479 pos2 = i; 480 } 481 } 482 if (pos1 == -1) { 483 throw Util.newInternal(m1 + " not found among siblings"); 484 } 485 if (pos2 == -1) { 486 throw Util.newInternal(m2 + " not found among siblings"); 487 } 488 Util.assertTrue(pos1 != pos2); 489 return pos1 < pos2 ? -1 : 1; 490 } 491 } 492 int levelDepth1 = m1.getLevel().getDepth(); 493 int levelDepth2 = m2.getLevel().getDepth(); 494 if (levelDepth1 < levelDepth2) { 495 final int c = compare(m1, m2.getParentMember(), false); 496 return (c == 0) ? -1 : c; 497 498 } else if (levelDepth1 > levelDepth2) { 499 final int c = compare(m1.getParentMember(), m2, false); 500 return (c == 0) ? 1 : c; 501 502 } else { 503 return compare(m1.getParentMember(), m2.getParentMember(), false); 504 } 505 } 506 507 513 class SiblingIterator { 514 private final MemberReader reader; 515 private final SiblingIterator parentIterator; 516 private RolapMember[] siblings; 517 private int position; 518 519 SiblingIterator(MemberReader reader, RolapMember member) { 520 this.reader = reader; 521 RolapMember parent = member.getParentMember(); 522 List<RolapMember> siblingList; 523 if (parent == null) { 524 siblingList = reader.getRootMembers(); 525 this.parentIterator = null; 526 } else { 527 siblingList = new ArrayList<RolapMember>(); 528 reader.getMemberChildren(parent, siblingList); 529 this.parentIterator = new SiblingIterator(reader, parent); 530 } 531 this.siblings = RolapUtil.toArray(siblingList); 532 this.position = -1; 533 for (int i = 0; i < this.siblings.length; i++) { 534 if (siblings[i] == member) { 535 this.position = i; 536 break; 537 } 538 } 539 if (this.position == -1) { 540 throw Util.newInternal( 541 "member " + member + " not found among its siblings"); 542 } 543 } 544 boolean hasNext() { 545 return (this.position < this.siblings.length - 1) || 546 (parentIterator != null) && 547 parentIterator.hasNext(); 548 } 549 Object next() { 550 return nextMember(); 551 } 552 RolapMember nextMember() { 553 if (++this.position >= this.siblings.length) { 554 if (parentIterator == null) { 555 throw Util.newInternal("there is no next member"); 556 } 557 RolapMember parent = parentIterator.nextMember(); 558 List<RolapMember> siblingList = new ArrayList<RolapMember>(); 559 reader.getMemberChildren(parent, siblingList); 560 this.siblings = RolapUtil.toArray(siblingList); 561 this.position = 0; 562 } 563 return this.siblings[this.position]; 564 } 565 boolean hasPrevious() { 566 return (this.position > 0) || 567 (parentIterator != null) && 568 parentIterator.hasPrevious(); 569 } 570 Object previous() { 571 return previousMember(); 572 } 573 RolapMember previousMember() { 574 if (--this.position < 0) { 575 if (parentIterator == null) { 576 throw Util.newInternal("there is no next member"); 577 } 578 RolapMember parent = parentIterator.previousMember(); 579 List<RolapMember> siblingList = new ArrayList<RolapMember>(); 580 reader.getMemberChildren(parent, siblingList); 581 this.siblings = RolapUtil.toArray(siblingList); 582 this.position = this.siblings.length - 1; 583 } 584 return this.siblings[this.position]; 585 } 586 } 587 588 public MemberBuilder getMemberBuilder() { 589 return source.getMemberBuilder(); 590 } 591 } 592 593 | Popular Tags |