1 13 14 package mondrian.rolap; 15 import mondrian.calc.Calc; 16 import mondrian.calc.ParameterSlot; 17 import mondrian.olap.*; 18 import mondrian.olap.fun.MondrianEvaluationException; 19 import mondrian.resource.MondrianResource; 20 import mondrian.rolap.agg.AggregationManager; 21 import mondrian.util.Format; 22 import mondrian.util.Bug; 23 import mondrian.util.ObjectPool; 24 25 import org.apache.log4j.Logger; 26 27 import java.util.Collections ; 28 import java.util.ArrayList ; 29 import java.util.List ; 30 import java.util.Iterator ; 31 import java.util.ListIterator ; 32 import java.util.HashMap ; 33 import java.util.Map ; 34 import java.util.Locale ; 35 36 43 public 44 class RolapResult extends ResultBase { 45 46 private static final Logger LOGGER = Logger.getLogger(ResultBase.class); 47 48 private RolapEvaluator evaluator; 49 private final CellKey point; 50 51 private CellInfoContainer cellInfos; 52 private FastBatchingCellReader batchingReader; 53 AggregatingCellReader aggregatingReader = new AggregatingCellReader(); 54 private Modulos modulos = null; 55 private final int maxEvalDepth = 56 MondrianProperties.instance().MaxEvalDepth.get(); 57 58 RolapResult(Query query, boolean execute) { 59 super(query, new Axis[query.axes.length]); 60 61 this.point = CellKey.Generator.newCellKey(query.axes.length); 62 final int expDeps = MondrianProperties.instance().TestExpDependencies.get(); 63 if (expDeps > 0) { 64 this.evaluator = new RolapDependencyTestingEvaluator(this, expDeps); 65 } else { 66 final RolapEvaluator.RolapEvaluatorRoot root = 67 new RolapResultEvaluatorRoot(this); 68 this.evaluator = new RolapEvaluator(root); 69 } 70 RolapCube rcube = (RolapCube) query.getCube(); 71 this.batchingReader = new FastBatchingCellReader(rcube); 72 73 this.cellInfos = (query.axes.length > 4) 74 ? new CellInfoMap(point) : new CellInfoPool(query.axes.length); 75 76 77 if (!execute) { 78 return; 79 } 80 81 boolean normalExecution = true; 82 try { 83 rcube.clearCachedAggregations(); 88 rcube.checkAggregateModifications(); 90 91 92 183 184 final AxisMember axisMembers = new AxisMember(); 187 188 189 final List <Member> nonDefaultAllMembers = new ArrayList <Member>(); 191 192 List <Member[]> nonAllMembers = new ArrayList <Member[]>(); 194 195 final List <Member> measureMembers = new ArrayList <Member>(); 197 198 loadSpecialMembers(nonDefaultAllMembers, 202 nonAllMembers, measureMembers); 203 204 query.clearEvalCache(); 206 207 query.putEvalCache("ALL_MEMBER_LIST", nonDefaultAllMembers); 209 210 211 final List <Member[]> emptyNonAllMembers = Collections.emptyList(); 212 213 axisMembers.setSlicer(true); 218 loadMembers(emptyNonAllMembers, evaluator, 219 query.slicerAxis, query.slicerCalc, axisMembers); 220 axisMembers.setSlicer(false); 221 222 if (! axisMembers.isEmpty()) { 223 for (Member m : axisMembers) { 224 evaluator.setContext(m); 225 if (m.isMeasure()) { 226 measureMembers.clear(); 230 } 231 } 232 replaceNonAllMembers(nonAllMembers, axisMembers); 233 axisMembers.clearMembers(); 234 } 235 238 239 boolean changed = false; 244 245 axisMembers.clearTotalCellCount(); 247 248 for (int i = 0; i < axes.length; i++) { 249 final QueryAxis axis = query.axes[i]; 250 final Calc calc = query.axisCalcs[i]; 251 loadMembers(emptyNonAllMembers, evaluator, 252 axis, calc, axisMembers); 253 } 254 255 if (! axisMembers.isEmpty()) { 256 for (Member m : axisMembers) { 257 if (m.isMeasure()) { 258 measureMembers.clear(); 262 } 263 } 264 changed = replaceNonAllMembers(nonAllMembers, axisMembers); 265 axisMembers.clearMembers(); 266 } 267 268 294 295 296 if (changed) { 297 axisMembers.countOnly(true); 299 axisMembers.clearTotalCellCount(); 301 302 for (int i = 0; i < axes.length; i++) { 303 final QueryAxis axis = query.axes[i]; 304 final Calc calc = query.axisCalcs[i]; 305 loadMembers(nonAllMembers, 306 (RolapEvaluator) evaluator.push(), 307 axis, calc, axisMembers); 308 } 309 } 310 311 axisMembers.checkLimit(); 313 314 317 this.slicerAxis = evalExecute(nonAllMembers, 322 nonAllMembers.size()-1, 323 (RolapEvaluator) evaluator.push(), 324 query.slicerAxis, 325 query.slicerCalc); 326 332 switch (this.slicerAxis.getPositions().size()) { 339 case 0: 340 throw MondrianResource.instance().EmptySlicer.ex(); 341 case 1: 342 break; 343 default: 344 throw MondrianResource.instance().CompoundSlicer.ex(); 345 } 346 349 boolean redo = true; 354 while (redo) { 355 RolapEvaluator e = (RolapEvaluator) evaluator.push(); 356 redo = false; 357 358 for (int i = 0; i < axes.length; i++) { 359 QueryAxis axis = query.axes[i]; 360 final Calc calc = query.axisCalcs[i]; 361 Axis axisResult = evalExecute(nonAllMembers, 362 nonAllMembers.size()-1, e, axis, calc); 363 364 if (! nonAllMembers.isEmpty()) { 365 List <Position> pl = axisResult.getPositions(); 366 for (Position p: pl) { 367 for (Member m: p) { 368 if (m.isCalculated()) { 369 CalculatedMeasureVisitor visitor = 370 new CalculatedMeasureVisitor(); 371 m.getExpression().accept(visitor); 372 Dimension dimension = visitor.dimension; 373 redo = removeDimension(dimension, nonAllMembers); 374 } 375 } 376 break; 378 } 379 } 380 this.axes[i] = axisResult; 381 } 382 } 383 386 executeBody(query); 391 394 if (this.cellInfos.size() > 10000) { 402 this.cellInfos.trimToSize(); 403 } 404 405 } catch (ResultLimitExceededException ex) { 406 normalExecution = false; 409 410 evaluator = null; 413 cellInfos = null; 414 batchingReader = null; 415 for (int i = 0; i < axes.length; i++) { 416 axes[i] = null; 417 } 418 slicerAxis = null; 419 420 query.clearEvalCache(); 421 422 throw ex; 423 424 } finally { 425 if (normalExecution) { 426 rcube.pushAggregateModificationsToGlobalCache(); 429 430 evaluator.clearExpResultCache(); 431 } 432 if (LOGGER.isDebugEnabled()) { 433 LOGGER.debug("RolapResult<init>: " + Util.printMemory()); 434 } 435 } 436 } 437 protected boolean removeDimension(Dimension dimension, List <Member[]> nonAllMembers) { 438 boolean changed = false; 439 for (ListIterator <Member[]> it = nonAllMembers.listIterator(); 440 it.hasNext();) { 441 Member[] ms = it.next(); 442 Dimension d = ms[0].getHierarchy().getDimension(); 443 if (d.equals(dimension)) { 444 it.remove(); 445 } 446 } 447 return changed; 448 } 449 450 private static class CalculatedMeasureVisitor extends mondrian.mdx.MdxVisitorImpl { 451 Dimension dimension; 452 CalculatedMeasureVisitor() { 453 } 454 public Object visit(mondrian.olap.Formula formula) { 455 return null; 456 } 457 public Object visit(mondrian.mdx.ResolvedFunCall call) { 458 return null; 459 } 460 public Object visit(mondrian.olap.Id id) { 461 return null; 462 } 463 public Object visit(mondrian.mdx.ParameterExpr parameterExpr) { 464 return null; 465 } 466 public Object visit(mondrian.mdx.DimensionExpr dimensionExpr) { 467 dimension = dimensionExpr.getDimension(); 468 return null; 469 } 470 public Object visit(mondrian.mdx.HierarchyExpr hierarchyExpr) { 471 Hierarchy hierarchy = hierarchyExpr.getHierarchy(); 472 dimension = hierarchy.getDimension(); 473 return null; 474 } 475 public Object visit(mondrian.mdx.LevelExpr levelExpr) { 476 return null; 477 } 478 public Object visit(mondrian.mdx.MemberExpr memberExpr) { 479 Member member = memberExpr.getMember(); 480 dimension = member.getHierarchy().getDimension(); 481 return null; 482 } 483 public Object visit(mondrian.mdx.NamedSetExpr namedSetExpr) { 484 return null; 485 } 486 public Object visit(mondrian.olap.Literal literal) { 487 return null; 488 } 489 } 490 private static class MeasureVisitor extends mondrian.mdx.MdxVisitorImpl { 491 List <Member> measures; 492 MeasureVisitor() { 493 measures = new ArrayList <Member>(); 494 } 495 public Object visit(mondrian.olap.Formula formula) { 496 return null; 497 } 498 public Object visit(mondrian.mdx.ResolvedFunCall call) { 499 return null; 500 } 501 public Object visit(mondrian.olap.Id id) { 502 return null; 503 } 504 public Object visit(mondrian.mdx.ParameterExpr parameterExpr) { 505 return null; 506 } 507 public Object visit(mondrian.mdx.DimensionExpr dimensionExpr) { 508 return null; 509 } 510 public Object visit(mondrian.mdx.HierarchyExpr hierarchyExpr) { 511 return null; 512 } 513 public Object visit(mondrian.mdx.LevelExpr levelExpr) { 514 return null; 515 } 516 public Object visit(mondrian.mdx.MemberExpr memberExpr) { 517 Member member = memberExpr.getMember(); 518 if (member.isMeasure()) { 519 if (! measures.contains(member)) { 520 measures.add(member); 521 } 522 } 523 return null; 524 } 525 public Object visit(mondrian.mdx.NamedSetExpr namedSetExpr) { 526 return null; 527 } 528 public Object visit(mondrian.olap.Literal literal) { 529 return null; 530 } 531 } 532 533 protected boolean replaceNonAllMembers(List <Member[]> nonAllMembers, 534 AxisMember axisMembers) { 535 536 boolean changed = false; 537 List <Member> mList = new ArrayList <Member>(); 538 for (ListIterator <Member[]> it = nonAllMembers.listIterator(); 539 it.hasNext();) { 540 Member[] ms = it.next(); 541 Hierarchy h = ms[0].getHierarchy(); 542 mList.clear(); 543 for (Member m : axisMembers) { 544 if (m.getHierarchy().equals(h)) { 545 mList.add(m); 546 } 547 } 548 if (! mList.isEmpty()) { 549 changed = true; 550 Member[] ml = mList.toArray(new Member[mList.size()]); 551 it.set(ml); 552 } 553 } 554 return changed; 555 556 } 557 558 protected void loadMembers(List <Member[]> nonAllMembers, 559 RolapEvaluator evaluator, QueryAxis axis, Calc calc, 560 AxisMember axisMembers) { 561 int attempt = 0; 562 evaluator.setCellReader(batchingReader); 563 while (true) { 564 axisMembers.clearAxisCount(); 565 evalLoad(nonAllMembers, nonAllMembers.size()-1, 566 evaluator, axis, calc, axisMembers); 567 evaluator.clearExpResultCache(); 568 569 if (!batchingReader.loadAggregations(query)) { 570 break; 571 } 572 573 if (attempt++ > maxEvalDepth) { 574 throw Util.newInternal( 575 "Failed to load all aggregations after " + 576 maxEvalDepth + 577 "passes; there's probably a cycle"); 578 } 579 } 580 } 581 582 void evalLoad(List <Member[]> nonAllMembers, int cnt, 583 Evaluator evaluator, QueryAxis axis, Calc calc, 584 AxisMember axisMembers) { 585 if (cnt < 0) { 586 executeAxis(evaluator.push(), axis, calc, false, axisMembers); 587 } else { 588 for (Member m : nonAllMembers.get(cnt)) { 589 evaluator.setContext(m); 590 evalLoad(nonAllMembers, cnt-1, evaluator, axis, calc, axisMembers); 591 } 592 } 593 } 594 Axis evalExecute(List <Member[]> nonAllMembers, int cnt, 595 RolapEvaluator evaluator, QueryAxis axis, Calc calc) { 596 Axis axisResult = null; 597 if (cnt < 0) { 598 evaluator.setCellReader(aggregatingReader); 599 axisResult = 600 executeAxis(evaluator.push(), axis, calc, true, null); 601 evaluator.clearExpResultCache(); 602 } else { 603 for (Member m : nonAllMembers.get(cnt)) { 604 evaluator.setContext(m); 605 Axis a = evalExecute(nonAllMembers, cnt-1, evaluator, axis, calc); 606 axisResult = mergeAxes(axisResult, a); 607 } 608 } 609 return axisResult; 610 } 611 612 623 protected void loadSpecialMembers(List <Member> nonDefaultAllMembers, 624 List <Member[]> nonAllMembers, 625 List <Member> measureMembers) { 626 SchemaReader schemaReader = evaluator.getSchemaReader(); 627 Member[] evalMembers = evaluator.getMembers(); 628 for (int i = 0, j = 0; i < evalMembers.length; i++) { 629 Member em = evalMembers[i]; 630 if (em.isCalculated()) { 631 continue; 632 } 633 Hierarchy h = em.getHierarchy(); 634 Dimension d = h.getDimension(); 635 if (d.getDimensionType() == DimensionType.TimeDimension) { 636 continue; 637 } 638 if (! em.isAll()) { 639 Member[] rootMembers = schemaReader.getHierarchyRootMembers(h); 640 if (em.isMeasure()) { 641 for (Member mm : rootMembers) { 642 measureMembers.add(mm); 643 } 644 } else { 645 if (h.hasAll()) { 646 boolean found = false; 647 for (Member m : rootMembers) { 648 if (m.isAll()) { 649 nonDefaultAllMembers.add(m); 650 found = true; 651 break; 652 } 653 } 654 if (! found) { 655 } 656 } else { 657 nonAllMembers.add(rootMembers); 658 } 659 } 660 } 661 } 662 } 663 664 protected Logger getLogger() { 665 return LOGGER; 666 } 667 public Cube getCube() { 668 return evaluator.getCube(); 669 } 670 671 public Axis[] getAxes() { 673 return axes; 674 } 675 676 682 public Cell getCell(int[] pos) { 683 if (pos.length != point.size()) { 684 throw Util.newError( 685 "coordinates should have dimension " + point.size()); 686 } 687 688 CellInfo ci = cellInfos.lookup(pos); 689 if (ci.value == null) { 690 ci.value = Util.nullValue; 691 } 692 693 return new RolapCell(this, pos.clone(), ci); 694 } 695 696 private Axis executeAxis( 697 Evaluator evaluator, 698 QueryAxis axis, 699 Calc axisCalc, 700 boolean construct, 701 AxisMember axisMembers) 702 { 703 Axis axisResult = null; 704 if (axis == null) { 705 if (construct) { 708 axisResult = new RolapAxis.SingleEmptyPosition(); 709 } 710 711 } else { 712 evaluator.setNonEmpty(axis.isNonEmpty()); 713 evaluator.setEvalAxes(true); 714 Object value = axisCalc.evaluate(evaluator); 715 evaluator.setNonEmpty(false); 716 if (value != null) { 717 if (value instanceof List ) { 719 List <Object > list = (List ) value; 720 if (construct) { 721 if (list.size() == 0) { 722 axisResult = new RolapAxis.NoPosition(); 724 } else if (list.get(0) instanceof Member[]) { 725 axisResult = 726 new RolapAxis.MemberArrayList((List <Member[]>)value); 727 } else { 728 axisResult = 729 new RolapAxis.MemberList((List <Member>)value); 730 } 731 } else if (axisMembers != null) { 732 axisMembers.merge(value); 733 } 734 } else { 735 Iterable <Object > iter = (Iterable ) value; 737 Iterator it = iter.iterator(); 738 if (construct) { 739 if (! it.hasNext()) { 740 axisResult = new RolapAxis.NoPosition(); 741 } else if (it.next() instanceof Member[]) { 742 axisResult = new RolapAxis.MemberArrayIterable( 743 (Iterable <Member[]>)value); 744 } else { 745 axisResult = new RolapAxis.MemberIterable( 746 (Iterable <Member>)value); 747 } 748 } else if (axisMembers != null) { 749 axisMembers.merge(it); 750 } 751 } 752 } 753 evaluator.setEvalAxes(false); 754 } 755 return axisResult; 756 } 757 758 private void executeBody(Query query) { 759 try { 760 int count = 0; 763 while (true) { 764 765 evaluator.setCellReader(this.batchingReader); 766 executeStripe(query.axes.length - 1, 767 (RolapEvaluator) evaluator.push()); 768 evaluator.clearExpResultCache(); 769 770 if (!batchingReader.loadAggregations(query)) { 773 return; 776 } 777 if (count++ > maxEvalDepth) { 778 if (evaluator instanceof RolapDependencyTestingEvaluator) { 779 ((RolapDependencyTestingEvaluator.DteRoot) evaluator.root).disabled = true; 783 if (count > maxEvalDepth * 2) { 784 throw Util.newInternal("Query required more than " 785 + count + " iterations"); 786 } 787 } else { 788 throw Util.newInternal("Query required more than " 789 + count + " iterations"); 790 } 791 } 792 793 cellInfos.clear(); 794 } 795 } finally { 796 797 } 798 } 799 800 boolean isDirty() { 801 return batchingReader.isDirty(); 802 } 803 804 private Object evaluateExp(Calc calc, Evaluator evaluator) { 805 int attempt = 0; 806 boolean dirty = batchingReader.isDirty(); 807 while (true) { 808 RolapEvaluator ev = (RolapEvaluator) evaluator.push(); 809 810 ev.setCellReader(batchingReader); 811 Object preliminaryValue = calc.evaluate(ev); 812 Util.discard(preliminaryValue); 813 if (!batchingReader.loadAggregations(evaluator.getQuery())) { 814 break; 815 } 816 if (attempt++ > maxEvalDepth) { 817 throw Util.newInternal( 818 "Failed to load all aggregations after " + 819 maxEvalDepth + "passes; there's probably a cycle"); 820 } 821 } 822 823 if (dirty) { 827 batchingReader.setDirty(true); 828 } 829 RolapEvaluator ev = (RolapEvaluator) evaluator.push(); 830 ev.setCellReader(aggregatingReader); 831 Object value = calc.evaluate(ev); 832 return value; 833 } 834 835 839 private static class AggregatingCellReader implements CellReader { 840 private final RolapAggregationManager aggMan = 841 AggregationManager.instance(); 842 843 public Object get(Evaluator evaluator) { 845 final RolapEvaluator rolapEvaluator = (RolapEvaluator) evaluator; 846 return aggMan.getCellFromCache(rolapEvaluator.getMembers()); 847 } 848 849 public int getMissCount() { 850 return aggMan.getMissCount(); 851 } 852 } 853 854 private void executeStripe(int axisOrdinal, RolapEvaluator revaluator) { 855 if (axisOrdinal < 0) { 856 Axis axis = slicerAxis; 857 List <Position> positions = axis.getPositions(); 858 for (Position position: positions) { 859 getQuery().checkCancelOrTimeout(); 860 revaluator.setContext(position); 861 Object o; 862 try { 863 o = revaluator.evaluateCurrent(); 864 } catch (MondrianEvaluationException e) { 865 o = e; 866 } 867 868 CellInfo ci = null; 869 870 try { 873 878 ci = cellInfos.create(point.getOrdinals()); 881 882 String cachedFormatString = null; 883 ValueFormatter valueFormatter; 884 885 RolapCube cube = (RolapCube) getCube(); 891 Dimension measuresDim = 892 cube.getMeasuresHierarchy().getDimension(); 893 RolapMeasure m = 894 (RolapMeasure) revaluator.getContext(measuresDim); 895 CellFormatter cf = m.getFormatter(); 896 if (cf != null) { 897 valueFormatter = cellFormatters.get(cf); 898 if (valueFormatter == null) { 899 valueFormatter = new CellFormatterValueFormatter(cf); 900 cellFormatters.put(cf, valueFormatter); 901 } 902 } else { 903 cachedFormatString = revaluator.getFormatString(); 904 Locale locale = query.getConnection().getLocale(); 905 valueFormatter = formatValueFormatters.get(locale); 906 if (valueFormatter == null) { 907 valueFormatter = new FormatValueFormatter(locale); 908 formatValueFormatters.put(locale, valueFormatter); 909 } 910 } 911 912 ci.formatString = cachedFormatString; 913 ci.valueFormatter = valueFormatter; 914 915 } catch (ResultLimitExceededException e) { 916 throw e; 918 919 } catch (MondrianEvaluationException e) { 920 922 } catch (Throwable e) { 923 Util.discard(e); 924 } 925 926 if (o == RolapUtil.valueNotReadyException) { 927 continue; 928 } 929 930 ci.value = o; 931 } 932 } else { 933 Axis axis = axes[axisOrdinal]; 934 List <Position> positions = axis.getPositions(); 935 int i = 0; 936 for (Position position: positions) { 937 point.setAxis(axisOrdinal, i); 938 revaluator.setContext(position); 939 getQuery().checkCancelOrTimeout(); 940 executeStripe(axisOrdinal - 1, revaluator); 941 i++; 942 } 943 } 944 } 945 946 953 int[] getCellPos(int cellOrdinal) { 954 if (modulos == null) { 955 makeModulos(); 956 } 957 return modulos.getCellPos(cellOrdinal); 958 } 959 960 967 int getCellOrdinal(int[] pos) { 968 if (modulos == null) { 969 makeModulos(); 970 } 971 return modulos.getCellOrdinal(pos); 972 } 973 974 981 protected void makeModulos() { 982 modulos = Modulos.Generator.create(axes); 983 } 984 985 991 RolapEvaluator getCellEvaluator(int[] pos) { 992 final RolapEvaluator cellEvaluator = (RolapEvaluator) evaluator.push(); 993 for (int i = 0; i < pos.length; i++) { 994 Position position = axes[i].getPositions().get(pos[i]); 995 cellEvaluator.setContext(position); 996 } 997 return cellEvaluator; 998 } 999 1000 1007 Member[] getCellMembers(int[] pos) { 1008 Member[] members = evaluator.getMembers().clone(); 1009 final Cube cube = getCube(); 1010 for (int i = 0; i < pos.length; i++) { 1011 Position position = axes[i].getPositions().get(pos[i]); 1012 for (Member member: position) { 1013 RolapMember m = (RolapMember) member; 1014 int ordinal = m.getDimension().getOrdinal(cube); 1015 members[ordinal] = m; 1016 } 1017 1018 } 1019 return members; 1020 } 1021 1022 Evaluator getRootEvaluator() { 1023 return evaluator; 1024 } 1025 1026 Evaluator getEvaluator(int[] pos) { 1027 Evaluator cellEvaluator = evaluator.push(); 1030 for (int i = -1; i < axes.length; i++) { 1031 Axis axis; 1032 int index; 1033 if (i < 0) { 1034 axis = slicerAxis; 1035 index = 0; 1036 } else { 1037 axis = axes[i]; 1038 index = pos[i]; 1039 } 1040 Position position = axis.getPositions().get(index); 1041 cellEvaluator.setContext(position); 1042 } 1043 return cellEvaluator; 1044 } 1045 1046 1047 1055 private static class AxisMember implements Iterable <Member> { 1056 private final List <Member> members; 1057 private final int limit; 1058 private boolean isSlicer; 1059 private int totalCellCount; 1060 private int axisCount; 1061 private boolean countOnly; 1062 1063 AxisMember() { 1064 this.countOnly = false; 1065 this.members = new ArrayList <Member>(); 1066 this.totalCellCount = 1; 1067 this.axisCount = 0; 1068 this.limit = MondrianProperties.instance().ResultLimit.get(); 1071 } 1072 public Iterator <Member> iterator() { 1073 return members.iterator(); 1074 } 1075 void setSlicer(final boolean isSlicer) { 1076 this.isSlicer = isSlicer; 1077 } 1078 boolean isEmpty() { 1079 return this.members.isEmpty(); 1080 } 1081 void countOnly(boolean countOnly) { 1082 this.countOnly = countOnly; 1083 } 1084 void checkLimit() { 1085 if (this.limit > 0) { 1086 this.totalCellCount *= this.axisCount; 1087 if (this.totalCellCount > this.limit) { 1088 throw MondrianResource.instance(). 1089 TotalMembersLimitExceeded.ex(this.totalCellCount, 1090 this.limit); 1091 } 1092 this.axisCount = 0; 1093 } 1094 } 1095 void clearAxisCount() { 1096 this.axisCount = 0; 1097 } 1098 void clearTotalCellCount() { 1099 this.totalCellCount = 1; 1100 } 1101 void clearMembers() { 1102 this.members.clear(); 1103 this.axisCount = 0; 1104 this.totalCellCount = 1; 1105 } 1106 List <Member> members() { 1107 return this.members; 1108 } 1109 void merge(Object value) { 1110 List <Object > list = (List ) value; 1111 if (list.size() != 0) { 1112 if (list.get(0) instanceof Member[]) { 1113 for (Member[] o : (List <Member[]>) value) { 1114 merge(o); 1115 } 1116 } else { 1117 for (Member o : (List <Member>) value) { 1118 merge(o); 1119 } 1120 } 1121 } 1122 } 1123 void merge(Iterator it) { 1124 if (it.hasNext()) { 1125 Object o = it.next(); 1126 if (o instanceof Member[]) { 1127 merge((Member[]) o); 1128 while (it.hasNext()) { 1129 o = it.next(); 1130 merge((Member[]) o); 1131 } 1132 } else { 1133 merge((Member) o); 1134 while (it.hasNext()) { 1135 o = it.next(); 1136 merge((Member) o); 1137 } 1138 } 1139 } 1140 } 1141 private Member getTopParent(final Member m) { 1142 Member parent = m.getParentMember(); 1143 return (parent == null) ? m : getTopParent(parent); 1144 } 1145 1146 private void merge(final List <Member> members) { 1147 for (Member member : members) { 1148 merge(member); 1149 } 1150 } 1151 private void merge(final Member[] members) { 1152 for (Member member : members) { 1153 merge(member); 1154 } 1155 } 1156 1157 private void merge(final Member member) { 1158 this.axisCount++; 1159 if (! countOnly) { 1160 if (isSlicer) { 1161 if (! members.contains(member)) { 1162 members.add(member); 1163 } 1164 } else { 1165 if (member.isNull()) { 1166 return; 1167 } else if (member.isMeasure()) { 1168 return; 1169 } else if (member.isCalculated()) { 1170 return; 1171 } else if (member.isAll()) { 1172 return; 1173 } 1174 Member topParent = getTopParent(member); 1175 if (! this.members.contains(topParent)) { 1176 this.members.add(topParent); 1177 } 1178 } 1179 } 1180 } 1181 } 1182 1183 1184 1194 protected static class RolapResultEvaluatorRoot 1195 extends RolapEvaluator.RolapEvaluatorRoot { 1196 1199 private final Map <String , Object > namedSetValues = 1200 new HashMap <String , Object >(); 1201 1202 1205 private RolapEvaluator slicerEvaluator; 1206 private final RolapResult result; 1207 private static final Object Sentinel = new Object (); 1208 1209 public RolapResultEvaluatorRoot(RolapResult result) { 1210 super(result.query); 1211 this.result = result; 1212 } 1213 1214 protected void init(Evaluator evaluator) { 1215 slicerEvaluator = (RolapEvaluator) evaluator; 1216 } 1217 1218 protected Object evaluateNamedSet(String name, Exp exp) { 1219 Object value = namedSetValues.get(name); 1220 if (value == null) { 1221 final RolapEvaluator.RolapEvaluatorRoot root = 1222 slicerEvaluator.root; 1223 final Calc calc = root.getCompiled(exp, false); 1224 Object o = result.evaluateExp(calc, slicerEvaluator.push()); 1225 List list; 1226 if (o instanceof List ) { 1227 list = (List ) o; 1228 } else { 1229 1231 Iterable iter = (Iterable ) o; 1240 list = new ArrayList (); 1241 for (Object e: iter) { 1242 list.add(e); 1243 } 1244 } 1245 value = Collections.unmodifiableList(list); 1248 namedSetValues.put(name, value); 1249 } 1250 return value; 1251 } 1252 1253 protected void clearNamedSets() { 1254 namedSetValues.clear(); 1255 } 1256 1257 public Object getParameterValue(ParameterSlot slot) { 1258 Object value = slot.getParameterValue(); 1259 if (value != null) { 1260 return value; 1261 } 1262 1263 Parameter.Scope scope = slot.getParameter().getScope(); 1266 switch (scope) { 1267 case System: 1268 1270 case Schema: 1272 1274 case Connection: 1276 1278 case Statement: 1280 break; 1281 1282 default: 1283 throw Util.badValue(scope); 1284 } 1285 1286 value = slot.getCachedDefaultValue(); 1289 if (value != null) { 1290 if (value == Sentinel) { 1291 throw MondrianResource.instance(). 1292 CycleDuringParameterEvaluation.ex( 1293 slot.getParameter().getName()); 1294 } 1295 return value; 1296 } 1297 slot.setCachedDefaultValue(Sentinel); 1299 value = result.evaluateExp( 1300 slot.getDefaultValueCalc(), slicerEvaluator.push()); 1301 slot.setCachedDefaultValue(value); 1302 return value; 1303 } 1304 } 1305 1306 1326 interface ValueFormatter { 1327 String format(Object value, String formatString); 1328 } 1329 1330 1334 class CellFormatterValueFormatter implements ValueFormatter { 1335 final CellFormatter cf; 1336 1337 1342 CellFormatterValueFormatter(CellFormatter cf) { 1343 this.cf = cf; 1344 } 1345 public String format(Object value, String formatString) { 1346 return cf.formatCell(value); 1347 } 1348 } 1349 1350 1356 class FormatValueFormatter implements ValueFormatter{ 1357 final Locale locale; 1358 1359 1364 FormatValueFormatter(Locale locale) { 1365 this.locale = locale; 1366 } 1367 public String format(Object value, String formatString) { 1368 if (value == Util.nullValue) { 1369 Format format = getFormat(formatString); 1370 return format.format(null); 1371 } else if (value instanceof Throwable ) { 1372 return "#ERR: " + value.toString(); 1373 } else if (value instanceof String ) { 1374 return (String ) value; 1375 } else { 1376 Format format = getFormat(formatString); 1377 return format.format(value); 1378 } 1379 } 1380 private Format getFormat(String formatString) { 1381 return Format.get(formatString, locale); 1382 } 1383 } 1384 1385 1416 1417 1418 1419 1424 protected static final Map <Locale , ValueFormatter> 1425 formatValueFormatters = 1426 Collections.synchronizedMap(new HashMap <Locale , ValueFormatter>()); 1427 1428 1434 protected static final Map <CellFormatter, ValueFormatter> 1435 cellFormatters = 1436 Collections.synchronizedMap(new HashMap <CellFormatter, ValueFormatter>()); 1437 1438 1446 static class CellInfo { 1447 Object value; 1448 String formatString; 1449 ValueFormatter valueFormatter; 1450 long key; 1451 1452 1457 CellInfo(long key) { 1458 this(key, null, null, null); 1459 } 1460 1461 1470 CellInfo( 1471 long key, 1472 Object value, 1473 String formatString, 1474 ValueFormatter valueFormatter) 1475 { 1476 this.key = key; 1477 this.value = value; 1478 this.formatString = formatString; 1479 this.valueFormatter = valueFormatter; 1480 } 1481 1482 public int hashCode() { 1483 return (int)(key ^ (key >>> 32)); 1484 } 1485 public boolean equals(Object o) { 1486 if (o instanceof CellInfo) { 1487 CellInfo that = (CellInfo) o; 1488 return that.key == this.key; 1489 } else { 1490 return false; 1491 } 1492 } 1493 1494 1498 String getFormatValue() { 1499 return valueFormatter.format(value, formatString); 1500 } 1501 } 1502 1503 1508 interface CellInfoContainer { 1509 1513 int size(); 1514 1519 void trimToSize(); 1520 1524 void clear(); 1525 1532 CellInfo create(int[] pos); 1533 1539 CellInfo lookup(int[] pos); 1540 } 1541 1542 1551 static class CellInfoMap implements CellInfoContainer { 1552 private final Map <CellKey, CellInfo> cellInfoMap; 1553 private final CellKey point; 1554 1555 1560 CellInfoMap(CellKey point) { 1561 this.point = point; 1562 this.cellInfoMap = new HashMap <CellKey, CellInfo>(); 1563 } 1564 public int size() { 1565 return this.cellInfoMap.size(); 1566 } 1567 public void trimToSize() { 1568 } 1570 public void clear() { 1571 this.cellInfoMap.clear(); 1572 } 1573 public CellInfo create(int[] pos) { 1574 CellKey key = this.point.copy(); 1575 CellInfo ci = this.cellInfoMap.get(key); 1576 if (ci == null) { 1577 ci = new CellInfo(0); 1578 this.cellInfoMap.put(key, ci); 1579 } 1580 return ci; 1581 } 1582 public CellInfo lookup(int[] pos) { 1583 CellKey key = CellKey.Generator.newCellKey(pos); 1584 return this.cellInfoMap.get(key); 1585 } 1586 } 1587 1588 1610 static class CellInfoPool implements CellInfoContainer { 1611 1615 protected static final long MAX_AXIS_SIZE_2 = 2147483647; 1616 1620 protected static final long MAX_AXIS_SIZE_3 = 2000000; 1621 1625 protected static final long MAX_AXIS_SIZE_4 = 50000; 1626 1627 1631 interface CellKeyMaker { 1632 long generate(int[] pos); 1633 } 1634 1637 static class Zero implements CellKeyMaker { 1638 public long generate(int[] pos) { 1639 return 0; 1640 } 1641 } 1642 1645 static class One implements CellKeyMaker { 1646 public long generate(int[] pos) { 1647 return pos[0]; 1648 } 1649 } 1650 1653 static class Two implements CellKeyMaker { 1654 public long generate(int[] pos) { 1655 long l = pos[0]; 1656 l += (MAX_AXIS_SIZE_2 * (long) pos[1]); 1657 return l; 1658 } 1659 } 1660 1663 static class Three implements CellKeyMaker { 1664 public long generate(int[] pos) { 1665 long l = pos[0]; 1666 l += (MAX_AXIS_SIZE_3 * (long) pos[1]); 1667 l += (MAX_AXIS_SIZE_3 * MAX_AXIS_SIZE_3 * (long) pos[2]); 1668 return l; 1669 } 1670 } 1671 1674 static class Four implements CellKeyMaker { 1675 public long generate(int[] pos) { 1676 long l = pos[0]; 1677 l += (MAX_AXIS_SIZE_4 * (long) pos[1]); 1678 l += (MAX_AXIS_SIZE_4 * MAX_AXIS_SIZE_4 * (long) pos[2]); 1679 l += (MAX_AXIS_SIZE_4 * MAX_AXIS_SIZE_4 * MAX_AXIS_SIZE_4 * (long) pos[3]); 1680 return l; 1681 } 1682 } 1683 1684 private final ObjectPool<CellInfo> cellInfoPool; 1685 private final CellKeyMaker cellKeyMaker; 1686 1687 CellInfoPool(int axisLength) { 1688 this.cellInfoPool = new ObjectPool<CellInfo>(); 1689 switch (axisLength) { 1690 case 0: 1691 this.cellKeyMaker = new Zero(); 1692 break; 1693 case 1: 1694 this.cellKeyMaker = new One(); 1695 break; 1696 case 2: 1697 this.cellKeyMaker = new Two(); 1698 break; 1699 case 3: 1700 this.cellKeyMaker = new Three(); 1701 break; 1702 case 4: 1703 this.cellKeyMaker = new Four(); 1704 break; 1705 default: 1706 throw new RuntimeException ( 1707 "Creating CellInfoPool with axisLength=" +axisLength); 1708 } 1709 } 1710 public int size() { 1711 return this.cellInfoPool.size(); 1712 } 1713 public void trimToSize() { 1714 this.cellInfoPool.trimToSize(); 1715 } 1716 public void clear() { 1717 this.cellInfoPool.clear(); 1718 } 1719 public CellInfo create(int[] pos) { 1720 long key = this.cellKeyMaker.generate(pos); 1721 return this.cellInfoPool.add(new CellInfo(key)); 1722 } 1723 public CellInfo lookup(int[] pos) { 1724 long key = this.cellKeyMaker.generate(pos); 1725 return this.cellInfoPool.add(new CellInfo(key)); 1726 } 1727 } 1728 1729 static Axis mergeAxes(Axis axis1, Axis axis2) { 1730 if (axis1 == null) { 1731 return axis2; 1732 } 1733 List <Position> pl1 = axis1.getPositions(); 1734 List <Position> pl2 = axis2.getPositions(); 1735 int arrayLen = -1; 1736 if (pl1 instanceof RolapAxis.PositionListBase) { 1737 if (pl1.size() == 0) { 1738 return axis2; 1739 } 1740 arrayLen = pl1.get(0).size(); 1741 } 1742 if (axis1 instanceof RolapAxis.SingleEmptyPosition) { 1743 return axis2; 1744 } 1745 if (axis1 instanceof RolapAxis.NoPosition) { 1746 return axis2; 1747 } 1748 if (pl2 instanceof RolapAxis.PositionListBase) { 1749 if (pl2.size() == 0) { 1750 return axis1; 1751 } 1752 arrayLen = pl2.get(0).size(); 1753 } 1754 if (axis2 instanceof RolapAxis.SingleEmptyPosition) { 1755 return axis1; 1756 } 1757 if (axis2 instanceof RolapAxis.NoPosition) { 1758 return axis1; 1759 } 1760 if (arrayLen == -1) { 1761 arrayLen = 0; 1763 for (Position p1: pl1) { 1764 for (Member m1: p1) { 1765 arrayLen++; 1766 } 1767 break; 1768 } 1769 } 1770 if (arrayLen == 1) { 1771 List <Member> list = new ArrayList <Member>(); 1773 for (Position p1: pl1) { 1774 for (Member m1: p1) { 1775 list.add(m1); 1776 } 1777 } 1778 for (Position p2: pl2) { 1779 for (Member m2: p2) { 1780 if (! list.contains(m2)) { 1781 list.add(m2); 1782 } 1783 } 1784 } 1785 return new RolapAxis.MemberList(list); 1786 } else { 1787 List <Member[]> list = new ArrayList <Member[]>(); 1789 for (Position p1: pl1) { 1790 Member[] members = new Member[arrayLen]; 1791 int i = 0; 1792 for (Member m1: p1) { 1793 members[i++] = m1; 1794 } 1795 list.add(members); 1796 } 1797 List <Member[]> extras = new ArrayList <Member[]>(); 1798 for (Position p2: pl2) { 1799 int i = 0; 1800 Member[] members = new Member[arrayLen]; 1801 for (Member m2: p2) { 1802 members[i++] = m2; 1803 } 1804 Iterator <Member[]> it1 = list.iterator(); 1805 boolean found = false; 1806 while (it1.hasNext()) { 1807 Member[] m1 = it1.next(); 1808 if (java.util.Arrays.equals(members, m1)) { 1809 found = true; 1810 break; 1811 } 1812 } 1813 if (! found) { 1814 extras.add(members); 1815 } 1816 } 1817 list.addAll(extras); 1818 return new RolapAxis.MemberArrayList(list); 1819 } 1820 } 1821} 1822 1823 | Popular Tags |