1 10 package mondrian.rolap; 11 12 import mondrian.olap.*; 13 import mondrian.resource.MondrianResource; 14 import mondrian.olap.CacheControl; 15 16 import javax.sql.DataSource ; 17 import java.util.*; 18 import java.io.PrintWriter ; 19 20 27 public class CacheControlImpl implements CacheControl { 28 public CellRegion createMemberRegion(Member member, boolean descendants) { 29 final ArrayList<Member> list = new ArrayList<Member>(); 30 list.add(member); 31 return new MemberCellRegion(list, descendants); 32 } 33 34 public CellRegion createMemberRegion( 35 boolean lowerInclusive, 36 Member lowerMember, 37 boolean upperInclusive, 38 Member upperMember, 39 boolean descendants) 40 { 41 if (lowerMember == null) { 42 lowerInclusive = false; 43 } 44 if (upperMember == null) { 45 upperInclusive = false; 46 } 47 return new MemberRangeCellRegion( 48 (RolapMember) lowerMember, lowerInclusive, 49 (RolapMember) upperMember, upperInclusive, 50 descendants); 51 } 52 53 public CellRegion createCrossjoinRegion(CellRegion... regions) { 54 assert regions != null; 55 assert regions.length >= 2; 56 final HashSet<Dimension> set = new HashSet<Dimension>(); 57 final List<CellRegionImpl> list = new ArrayList<CellRegionImpl>(); 58 for (CellRegion region : regions) { 59 int prevSize = set.size(); 60 List<Dimension> dimensionality = region.getDimensionality(); 61 set.addAll(dimensionality); 62 if (set.size() < prevSize + dimensionality.size()) { 63 throw MondrianResource.instance(). 64 CacheFlushCrossjoinDimensionsInCommon.ex( 65 getDimensionalityList(regions)); 66 } 67 68 flattenCrossjoin((CellRegionImpl) region, list); 69 } 70 return new CrossjoinCellRegion(list); 71 } 72 73 private String getDimensionalityList(CellRegion[] regions) { 75 StringBuilder buf = new StringBuilder (); 76 int k = 0; 77 for (CellRegion region : regions) { 78 if (k++ > 0) { 79 buf.append(", "); 80 } 81 buf.append("'"); 82 buf.append(region.getDimensionality().toString()); 83 buf.append("'"); 84 } 85 return buf.toString(); 86 } 87 88 public CellRegion createUnionRegion(CellRegion... regions) 89 { 90 if (regions == null) { 91 throw new NullPointerException (); 92 } 93 if (regions.length < 2) { 94 throw new IllegalArgumentException (); 95 } 96 final List<CellRegionImpl> list = new ArrayList<CellRegionImpl>(); 97 for (CellRegion region : regions) { 98 if (!region.getDimensionality().equals( 99 regions[0].getDimensionality())) { 100 throw MondrianResource.instance(). 101 CacheFlushUnionDimensionalityMismatch.ex( 102 regions[0].getDimensionality().toString(), 103 region.getDimensionality().toString()); 104 } 105 list.add((CellRegionImpl) region); 106 } 107 return new UnionCellRegion(list); 108 } 109 110 public CellRegion createMeasuresRegion(Cube cube) { 111 final Dimension measuresDimension = cube.getDimensions()[0]; 112 final Member[] measures = 113 cube.getSchemaReader(null).getLevelMembers( 114 measuresDimension.getHierarchy().getLevels()[0], 115 false); 116 return new MemberCellRegion(Arrays.asList(measures), false); 117 } 118 119 public void flush(CellRegion region) { 120 final List<Dimension> dimensionality = region.getDimensionality(); 121 boolean found = false; 122 for (Dimension dimension : dimensionality) { 123 if (dimension.isMeasures()) { 124 found = true; 125 break; 126 } 127 } 128 if (!found) { 129 throw MondrianResource.instance(). 130 CacheFlushRegionMustContainMembers.ex(); 131 } 132 final UnionCellRegion union = normalize((CellRegionImpl) region); 133 for (CellRegionImpl cellRegion : union.regions) { 134 flushNonUnion(cellRegion); 136 } 137 } 138 139 public void trace(String message) { 140 } 142 143 public void flushSchemaCache() { 144 throw new UnsupportedOperationException (); 145 } 146 147 public void flushSchema( 149 String catalogUrl, 150 String connectionKey, 151 String jdbcUser, 152 String dataSourceStr) 153 { 154 RolapSchema.Pool.instance().remove( 155 catalogUrl, 156 connectionKey, 157 jdbcUser, 158 dataSourceStr); 159 } 160 161 public void flushSchema( 163 String catalogUrl, 164 DataSource dataSource) 165 { 166 RolapSchema.Pool.instance().remove( 167 catalogUrl, 168 dataSource); 169 } 170 171 protected void flushNonUnion(CellRegion region) { 172 throw new UnsupportedOperationException (); 173 } 174 175 181 UnionCellRegion normalize(CellRegionImpl region) { 182 190 List<CellRegionImpl> nonUnionList = new LinkedList<CellRegionImpl>(); 192 flattenUnion(region, nonUnionList); 193 194 for (int i = 0; i < nonUnionList.size(); i++) { 195 while (true) { 196 CellRegionImpl nonUnionRegion = nonUnionList.get(i); 197 UnionCellRegion firstUnion = findFirstUnion(nonUnionRegion); 198 if (firstUnion == null) { 199 break; 200 } 201 List<CellRegionImpl> list = new ArrayList<CellRegionImpl>(); 202 for (CellRegionImpl unionComponent : firstUnion.regions) { 203 CellRegionImpl cj = 206 copyReplacing( 207 nonUnionRegion, 208 firstUnion, 209 unionComponent); 210 list.add(cj); 211 } 212 nonUnionList.remove(i); 216 nonUnionList.addAll(i, list); 217 } 218 } 219 return new UnionCellRegion(nonUnionList); 220 } 221 222 private CellRegionImpl copyReplacing( 223 CellRegionImpl region, 224 CellRegionImpl seek, 225 CellRegionImpl replacement) 226 { 227 if (region == seek) { 228 return replacement; 229 } 230 if (region instanceof UnionCellRegion) { 231 final UnionCellRegion union = (UnionCellRegion) region; 232 List<CellRegionImpl> list = new ArrayList<CellRegionImpl>(); 233 for (CellRegionImpl child : union.regions) { 234 list.add(copyReplacing(child, seek, replacement)); 235 } 236 return new UnionCellRegion(list); 237 } 238 if (region instanceof CrossjoinCellRegion) { 239 final CrossjoinCellRegion crossjoin = (CrossjoinCellRegion) region; 240 List<CellRegionImpl> list = new ArrayList<CellRegionImpl>(); 241 for (CellRegionImpl child : crossjoin.components) { 242 list.add(copyReplacing(child, seek, replacement)); 243 } 244 return new CrossjoinCellRegion(list); 245 } 246 return region; 249 } 250 251 257 private void flattenUnion( 258 CellRegionImpl region, 259 List<CellRegionImpl> list) 260 { 261 if (region instanceof UnionCellRegion) { 262 UnionCellRegion union = (UnionCellRegion) region; 263 for (CellRegionImpl region1 : union.regions) { 264 flattenUnion(region1, list); 265 } 266 } else { 267 list.add(region); 268 } 269 } 270 271 277 private void flattenCrossjoin( 278 CellRegionImpl region, 279 List<CellRegionImpl> list) 280 { 281 if (region instanceof CrossjoinCellRegion) { 282 CrossjoinCellRegion crossjoin = (CrossjoinCellRegion) region; 283 for (CellRegionImpl component : crossjoin.components) { 284 flattenCrossjoin(component, list); 285 } 286 } else { 287 list.add(region); 288 } 289 } 290 291 private UnionCellRegion findFirstUnion(CellRegion region) { 292 final CellRegionVisitor visitor = 293 new CellRegionVisitorImpl() { 294 public void visit(UnionCellRegion region) { 295 throw new FoundOne(region); 296 } 297 }; 298 try { 299 ((CellRegionImpl) region).accept(visitor); 300 return null; 301 } catch (FoundOne foundOne) { 302 return foundOne.region; 303 } 304 } 305 306 313 static List<Member> findMeasures(CellRegion region) { 314 final List<Member> list = new ArrayList<Member>(); 315 final CellRegionVisitor visitor = 316 new CellRegionVisitorImpl() { 317 public void visit(MemberCellRegion region) { 318 if (region.dimension.isMeasures()) { 319 list.addAll(region.memberList); 320 } 321 } 322 323 public void visit(MemberRangeCellRegion region) { 324 if (region.level.getDimension().isMeasures()) { 325 assert false : "ranges on measures dimension"; 327 } 328 } 329 }; 330 ((CellRegionImpl) region).accept(visitor); 331 return list; 332 } 333 334 static List<RolapStar> getStarList(CellRegion region) { 335 List<RolapStar> starList = new ArrayList<RolapStar>(); 337 final List<Member> measuresList = findMeasures(region); 338 for (Member member : measuresList) { 339 RolapStoredMeasure measure = (RolapStoredMeasure) member; 340 final RolapStar.Measure starMeasure = 341 (RolapStar.Measure) measure.getStarMeasure(); 342 if (!starList.contains(starMeasure.getStar())) { 343 starList.add(starMeasure.getStar()); 344 } 345 } 346 return starList; 347 } 348 349 public void printCacheState( 350 PrintWriter pw, 351 CellRegion region) 352 { 353 List<RolapStar> starList = getStarList(region); 354 for (RolapStar star : starList) { 355 star.print(pw, "", false); 356 } 357 } 358 359 364 static class MemberCellRegion implements CellRegionImpl { 365 private final List<Member> memberList; 366 private final Dimension dimension; 367 private final boolean descendants; 368 369 MemberCellRegion(List<Member> memberList, boolean descendants) { 370 assert memberList.size() > 0; 371 this.memberList = memberList; 372 this.dimension = (memberList.get(0)).getDimension(); 373 this.descendants = descendants; 374 } 375 376 public List<Dimension> getDimensionality() { 377 return Collections.singletonList(dimension); 378 } 379 380 public String toString() { 381 final StringBuilder sb = new StringBuilder ("Member("); 382 for (int i = 0; i < memberList.size(); i++) { 383 if (i > 0) { 384 sb.append(", "); 385 } 386 Member member = memberList.get(i); 387 sb.append(member.toString()); 388 } 389 sb.append(")"); 390 return sb.toString(); 391 } 392 393 public void accept(CellRegionVisitor visitor) { 394 visitor.visit(this); 395 } 396 397 public List<Member> getMemberList() { 398 return memberList; 399 } 400 } 401 402 405 static class MemberRangeCellRegion implements CellRegionImpl { 406 private final RolapMember lowerMember; 407 private final boolean lowerInclusive; 408 private final RolapMember upperMember; 409 private final boolean upperInclusive; 410 private final boolean descendants; 411 private final RolapLevel level; 412 413 MemberRangeCellRegion( 414 RolapMember lowerMember, 415 boolean lowerInclusive, 416 RolapMember upperMember, 417 boolean upperInclusive, 418 boolean descendants) 419 { 420 assert lowerMember != null || upperMember != null; 421 assert lowerMember == null 422 || upperMember == null 423 || lowerMember.getLevel() == upperMember.getLevel(); 424 assert !(lowerMember == null && lowerInclusive); 425 assert !(upperMember == null && upperInclusive); 426 this.lowerMember = lowerMember; 427 this.lowerInclusive = lowerInclusive; 428 this.upperMember = upperMember; 429 this.upperInclusive = upperInclusive; 430 this.descendants = descendants; 431 this.level = lowerMember == null ? 432 upperMember.getLevel() : 433 lowerMember.getLevel(); 434 } 435 436 public List<Dimension> getDimensionality() { 437 return Collections.singletonList(level.getDimension()); 438 } 439 440 public RolapLevel getLevel() { 441 return level; 442 } 443 444 public String toString() { 445 final StringBuilder sb = new StringBuilder ("Range("); 446 if (lowerMember == null) { 447 sb.append("null"); 448 } else { 449 sb.append(lowerMember); 450 if (lowerInclusive) { 451 sb.append(" inclusive"); 452 } else { 453 sb.append(" exclusive"); 454 } 455 } 456 sb.append(" to "); 457 if (upperMember == null) { 458 sb.append("null"); 459 } else { 460 sb.append(upperMember); 461 if (upperInclusive) { 462 sb.append(" inclusive"); 463 } else { 464 sb.append(" exclusive"); 465 } 466 } 467 sb.append(")"); 468 return sb.toString(); 469 } 470 471 public void accept(CellRegionVisitor visitor) { 472 visitor.visit(this); 473 } 474 475 public boolean getLowerInclusive() { 476 return lowerInclusive; 477 } 478 479 public RolapMember getLowerBound() { 480 return lowerMember; 481 } 482 483 public boolean getUpperInclusive() { 484 return upperInclusive; 485 } 486 487 public RolapMember getUpperBound() { 488 return upperMember; 489 } 490 } 491 492 495 static class CrossjoinCellRegion implements CellRegionImpl { 496 final List<Dimension> dimensions; 497 private List<CellRegionImpl> components = 498 new ArrayList<CellRegionImpl>(); 499 500 CrossjoinCellRegion(List<CellRegionImpl> regions) { 501 final List<Dimension> dimensionality = new ArrayList<Dimension>(); 502 compute(regions, components, dimensionality); 503 dimensions = Collections.unmodifiableList(dimensionality); 504 } 505 506 private static void compute( 507 List<CellRegionImpl> regions, 508 List<CellRegionImpl> components, 509 List<Dimension> dimensionality) 510 { 511 final Set<Dimension> dimensionSet = new HashSet<Dimension>(); 512 for (CellRegionImpl region : regions) { 513 addComponents(region, components); 514 515 final List<Dimension> regionDimensionality = 516 region.getDimensionality(); 517 dimensionality.addAll(regionDimensionality); 518 dimensionSet.addAll(regionDimensionality); 519 assert dimensionSet.size() == dimensionality.size() : 520 "dimensions in common"; 521 } 522 } 523 524 public void accept(CellRegionVisitor visitor) { 525 visitor.visit(this); 526 for (CellRegion component : components) { 527 CellRegionImpl cellRegion = (CellRegionImpl) component; 528 cellRegion.accept(visitor); 529 } 530 } 531 532 private static void addComponents( 533 CellRegionImpl region, 534 List<CellRegionImpl> list) 535 { 536 if (region instanceof CrossjoinCellRegion) { 537 CrossjoinCellRegion crossjoinRegion = 538 (CrossjoinCellRegion) region; 539 for (CellRegionImpl component : crossjoinRegion.components) { 540 list.add(component); 541 } 542 } else { 543 list.add(region); 544 } 545 } 546 547 public List<Dimension> getDimensionality() { 548 return dimensions; 549 } 550 551 public String toString() { 552 final StringBuilder sb = new StringBuilder ("Crosssjoin("); 553 for (int i = 0; i < components.size(); i++) { 554 if (i > 0) { 555 sb.append(", "); 556 } 557 CellRegion component = components.get(i); 558 sb.append(component.toString()); 559 } 560 sb.append(")"); 561 return sb.toString(); 562 } 563 564 public List<CellRegion> getComponents() { 565 return (List<CellRegion>) (List) components; 566 } 567 } 568 569 private static class UnionCellRegion implements CellRegionImpl { 570 private final List<CellRegionImpl> regions; 571 572 UnionCellRegion(List<CellRegionImpl> regions) { 573 this.regions = regions; 574 assert regions.size() >= 1; 575 576 for (int i = 1; i < regions.size(); i++) { 578 final CellRegion region0 = regions.get(0); 579 final CellRegion region = regions.get(i); 580 assert region0.getDimensionality().equals( 581 region.getDimensionality()); 582 } 583 } 584 585 public List<Dimension> getDimensionality() { 586 return regions.get(0).getDimensionality(); 587 } 588 589 public String toString() { 590 final StringBuilder sb = new StringBuilder ("Union("); 591 for (int i = 0; i < regions.size(); i++) { 592 if (i > 0) { 593 sb.append(", "); 594 } 595 CellRegion component = regions.get(i); 596 sb.append(component.toString()); 597 } 598 sb.append(")"); 599 return sb.toString(); 600 } 601 602 public void accept(CellRegionVisitor visitor) { 603 visitor.visit(this); 604 for (CellRegionImpl cellRegion : regions) { 605 cellRegion.accept(visitor); 606 } 607 } 608 } 609 610 interface CellRegionImpl extends CellRegion { 611 void accept(CellRegionVisitor visitor); 612 } 613 614 617 interface CellRegionVisitor { 618 void visit(MemberCellRegion region); 619 void visit(MemberRangeCellRegion region); 620 void visit(UnionCellRegion region); 621 void visit(CrossjoinCellRegion region); 622 } 623 624 private static class FoundOne extends RuntimeException { 625 private final UnionCellRegion region; 626 627 public FoundOne(UnionCellRegion region) { 628 this.region = region; 629 } 630 } 631 632 635 private static class CellRegionVisitorImpl implements CellRegionVisitor { 636 public void visit(MemberCellRegion region) { 637 } 639 640 public void visit(MemberRangeCellRegion region) { 641 } 643 644 public void visit(UnionCellRegion region) { 645 } 647 648 public void visit(CrossjoinCellRegion region) { 649 } 651 } 652 } 653 654 | Popular Tags |