protected void createCrosstab() throws JRException { CollectedList[] collectedHeaders = new CollectedList[BucketingService.DIMENSIONS]; collectedHeaders[DIMENSION_ROW] = createHeadersList(DIMENSION_ROW, bucketValueMap, 0, false); BucketListMap collectedCols; if (allBuckets[0].computeTotal()) { BucketMap map = bucketValueMap; for (int i = 0; i < rowBucketCount; ++i) { map = (BucketMap) map.getTotalEntry().getValue(); } collectedCols = (BucketListMap) map; } else { collectedCols = createCollectBucketMap(rowBucketCount); collectCols(collectedCols, bucketValueMap); } collectedHeaders[DIMENSION_COLUMN] = createHeadersList(DIMENSION_COLUMN, collectedCols, 0, false); int rowBuckets = collectedHeaders[BucketingService.DIMENSION_ROW].span; int colBuckets = collectedHeaders[BucketingService.DIMENSION_COLUMN].span; int bucketMeasureCount = rowBuckets * colBuckets * origMeasureCount; checkBucketMeasureCount(bucketMeasureCount); colHeaders = createHeaders(BucketingService.DIMENSION_COLUMN, collectedHeaders); rowHeaders = createHeaders(BucketingService.DIMENSION_ROW, collectedHeaders); cells = new CrosstabCell[rowBuckets][colBuckets]; fillCells( collectedHeaders, bucketValueMap, 0, new int[] {0, 0}, new ArrayList(), new ArrayList()); }
/** Clears all the accumulated and computed data. */ public void clear() { bucketValueMap.clear(); columnBucketMap.clear(); processed = false; dataCount = 0; runningBucketMeasureCount = 0; }
/** * Returns the grand total measure values. * * @return the grand total measure values */ public MeasureValue[] getGrandTotals() { BucketMap map = bucketValueMap; for (int i = 0; map != null && i < allBuckets.length - 1; ++i) { map = (BucketMap) map.getTotalEntry().getValue(); } return map == null ? null : (MeasureValue[]) map.getTotalEntry().getValue(); }
/** * Returns the measure values for a set of bucket values. * * @param bucketValues the bucket values * @return the measure values corresponding to the bucket values */ public MeasureValue[] getMeasureValues(Bucket[] bucketValues) { BucketMap map = bucketValueMap; for (int i = 0; map != null && i < allBuckets.length - 1; ++i) { map = (BucketMap) map.get(bucketValues[i]); } return map == null ? null : (MeasureValue[]) map.get(bucketValues[allBuckets.length - 1]); }
/** * Feeds data to the engine. * * @param bucketValues the bucket values * @param measureValues the measure values * @throws JRException */ public void addData(Object[] bucketValues, Object[] measureValues) throws JRException { if (processed) { throw new JRException(EXCEPTION_MESSAGE_KEY_BUCKET_DATA_PROCESSED, (Object[]) null); } ++dataCount; Bucket[] bucketVals = getBucketValues(bucketValues); MeasureValue[] values = bucketValueMap.insertMeasureValues(bucketVals, true, 0); for (int i = 0; i < measures.length; ++i) { Object measureValue = measureValues[measureIndexes[i]]; values[i].addValue(measureValue); } // collect column bucket values columnBucketMap.insertMeasureValues(bucketVals, false, rowBucketCount); }
protected void computeColumnTotal(BucketMap bucketMap) throws JRException { MeasureValue[] totals = initMeasureValues(); for (Iterator it = bucketMap.entryIterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); for (int i = bucketMap.level + 1; i < allBuckets.length; ++i) { entry = ((BucketMap) entry.getValue()).getTotalEntry(); } sumVals(totals, (MeasureValue[]) entry.getValue()); } for (int i = bucketMap.level + 1; i < allBuckets.length; ++i) { bucketMap = bucketMap.addTotalNextMap(); } bucketMap.addTotalEntry(totals); }
protected void computeRowTotals(BucketMap bucketMap) throws JRException { BucketMapMap totals = createRowTotalsBucketMap(); for (Iterator<Map.Entry<Bucket, Object>> it = bucketMap.entryIterator(); it.hasNext(); ) { Map.Entry<Bucket, Object> entry = it.next(); for (int i = bucketMap.level + 1; i < rowBucketCount; ++i) { entry = ((BucketMap) entry.getValue()).getTotalEntry(); } totals.sumValues((BucketMap) entry.getValue()); } BucketMap totalBucketMap = bucketMap; for (int i = bucketMap.level + 1; i < rowBucketCount; ++i) { totalBucketMap = totalBucketMap.addTotalNextMap(); } totalBucketMap.addTotalEntry(totals); }
protected void computeRowTotals(BucketMap bucketMap) throws JRException { BucketListMap totals = createCollectBucketMap(rowBucketCount); for (Iterator it = bucketMap.entryIterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); for (int i = bucketMap.level + 1; i < rowBucketCount; ++i) { entry = ((BucketMap) entry.getValue()).getTotalEntry(); } totals.collectVals((BucketMap) entry.getValue(), true); } BucketMap totalBucketMap = bucketMap; for (int i = bucketMap.level + 1; i < rowBucketCount; ++i) { totalBucketMap = totalBucketMap.addTotalNextMap(); } totalBucketMap.addTotalEntry(totals); }
protected void collectCols(BucketListMap collectedCols, BucketMap bucketMap) throws JRException { if (allBuckets[bucketMap.level].computeTotal()) { BucketMap map = bucketMap; for (int i = bucketMap.level; i < rowBucketCount; ++i) { map = (BucketMap) map.getTotalEntry().getValue(); } collectedCols.collectVals(map, false); return; } for (Iterator it = bucketMap.entryIterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); BucketMap nextMap = (BucketMap) entry.getValue(); if (bucketMap.level == rowBucketCount - 1) { collectedCols.collectVals(nextMap, false); } else { collectCols(collectedCols, nextMap); } } }
void collectVals(BucketMap map, boolean sum) throws JRException { ListIterator totalIt = entries.listIterator(); MapEntry totalItEntry = totalIt.hasNext() ? (MapEntry) totalIt.next() : null; Iterator it = map.entryIterator(); Map.Entry entry = it.hasNext() ? (Map.Entry) it.next() : null; while (entry != null) { Bucket key = (Bucket) entry.getKey(); int compare = totalItEntry == null ? -1 : key.compareTo(totalItEntry.key); if (compare <= 0) { Object addVal = null; if (last) { if (sum) { MeasureValue[] totalVals = compare == 0 ? (MeasureValue[]) totalItEntry.value : null; if (totalVals == null) { totalVals = initMeasureValues(); addVal = totalVals; } sumVals(totalVals, (MeasureValue[]) entry.getValue()); } } else { BucketListMap nextTotals = compare == 0 ? (BucketListMap) totalItEntry.value : null; if (nextTotals == null) { nextTotals = createCollectBucketMap(level + 1); addVal = nextTotals; } nextTotals.collectVals((BucketMap) entry.getValue(), sum); } if (compare < 0) { if (totalItEntry != null) { totalIt.previous(); } totalIt.add(new MapEntry(key, addVal)); if (totalItEntry != null) { totalIt.next(); } } entry = it.hasNext() ? (Map.Entry) it.next() : null; } if (compare >= 0) { totalItEntry = totalIt.hasNext() ? (MapEntry) totalIt.next() : null; } } }
protected MeasureValue[][][] retrieveTotals(List vals, List bucketMaps) { MeasureValue[][][] totals = new MeasureValue[rowBucketCount + 1][colBucketCount + 1][]; for (int row = rowRetrTotalMax; row >= rowRetrTotalMin; --row) { if (!rowRetrTotals[row]) { continue; } BucketMap rowMap = (BucketMap) bucketMaps.get(row); for (int i = row; rowMap != null && i < rowBucketCount; ++i) { Entry totalEntry = rowMap.getTotalEntry(); rowMap = totalEntry == null ? null : (BucketMap) totalEntry.getValue(); } for (int col = 0; col <= rowRetrColMax[row]; ++col) { BucketMap colMap = rowMap; if (col < colBucketCount - 1) { if (row == rowBucketCount) { rowMap = (BucketMap) bucketMaps.get(rowBucketCount + col + 1); } else if (rowMap != null) { rowMap = (BucketMap) rowMap.get((Bucket) vals.get(rowBucketCount + col)); } } if (!retrieveTotal[row][col]) { continue; } for (int i = col + 1; colMap != null && i < colBucketCount; ++i) { colMap = (BucketMap) colMap.getTotalEntry().getValue(); } if (colMap != null) { if (col == colBucketCount) { MeasureValue[] measureValues = (MeasureValue[]) colMap.get((Bucket) vals.get(rowBucketCount + colBucketCount - 1)); totals[row][col] = getUserMeasureValues(measureValues); } else { Map.Entry totalEntry = colMap.getTotalEntry(); if (totalEntry != null) { MeasureValue[] totalValues = (MeasureValue[]) totalEntry.getValue(); totals[row][col] = getUserMeasureValues(totalValues); } } } if (totals[row][col] == null) { totals[row][col] = zeroUserMeasureValues; } } } return totals; }
/** * Feeds data to the engine. * * @param bucketValues the bucket values * @param measureValues the measure values * @throws JRException */ public void addData(Object[] bucketValues, Object[] measureValues) throws JRException { if (processed) { throw new JRException("Crosstab data has already been processed."); } ++dataCount; Bucket[] bucketVals = getBucketValues(bucketValues); MeasureValue[] values = bucketValueMap.insertMeasureValues(bucketVals); for (int i = 0; i < measures.length; ++i) { values[i].addValue(measureValues[measureIndexes[i]]); } }
void sumValues(BucketMap bucketMap) throws JRException { for (Iterator<Map.Entry<Bucket, Object>> it = bucketMap.entryIterator(); it.hasNext(); ) { Map.Entry<Bucket, Object> entry = it.next(); // find the total entry that matches the map entry. // the total map is should contain all collected entries // FIXME optimize this for sorted maps where we can assume that the order is the same Object value = get(entry.getKey()); if (last) { // last level, sum the values sumVals((MeasureValue[]) value, (MeasureValue[]) entry.getValue()); } else { // go to the next level ((BucketMapMap) value).sumValues((BucketMap) entry.getValue()); } } }
void copyEntries(BucketMap bucketMap) { for (Iterator<Entry<Bucket, Object>> bucketIterator = bucketMap.entryIterator(); bucketIterator.hasNext(); ) { Entry<Bucket, Object> bucketEntry = bucketIterator.next(); Bucket bucketKey = bucketEntry.getKey(); Object copyBucketValue; if (bucketMap.last) { copyBucketValue = initMeasureValues(); } else { BucketMap bucketSubMap = (BucketMap) bucketEntry.getValue(); BucketMapMap copyBucketSubMap = new BucketMapMap(level + 1, false); copyBucketSubMap.copyEntries(bucketSubMap); copyBucketValue = copyBucketSubMap; } map.put(bucketKey, copyBucketValue); } }
protected CollectedList createHeadersList( byte dimension, BucketMap bucketMap, int level, boolean total) { CollectedList headers = new CollectedList(); for (Iterator it = bucketMap.entryIterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); Bucket bucketValue = (Bucket) entry.getKey(); boolean totalBucket = bucketValue.isTotal(); byte totalPosition = allBuckets[bucketMap.level].getTotalPosition(); boolean createHeader = !totalBucket || total || totalPosition != BucketDefinition.TOTAL_POSITION_NONE; if (createHeader) { CollectedList nextHeaders; if (level + 1 < buckets[dimension].length) { BucketMap nextMap = (BucketMap) entry.getValue(); nextHeaders = createHeadersList(dimension, nextMap, level + 1, total || totalBucket); } else { nextHeaders = new CollectedList(); nextHeaders.span = 1; } nextHeaders.key = bucketValue; if (totalBucket) { if (totalPosition == BucketDefinition.TOTAL_POSITION_START) { headers.addFirst(nextHeaders); } else { headers.add(nextHeaders); } } else { headers.add(nextHeaders); } } } if (headers.span == 0) { headers.span = 1; } return headers; }
protected void computeTotals(BucketMap bucketMap) throws JRException { byte dimension = bucketMap.level < rowBucketCount ? DIMENSION_ROW : DIMENSION_COLUMN; if (dimension == DIMENSION_COLUMN && !allBuckets[allBuckets.length - 1].computeTotal()) { return; } if (!bucketMap.last) { for (Iterator it = bucketMap.entryIterator(); it.hasNext(); ) { Map.Entry entry = (Map.Entry) it.next(); computeTotals((BucketMap) entry.getValue()); } } if (allBuckets[bucketMap.level].computeTotal()) { if (dimension == DIMENSION_COLUMN) { computeColumnTotal(bucketMap); } else { computeRowTotals(bucketMap); } } }
protected void fillCells( CollectedList[] collectedHeaders, BucketMap bucketMap, int level, int[] pos, List vals, List bucketMaps) { bucketMaps.add(bucketMap); byte dimension = level < rowBucketCount ? DIMENSION_ROW : DIMENSION_COLUMN; boolean last = level == allBuckets.length - 1; CollectedList[] nextCollected = null; if (!last) { nextCollected = new CollectedList[DIMENSIONS]; for (int d = 0; d < DIMENSIONS; ++d) { if (d != dimension) { nextCollected[d] = collectedHeaders[d]; } } } boolean incrementRow = level == buckets[BucketingService.DIMENSION_ROW].length - 1; CollectedList collectedList = collectedHeaders[dimension]; Iterator bucketIt = bucketMap == null ? null : bucketMap.entryIterator(); Map.Entry bucketItEntry = bucketIt != null && bucketIt.hasNext() ? (Map.Entry) bucketIt.next() : null; for (Iterator it = collectedList.iterator(); it.hasNext(); ) { CollectedList list = (CollectedList) it.next(); Map.Entry bucketEntry = null; if (list.key.isTotal()) { if (bucketMap != null) { bucketEntry = bucketMap.getTotalEntry(); } } else { if (bucketItEntry != null && bucketItEntry.getKey().equals(list.key)) { bucketEntry = bucketItEntry; bucketItEntry = bucketIt.hasNext() ? (Map.Entry) bucketIt.next() : null; } } vals.add(list.key); if (last) { fillCell(pos, vals, bucketMaps, bucketEntry); } else { nextCollected[dimension] = list; BucketMap nextMap = bucketEntry == null ? null : (BucketMap) bucketEntry.getValue(); fillCells(nextCollected, nextMap, level + 1, pos, vals, bucketMaps); } vals.remove(vals.size() - 1); if (incrementRow) { ++pos[0]; pos[1] = 0; } } bucketMaps.remove(bucketMaps.size() - 1); }