1 package com.calipso.reportgenerator.reportcalculator; 2 3 import com.calipso.reportgenerator.common.InfoException; 4 5 import java.util.*; 6 import java.io.Serializable ; 7 import java.io.ObjectOutputStream ; 8 import java.io.IOException ; 9 import java.io.ObjectInputStream ; 10 11 import com.calipso.reportgenerator.common.ReportMetricSpec; 12 import com.calipso.reportgenerator.common.LanguageTraslator; 13 import com.calipso.reportgenerator.reportdefinitions.types.CalculationType; 14 15 34 35 public class Cube implements Serializable , PivotClient { 36 private CubeDefinition definition; 37 private CubeQuery query; 38 private Object [] root; 39 private int arraySize; 40 private int metricsSize; 41 private LinkedList dimensionsCombinations; 42 private Set[] dimensionValues; 43 private MetricCalculationStrategy[] metricStrategies; 44 private MetricCalculationStrategy[] groupFooterStrategies; 45 private int dimensionsSize; 46 private int[] queryMetrics; 47 private static final int INVALID_DIMENSION = 999; 48 private Object [] metrics; 49 private Map excludedNodes = new HashMap(); 50 private static final String others = LanguageTraslator.traslate("404").intern(); private Pivot pivot; 52 private int fullDimensionsSize; 53 54 58 public int getDimensionsSize() { 59 return dimensionsSize; 60 } 61 62 70 private void initialize() { 71 metrics = definition.getMetrics(); 72 initAverageCountMetrics(); 73 metricsSize = getMetrics().length; 74 dimensionsSize = query.getDimensions().length; fullDimensionsSize = definition.getDimensions().length; 76 setArraySize(dimensionsSize + metricsSize); 77 initMetricStrategies(); 78 initGroupFooterStrategies(); 79 excludedNodes = new HashMap(); 80 } 81 82 86 private void initAverageCountMetrics() { 87 if(this.hasAverageMetrics()){ 88 ReportMetricSpec countMetric; 89 Object [] resultMetrics = new Object [(metrics.length * 2)]; 90 for (int i = 0; i < metrics.length; i++) { 91 resultMetrics[i] = metrics[i]; 92 countMetric = new ReportMetricSpec("Count" + i); 93 countMetric.setAggregateType(CalculationType.COUNT); 94 countMetric.setGroupFooterType(CalculationType.COUNT); 95 resultMetrics[metrics.length + i] = countMetric; 96 } 97 metrics = resultMetrics; 98 } 99 } 100 101 105 private boolean hasAverageMetrics() { 106 return getAverageMetricsIndexes().length > 0; 107 } 108 109 113 private int[] getAverageMetricsIndexes() { 114 Object [] metrics = definition.getMetrics(); 115 LinkedList indexes = new LinkedList(); 116 for (int i = 0; i < metrics.length; i++) { 117 Object metric = metrics[i]; 118 if(metric instanceof ReportMetricSpec){ 119 ReportMetricSpec metricSpec = (ReportMetricSpec)metric; 120 if((metricSpec.getAggregateType().getType() == CalculationType.AVERAGE_TYPE || 121 metricSpec.getGroupFooterType().getType() == CalculationType.AVERAGE_TYPE) && 122 isMetricInQuery(i)){ 123 indexes.add(new Integer (i)); 124 } 125 } 126 } 127 return toIntArray(indexes); 128 } 129 130 135 private boolean isMetricInQuery(int i) { 136 for (int j = 0; j < queryMetrics.length; j++) { 137 if(i + definition.getDimensions().length == queryMetrics[j]){ 138 return true; 139 } 140 } 141 return false; 142 } 143 144 147 private void initGroupFooterStrategies() { 148 Object [] metrics = getMetrics(); 149 groupFooterStrategies = new MetricCalculationStrategy[metrics.length]; 150 for (int i = 0; i < metrics.length; i++) { 151 Object metric = metrics[i]; 152 if(metric instanceof ReportMetricSpec){ 153 groupFooterStrategies[i] = MetricCalculationStrategy.getFooterStrategyFor((ReportMetricSpec)metric); 154 }else{ 155 groupFooterStrategies[i] = new SumStrategy(); 156 } 157 } 158 } 159 160 166 private Object [] getMetrics() { 167 return metrics; 168 } 169 170 173 private void initMetricStrategies() { 174 Object [] metrics = getMetrics(); 175 metricStrategies = new MetricCalculationStrategy[metrics.length]; 176 for (int i = 0; i < metrics.length; i++) { 177 Object metric = metrics[i]; 178 if(metric instanceof ReportMetricSpec){ 179 metricStrategies[i] = MetricCalculationStrategy.getMetricStrategyFor((ReportMetricSpec)metric); 180 }else{ 181 metricStrategies[i] = new SumStrategy(); 182 } 183 } 184 } 185 186 190 public CubeDefinition getDefinition() { 191 return definition; 192 } 193 194 198 public void setDefinition(CubeDefinition definition) { 199 this.definition = definition; 200 } 201 202 206 public CubeQuery getQuery() { 207 return query; 208 } 209 210 215 public void setQuery(CubeQuery query) throws InfoException { 216 try { 217 this.query = query; 218 queryMetrics = getQuery().getMetrics(); 219 setDimensionsCombinations(); 220 } 221 catch(Exception e){ 222 throw new InfoException(com.calipso.reportgenerator.common.LanguageTraslator.traslate("102"),e); 223 } 224 } 225 226 231 public Object [] getRoot() { 232 return root; 233 } 234 235 240 public void setRoot(Object [] root) { 241 this.root = root; 242 } 243 244 249 public int getArraySize() { 250 return arraySize; 251 } 252 253 258 public void setArraySize(int arraySize) { 259 this.arraySize = arraySize; 260 } 261 262 266 public int getMetricsSize() { 267 return metricsSize; 268 } 269 270 274 private void setDimensionsCombinations() throws InfoException { 275 dimensionsCombinations = new LinkedList(); 276 int[] cols = query.getColumns(); 277 int[] rows = query.getRows(); 278 for(int i=1; i <= rows.length; i++){ 279 int[] list = new int[i]; 280 for(int j=0; j < i; j++){ 281 list[j] = j; 282 } 283 dimensionsCombinations.add(list); 284 for(int z=1; z <= cols.length; z++){ 285 int[] withCol = new int[i + z]; 286 System.arraycopy(list, 0, withCol, 0, list.length); 287 for(int j=0; j < z; j++){ 288 withCol[j + i] = rows.length + j; 289 } 290 dimensionsCombinations.add(withCol); 291 } 292 } 293 if(rows.length != 0){ 294 for(int i=1; i <= cols.length; i++){ 295 int[] list = new int[i]; 296 for(int j=0; j < i; j++){ 297 list[j] = rows.length + j; 298 } 299 dimensionsCombinations.add(list); 300 } 301 } 302 336 } 337 338 public int[] getIntegerArray(int base, int length) { 339 int[] result = new int[length]; 340 for (int j=0, i = base; j < result.length; i++, j++) { 341 result[j] = i; 342 } 343 return result; 344 } 345 346 349 public void reset() { 350 initialize(); 351 root = null; 352 System.gc(); 353 root = newArray(); 354 } 355 356 357 363 private Object [] newArray() { 364 Object [] result; 365 int index; 366 result = new Object [arraySize]; 367 for (index = dimensionsSize; index < arraySize; index++) { 368 result[index] = SharedFloat.newFrom(Float.NaN); 369 } 370 371 return result; 372 } 373 374 378 public void fillWith(Object [] row) { 379 if (query.matches(row)) { 380 fillDimensionValues(row); 381 if (query.valuesEnabled(row)) { 382 row = shrinkRow(row); 383 basicFillWith(row); 384 } 385 }else if(query.isGroupExcludedValues()){ 386 if(query.otherFilterMatches()){ 387 row = shrinkRow(row); 388 fillExcludedValueNode(row); 389 } 390 } 391 } 392 393 398 private Object [] shrinkRow(Object [] row) { 399 int[] dimensions = query.getDimensions(); 400 int[] metrics = query.getMetrics(); 401 Object [] result = new Object [dimensions.length + metrics.length]; 402 int i = 0; 403 for (; i < dimensions.length; i++) { 404 result[i] = row[dimensions[i]]; 405 } 406 for (int j = 0; j < metrics.length; i++, j++) { 407 result[i] = row[metrics[j]]; 408 } 409 return result; 410 } 411 412 private void fillExcludedValueNode(Object [] aRow) { 413 Object [] measures; 414 Iterator iterator; 415 measures = valuesOfFrom(queryMetrics, aRow); 417 iterator = dimensionsCombinations.iterator(); 418 while (iterator.hasNext()) { 419 426 excludedAdd((int[]) iterator.next(), aRow, measures); 427 } 428 addTotal(measures, root, aRow); 429 } 430 431 private void excludedAdd(int[] dimensions, Object [] aRow, Object [] measures) { 432 Object [] node; 433 node = getExcludedNode(dimensions, aRow); 434 if(isLastLevel(dimensions)){ 435 addTo(measures, node, aRow); 436 }else{ 437 addTotal(measures, node, aRow); 438 } 439 } 440 441 private Object [] getExcludedNode(int[] dimensions, Object [] aRow) { 442 Object [] node = root; 443 for (int i = 0; i < dimensions.length; i++) { 444 int dimension = dimensions[i]; 445 if (dimension != INVALID_DIMENSION) { 446 if(node[dimension]==null){ 447 node[dimension] = new HashMap(); 448 } 449 Object value; 450 if(query.getExcludeGroupFilter().hasDimension(dimension) && !query.getExcludeGroupFilter().containsValue(dimension, aRow[dimension])){ 452 value = others; 453 }else{ 454 value = aRow[dimension]; 455 } 456 if(!((HashMap)node[dimension]).containsKey(value)){ 457 ((HashMap)node[dimension]).put(value, newArray()); 458 } 459 node = (Object [])((HashMap)node[dimension]).get(value); 460 } 461 } 462 476 return node; 477 } 478 479 private void addExcludedNode(Object [] excludedNode, int[] dimensions) { 480 Object [] node = root; 481 for (int i = 0; i < dimensions.length - 1; i++) { 482 int dimension = dimensions[i]; 483 if(dimension != INVALID_DIMENSION){ 484 HashMap map = (HashMap)node[dimension]; 485 if(map.containsKey(others)){ 486 node = (Object [])map.get(others); 487 } 488 } 489 } 490 Object child = node[dimensions[dimensions.length - 1]]; 491 if(child==null){ 492 child = new HashMap(); 493 node[dimensions[dimensions.length - 1]] = child; 494 } 495 ((Map)child).put(others, excludedNode); 496 } 497 498 private Object [] newExcludedNode(int[] dimensions) { 499 Object [] node = newArray(); 500 for (int i = 0; i < dimensions.length; i++) { 501 int dimension = dimensions[i]; 502 if(dimension != INVALID_DIMENSION){ 503 HashMap dict = new HashMap(); 504 Object [] subNode = getSubNode(dimensions, i+1); 505 dict.put(others, subNode); 506 node[dimension] = dict; 507 } 508 } 509 return node; 510 } 511 512 private Object [] getSubNode(int[] dimensions, int index) { 513 Object [] node = newArray(); 514 for (int j = index; j < dimensions.length; j++) { 515 int dimension = dimensions[j]; 516 if(dimension != INVALID_DIMENSION){ 517 HashMap dict = new HashMap(); 518 Object [] subNode = getSubNode(dimensions, j+1); 519 dict.put(others, subNode); 520 node[dimension] = dict; 521 } 522 } 523 return node; 524 } 525 526 530 protected void basicFillWith(Object [] aRow) { 531 Object [] measures; 532 Iterator iterator; 533 measures = valuesOfFrom(queryMetrics, aRow); 534 iterator = dimensionsCombinations.iterator(); 535 while (iterator.hasNext()) { 536 atFromAdd((int[]) iterator.next(), aRow, measures); 537 } 538 addTotal(measures, root, aRow); 539 } 540 541 private void fillDimensionValues(Object [] row) { 542 int[] dims; 543 dims = query.getRows(); 544 fillDimensionValuesFromArray(dims, row); 545 dims = query.getColumns(); 546 fillDimensionValuesFromArray(dims, row); 547 dims = query.getPages(); 548 fillDimensionValuesFromArray(dims, row); 549 } 550 551 private void fillDimensionValuesFromArray(int[] dimensions, Object [] row) { 552 for (int i = 0; i < dimensions.length; i++) { 553 int dim = dimensions[i]; 554 if (row[dim] != null){ 555 getDimensionValues()[dim].add(row[dim]); 556 } 557 } 558 } 559 560 561 566 private void addTo(Object [] measures, Object [] node, Object [] aRow) { 567 int index; 568 for (index = 0; index < metricsSize; index++) { 569 node[index + dimensionsSize] = (metricStrategies[index]).operate(node, index + dimensionsSize, measures[index], aRow); 570 } 572 } 573 574 580 private void atFromAdd(int[] dimensions, Object [] aRow, Object [] measures) { 581 Object [] node; 582 node = atFrom(dimensions, aRow); 583 if (node != null) { 584 if(isLastLevel(dimensions)){ 585 addTo(measures, node, aRow); 586 }else{ 587 addTotal(measures, node, aRow); 588 } 589 } 590 } 591 592 597 private void addTotal(Object [] measures, Object [] node, Object [] aRow) { 598 for (int index = 0; index < metricsSize; index++) { 599 node[index + dimensionsSize] = (groupFooterStrategies[index]).operate(node, index + dimensionsSize, measures[index], aRow); 600 } 601 } 602 603 608 private boolean isLastLevel(int[] dimensions) { 609 if(dimensions.length < getQuery().getDimensions().length){ 610 return false; 611 } 612 for (int i = 0; i < dimensions.length; i++) { 613 int dimension = dimensions[i]; 614 if(dimension == INVALID_DIMENSION){ 615 return false; 616 } 617 } 618 return true; 619 } 620 621 628 private Object [] atFrom(int[] dimensions, Object [] aRow) { 629 Object [] node; 630 int index; 631 int dimension; 632 int dimensionsLenght; 633 Object value; 634 635 node = root; 636 dimensionsLenght = dimensions.length; 637 for (index = 0; index < dimensionsLenght; index++) { 638 dimension = dimensions[index]; 639 if (dimension != INVALID_DIMENSION) { 640 value = aRow[dimension]; 641 if (value != null) { 642 node = atDimensionIn(value, dimension, node); 643 } 644 else { 645 return null; 646 } 647 } 648 } 649 return node; 650 } 651 652 658 private Object [] valuesOfFrom(int[] metrics, Object [] aRow) { 659 Object [] array = new Object [metricsSize]; 660 System.arraycopy(aRow, query.getDimensions().length, array, 0, query.getMetrics().length); 661 669 return array; 670 679 } 680 681 689 public float rowPercentageOf(int metric, int[] dimensions, Object [] values) { 690 float total; 691 692 total = rowTotalOf(metric, dimensions, values); 693 return percentageOf(metric, dimensions, values, total); 694 } 695 696 703 private float rowTotalOf(int metric, int[] dimensions, Object [] values) { 704 return totalOf(metric, dimensions, values, getQuery().getRows()); 705 } 706 707 715 public float columnPercentageOf(int metric, int[] dimensions, Object [] values) { 716 float total; 717 718 total = columnTotalOf(metric, dimensions, values); 719 return percentageOf(metric, dimensions, values, total); 720 } 721 722 723 730 private float columnTotalOf(int metric, int[] dimensions, Object [] values) { 731 return totalOf(metric, dimensions, values, getQuery().getColumns()); 732 } 733 734 735 743 private float totalOf(int metric, int[] dimensions, Object [] values, int[] rows) { 744 int dimension; 745 LinkedList selectedDimensions; 746 LinkedList selectedValues; 747 boolean found; 748 int row; 749 int dimensionsLenght; 750 int rowsLenght; 751 752 selectedDimensions = new LinkedList(); 753 selectedValues = new LinkedList(); 754 dimensionsLenght = dimensions.length; 755 for (int index = 0; index < dimensionsLenght; index++) { 756 dimension = dimensions[index]; 757 rowsLenght = rows.length; 758 found = false; 759 for (row = 0; (row < rowsLenght) && !found; row++) { 760 found = (rows[row] == dimension); 761 } 762 if (found) { 763 selectedDimensions.add(new Integer (dimension)); 764 selectedValues.add(values[index]); 765 } 766 } 767 768 return measureAtDimensionsValues(metric, toIntArray(selectedDimensions), selectedValues.toArray()); 769 } 770 771 776 private int[] toIntArray(LinkedList selectedIndexes) { 777 int[] result; 778 int index; 779 Iterator iterator; 780 int selectedDimensionsSize; 781 782 result = new int[selectedIndexes.size()]; 783 iterator = selectedIndexes.iterator(); 784 selectedDimensionsSize = selectedIndexes.size(); 785 for (index = 0; index < selectedDimensionsSize; index++) { 786 result[index] = ((Integer ) iterator.next()).intValue(); 787 } 788 return result; 789 } 790 791 799 private float percentageOf(int metric, int[] dimensions, Object [] values, float total) { 800 float value; 801 802 value = measureAtDimensionsValues(metric, dimensions, values); 803 if (total == 0) { 804 return 0; 805 } 806 else { 807 return value * 100 / total; 808 } 809 } 810 811 819 public float measureAtDimensionsValues(int metric, int[] dimensions, Object [] values) { 820 int metricIndex; 821 Object [] measures; 822 823 for (metricIndex = 0; metricIndex < getMetricsSize(); metricIndex++) { 824 if (getQuery().getMetrics()[metricIndex] == metric) { 825 break; 826 } 827 } 828 measures = measuresAtDimensionsValues(dimensions, values); 829 830 return ((SharedFloat) measures[metricIndex + dimensionsSize]).floatValue(); 831 } 832 833 840 public Object [] measuresAtDimensionsValues(int[] dimensions, Object [] values) { 841 Object [] node; 842 int index; 843 int dimensionsLenght; 844 845 node = root; 846 dimensionsLenght = dimensions.length; 847 for (index = 0; index < dimensionsLenght; index++) { 848 node = atDimensionIn(values[index], dimensions[index], node); 849 } 850 return node; 851 } 852 853 862 private Object [] atDimensionIn(Object value, int dimension, Object [] node) { 863 HashMap dict; 864 Object [] array; 865 Object o; 866 867 if ((node[dimension] instanceof HashMap)) { 868 dict = (HashMap) node[dimension]; 869 } 870 else { 871 node[dimension] = dict = new HashMap(); 872 } 873 o = dict.get(value); 874 if (o == null) { 875 array = newArray(); 876 dict.put(value, array); 877 return array; 878 } 879 else { 880 return (Object []) o; 881 } 882 } 883 884 889 public void writeTo(ObjectOutputStream stream) throws IOException { 890 stream.writeObject(this); 891 } 892 893 899 public void readFrom(ObjectInputStream stream, Pivot pivot) throws IOException , ClassNotFoundException { 900 Cube cube; 901 902 pivot = null; 903 cube = (Cube) stream.readObject(); 904 this.arraySize = cube.arraySize; 905 this.definition = cube.definition; 906 this.dimensionsCombinations = cube.dimensionsCombinations; 907 this.dimensionsSize = cube.dimensionsSize; 908 this.metricsSize = cube.metricsSize; 909 this.query = cube.query; 910 this.queryMetrics = cube.queryMetrics; 911 this.root = cube.root; 912 } 913 914 918 public void addDimension(int dimension) { 919 int[] dimensions; 920 int factor; 921 int[] list; 922 int queryDimensionsSize; 923 int combination; 924 String bits; 925 int bitsLenght; 926 int pos; 927 928 dimensions = getQuery().getDimensions(); 929 queryDimensionsSize = dimensions.length; 930 dimensionsCombinations = new LinkedList(); 931 for (combination = 1; combination <= (Math.pow(2, queryDimensionsSize) - 1); combination++) { 932 bits = Integer.toBinaryString(combination); 933 bitsLenght = bits.length(); 934 list = new int[bitsLenght]; 935 for (int index = 0; index < bitsLenght; index++) { 936 pos = bitsLenght - 1 - index; 937 factor = Character.digit(bits.charAt(pos), 10); 938 if (factor == 1) { 939 list[index] = factor * dimensions[index]; 940 } 941 else { 942 list[index] = INVALID_DIMENSION; 943 } 944 } 945 dimensionsCombinations.add(list); 946 } 947 } 948 949 953 public void fillWithNewDimensions(LinkedList newDimensions) { 954 964 } 966 967 971 public CubeIterator iterator() { 972 return CubeIterator.on(this); 973 } 974 975 981 public Iterator sortedIteratorFor(HashMap table, int dimensionIndex) { 982 988 TreeSet set; 989 set = new TreeSet(getQuery().entryComparatorFor(getQuery().getDimensions()[dimensionIndex])); 990 if (table!= null){ 991 set.addAll(table.entrySet()); 992 } 993 return set.iterator(); 994 } 996 997 1005 public Iterator valuesFor(int dimension, int[] previousDimensions, Object [] values) { 1006 Object [] node; 1007 HashMap table; 1008 1009 node = measuresAtDimensionsValues(previousDimensions, values); 1010 table = (HashMap) node[dimension]; 1011 1012 return sortedIteratorFor(table, dimension); 1013 } 1014 1015 public Set[] getDimensionValues() { 1016 if (dimensionValues == null) { 1017 dimensionValues = new TreeSet[getFullDimensionsSize()]; 1018 for (int i = 0; i < dimensionValues.length; i++) { 1019 dimensionValues[i] = new TreeSet(); 1020 } 1021 } 1022 return dimensionValues; 1023 } 1024 1025 private int getFullDimensionsSize() { 1026 return fullDimensionsSize; 1027 } 1028 1029 1033 public void afterFill() { 1034 if(emptyCube()){ 1035 root = newEmptyRoot(); 1036 }else{ 1037 int[] indexes = getAverageMetricsIndexes(); 1038 if(indexes.length > 0){ 1039 setAverageValues(root, indexes); 1040 } 1041 indexes = getMinMaxFootersIndexes(); 1042 if(indexes.length > 0){ 1043 int[] dimensionsOrder = getDimensionByGroupingOrder(); 1044 for (int i = 0; i < dimensionsOrder.length; i++) { 1045 setMinMaxFooters(root, indexes, dimensionsOrder, 0); 1046 } 1047 } 1048 indexes = getCountDistinctIndexes(); 1049 if(indexes.length > 0){ 1050 setNodesCountValues(root, indexes); 1051 } 1052 } 1053 if(!excludedNodes.isEmpty()){ 1054 Iterator it = dimensionsCombinations.iterator(); 1055 while (it.hasNext()) { 1056 int[] dimensions = (int[])it.next(); 1057 if(excludedNodes.containsKey(dimensions)) 1058 addExcludedNode((Object [])excludedNodes.get(dimensions), dimensions); 1059 } 1060 } 1061 System.gc(); 1062 System.gc(); 1063 System.gc(); 1064 System.gc(); 1065 System.gc(); 1066 } 1067 1068 private int[] getCountDistinctIndexes() { 1069 Object [] metrics = definition.getMetrics(); 1070 LinkedList indexes = new LinkedList(); 1071 for (int i = 0; i < metrics.length; i++) { 1072 Object metric = metrics[i]; 1073 if(metric instanceof ReportMetricSpec){ 1074 ReportMetricSpec metricSpec = (ReportMetricSpec)metric; 1075 if((metricSpec.getAggregateType().getType() == CalculationType.COUNT_DISTINCT_TYPE && isMetricInQuery(i))) { 1076 indexes.add(new Integer (i + dimensionsSize)); 1077 } 1078 } 1079 } 1080 return toIntArray(indexes); 1081 } 1082 1083 private void setNodesCountValues(Object [] node, int[] indexes) { 1084 for (int j = 0; j < indexes.length; j++) { 1085 int index = indexes[j]; 1086 node[index] = SharedFloat.newFrom(((Set)node[index]).size()); 1087 } 1088 for (int i = 0; i < dimensionsSize; i++) { 1089 if(node[i]!=null){ 1090 Map nodes = (Map)node[i]; 1091 Iterator it = nodes.values().iterator(); 1092 while (it.hasNext()) { 1093 Object [] childNode = (Object []) it.next(); 1094 setNodesCountValues(childNode, indexes); 1095 } 1096 } 1097 } 1098 } 1099 1100 1105 private int[] getDimensionByGroupingOrder() { 1106 int[] result = new int[query.getDimensions().length]; 1107 int[] queryColumns = query.getColumns(); 1108 int[] queryRows = query.getRows(); 1109 System.arraycopy(queryRows, 0, result, 0, queryRows.length); 1110 System.arraycopy(queryColumns, 0, result, queryRows.length, queryColumns.length); 1111 return result; 1112 } 1113 1114 1118 private Object [] newEmptyRoot() { 1119 Object [] result = new Object [arraySize]; 1120 for (int i = dimensionsSize; i < result.length; i++) { 1121 result[i] = SharedFloat.newFrom(0); 1122 } 1123 return result; 1124 } 1125 1126 1130 private boolean emptyCube() { 1131 int i = 0; 1132 for (; i < dimensionsSize; i++) { 1133 if(root[i] != null){ 1134 return false; 1135 } 1136 } 1137 for (; i < arraySize; i++){ 1138 if(!Float.isNaN(((SharedFloat)root[i]).floatValue())){ 1139 return false; 1140 } 1141 } 1142 return true; 1143 } 1144 1145 1155 private void setMinMaxFooters(Object [] node, int[] indexes, int[] modelIndexes, int modelIndex) { 1156 if(modelIndex + 1 < modelIndexes.length){ 1157 Iterator iterator = ((Map)node[modelIndexes[modelIndex]]).entrySet().iterator(); 1158 while (iterator.hasNext()) { 1159 Object [] childNode = (Object [])((Map.Entry) iterator.next()).getValue(); 1160 for(int childIndex = modelIndex + 1; childIndex < modelIndexes.length; childIndex++){ 1161 setMinMaxFooters(childNode, indexes, modelIndexes, childIndex); 1162 } 1163 } 1164 } 1165 int nodeIndex = getNodeIndex(node, modelIndexes); 1166 if(nodeIndex == modelIndexes[modelIndex]){ 1167 for (int i = 0; i < indexes.length; i++) { 1168 int index = indexes[i]; 1169 node[index] = obtainValue((Map)node[modelIndexes[modelIndex]], index); 1170 } 1171 } 1172 if(isInRows(nodeIndex) && getQuery().getColumns()!=null && getQuery().getColumns().length > 0){ 1174 setColumnValues(node, indexes, modelIndexes, nodeIndex); 1175 } 1176 } 1177 1178 1183 private boolean isInRows(int dimensionIndex) { 1184 for (int i = 0; i < getQuery().getRows().length; i++) { 1185 int row = getQuery().getRows()[i]; 1186 if(dimensionIndex==row){ 1187 return true; 1188 } 1189 } 1190 return false; 1191 } 1192 1193 1202 private void setColumnValues(Object [] node, int[] indexes, int[] modelIndexes, int maxNodeIndex) { 1203 for (int j = getQuery().getRows().length; j < modelIndexes.length; j++) { 1204 int modelIndex = modelIndexes[j]; 1205 Iterator iterator = ((Map)node[modelIndex]).entrySet().iterator(); 1206 while (iterator.hasNext()) { 1207 Map.Entry entry = (Map.Entry)iterator.next(); 1208 Vector dimensionsValues = new Vector(); 1209 dimensionsValues.add(entry.getKey()); 1210 Object [] childNode = (Object [])entry.getValue(); 1211 for (int i = 0; i < indexes.length; i++) { 1212 int footerIndex = indexes[i]; 1213 childNode[footerIndex] = getFooterValueFor(node, dimensionsValues, footerIndex, modelIndexes, j, maxNodeIndex); 1214 } 1215 setSubColumnValues(node, childNode, dimensionsValues, indexes, modelIndexes, j + 1, maxNodeIndex, j); 1216 } 1217 } 1218 } 1219 1220 1232 private void setSubColumnValues(Object [] node, Object [] childNode, Vector dimensionsValues, int[] indexes, int[] modelIndexes, int columnIndex, int maxNodeIndex, int startingColumnIndex) { 1233 if(columnIndex < modelIndexes.length){ 1234 Iterator iterator = ((Map)childNode[modelIndexes[columnIndex]]).entrySet().iterator(); 1235 while (iterator.hasNext()) { 1236 Map.Entry entry = (Map.Entry)iterator.next(); 1237 Vector clonedValues = (Vector)dimensionsValues.clone(); 1238 clonedValues.add(entry.getKey()); 1239 Object [] subNode = (Object [])entry.getValue(); 1240 for (int i = 0; i < indexes.length; i++) { 1241 int footerIndex = indexes[i]; 1242 subNode[footerIndex] = getFooterValueFor(node, clonedValues, footerIndex, modelIndexes, startingColumnIndex, maxNodeIndex); 1243 } 1244 setSubColumnValues(node, subNode, clonedValues, indexes, modelIndexes, columnIndex + 1, maxNodeIndex, startingColumnIndex); 1245 } 1246 } 1247 } 1248 1249 1259 private SharedFloat getFooterValueFor(Object [] node, Vector dimensionValues, int index, int[] modelIndexes, int columnIndex, int maxNodeIndex) { 1260 SharedFloat result = SharedFloat.newFrom(Float.NaN); 1261 Iterator iterator = ((Map)node[maxNodeIndex]).entrySet().iterator(); 1262 while (iterator.hasNext()) { 1263 Map.Entry entry = (Map.Entry)iterator.next(); 1264 Map subNodeValues = (Map)((Object [])entry.getValue())[modelIndexes[columnIndex]]; 1265 Object [] columnNode = (Object [])subNodeValues.get(dimensionValues.elementAt(0)); 1266 for (int i = 1; i < dimensionValues.size() && columnNode!=null && columnIndex + i < modelIndexes.length; i++) { 1267 Object dimensionValue = dimensionValues.elementAt(i); 1268 subNodeValues = (Map)columnNode[modelIndexes[columnIndex+i]]; 1269 columnNode = (Object [])subNodeValues.get(dimensionValue); 1270 } 1271 if(columnNode!=null){ 1272 result = (SharedFloat)groupFooterStrategies[index - dimensionsSize].operate(columnNode, index, result, null); 1273 }else{ 1274 result = (SharedFloat)groupFooterStrategies[index - dimensionsSize].operate(new Object []{result}, 0, null, null); 1276 } 1277 } 1278 return result; 1279 } 1280 1281 1288 private int getNodeIndex(Object [] node, int[] modelIndexes) { 1289 for (int i = 0; i < modelIndexes.length; i++) { 1290 int modelIndex = modelIndexes[i]; 1291 if(node[modelIndex]!=null){ 1292 return modelIndex; 1293 } 1294 } 1295 return modelIndexes[0]; 1296 } 1297 1298 1305 private SharedFloat obtainValue(Map nodeValues, int index) { 1306 SharedFloat result = SharedFloat.newFrom(Float.NaN); 1307 for (Iterator iterator = nodeValues.entrySet().iterator(); iterator.hasNext();) { 1308 Object [] node = (Object [])((Map.Entry) iterator.next()).getValue(); 1309 result = (SharedFloat)groupFooterStrategies[index - dimensionsSize].operate(node, index, result, null); 1310 } 1311 return result; 1312 } 1313 1314 1318 private int[] getMinMaxFootersIndexes() { 1319 Object [] metrics = definition.getMetrics(); 1320 LinkedList indexes = new LinkedList(); 1321 for (int i = 0; i < metrics.length; i++) { 1322 Object metric = metrics[i]; 1323 if(metric instanceof ReportMetricSpec){ 1324 ReportMetricSpec metricSpec = (ReportMetricSpec)metric; 1325 if((metricSpec.getGroupFooterType().getType() == CalculationType.MAX_TYPE || 1326 metricSpec.getGroupFooterType().getType() == CalculationType.MIN_TYPE) && 1327 isMetricInQuery(i)) { 1328 indexes.add(new Integer (i + dimensionsSize)); 1329 } 1330 } 1331 } 1332 return toIntArray(indexes); 1333 } 1334 1335 1340 private void setAverageValues(Object [] node, int[] indexes) { 1341 setAverageValueForNode(node, indexes); 1342 int[] dimensions = query.getDimensions(); 1343 for (int i = 0; i < dimensions.length; i++) { 1344 int dimension = dimensions[i]; 1345 if(node[dimension]!=null){ 1346 setAverageValueForChild((Map)node[dimension], indexes); 1347 } 1348 } 1349 } 1350 1351 1356 private void setAverageValueForChild(Map map, int[] indexes) { 1357 for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) { 1358 Map.Entry entry = (Map.Entry) iterator.next(); 1359 setAverageValues((Object [])entry.getValue(), indexes); 1360 } 1361 } 1362 1363 1368 private void setAverageValueForNode(Object [] node, int[] indexes) { 1369 for (int i = 0; i < indexes.length; i++) { 1370 int index = indexes[i]; 1371 if(isLastLevel(node) && metricStrategies[index] instanceof AverageStrategy){ 1372 node[index + dimensionsSize] = ((SharedFloat)node[index + dimensionsSize]).div((SharedFloat)node[index + dimensionsSize + metricsSize/2]); 1373 }else if(groupFooterStrategies[index] instanceof AverageStrategy){ 1374 node[index + dimensionsSize] = ((SharedFloat)node[index + dimensionsSize]).div((SharedFloat)node[index + dimensionsSize + metricsSize/2]); 1375 } 1376 } 1377 } 1378 1379 1384 private boolean isLastLevel(Object [] node) { 1385 for (int i = 0; i < node.length && i < getDimensionsSize(); i++) { 1386 if(node[i]!=null){ 1387 return false; 1388 } 1389 } 1390 return true; 1391 } 1392 1393 public Object [] getMetricsValuesAt(int[] dimensions, Object [] values) { 1394 Object [] node; 1395 int index; 1396 int dimensionsLenght; 1397 1398 node = root; 1399 dimensionsLenght = dimensions.length; 1400 for (index = 0; index < dimensionsLenght; index++) { 1401 node = atDimensionValueFor(values[index], dimensions[index], node); 1402 } 1403 return node; 1404 } 1405 1406 private Object [] atDimensionValueFor(Object value, int dimension, Object [] node) { 1407 HashMap dict; 1408 Object o; 1409 if(node==null){ 1410 return node; 1411 } 1412 if ((node[dimension] instanceof HashMap)) { 1413 dict = (HashMap) node[dimension]; 1414 } 1415 else { 1416 return null; 1417 } 1418 o = dict.get(value); 1419 return (Object []) o; 1420 } 1421 1422 public Set getDimensionValues(int index) throws InfoException { 1423 if(getDimensionValues()[index].isEmpty() && pivot!=null){ 1424 getDimensionValues()[index].addAll(pivot.getDimensionValues(index)); 1425 } 1426 return getDimensionValues()[index]; 1427 } 1428 1429 protected void setPivot(Pivot pivot) { 1430 this.pivot = pivot; 1431 } 1432 1433 public MetricCalculationStrategy[] getMetricStrategies() { 1434 return metricStrategies; 1435 } 1436 1437} 1438 | Popular Tags |