first commit

This commit is contained in:
2025-07-28 13:56:49 +05:30
commit e9eb805edb
3438 changed files with 520990 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
package net.sf.jasperreports.crosstabs.fill;
import java.util.Map;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.fill.JREvaluator;
import net.sf.jasperreports.engine.fill.JRFillExpressionEvaluator;
public class JRCrosstabExpressionEvaluator implements JRFillExpressionEvaluator {
private final JREvaluator evaluator;
public JRCrosstabExpressionEvaluator(JREvaluator evaluator) {
this.evaluator = evaluator;
}
public Object evaluate(JRExpression expression, byte evaluationType) throws JRException {
if (evaluationType != 3)
throw new JRException("The crosstab evaluator doesn't support old or estimated expression evaluation.");
return this.evaluator.evaluate(expression);
}
public void init(Map parametersMap, Map variablesMap, byte whenResourceMissingType) throws JRException {
this.evaluator.init(parametersMap, null, variablesMap, whenResourceMissingType);
}
}

View File

@@ -0,0 +1,46 @@
package net.sf.jasperreports.crosstabs.fill;
import net.sf.jasperreports.crosstabs.JRCellContents;
import net.sf.jasperreports.crosstabs.JRCrosstabCell;
import net.sf.jasperreports.engine.fill.JRFillCellContents;
import net.sf.jasperreports.engine.fill.JRFillObjectFactory;
public class JRFillCrosstabCell implements JRCrosstabCell {
private JRCrosstabCell parentCell;
protected JRFillCellContents contents;
public JRFillCrosstabCell(JRCrosstabCell cell, JRFillObjectFactory factory) {
factory.put(cell, this);
this.parentCell = cell;
this.contents = factory.getCell(cell.getContents());
}
public String getRowTotalGroup() {
return this.parentCell.getRowTotalGroup();
}
public String getColumnTotalGroup() {
return this.parentCell.getColumnTotalGroup();
}
public JRCellContents getContents() {
return (JRCellContents)this.contents;
}
public JRFillCellContents getFillContents() {
return this.contents;
}
public Integer getWidth() {
return this.parentCell.getWidth();
}
public Integer getHeight() {
return this.parentCell.getHeight();
}
public Object clone() {
return null;
}
}

View File

@@ -0,0 +1,19 @@
package net.sf.jasperreports.crosstabs.fill;
import net.sf.jasperreports.crosstabs.JRCrosstabColumnGroup;
import net.sf.jasperreports.crosstabs.JRCrosstabGroup;
import net.sf.jasperreports.engine.fill.JRFillObjectFactory;
public class JRFillCrosstabColumnGroup extends JRFillCrosstabGroup implements JRCrosstabColumnGroup {
public JRFillCrosstabColumnGroup(JRCrosstabColumnGroup group, JRFillObjectFactory factory) {
super((JRCrosstabGroup)group, factory);
}
public byte getPosition() {
return ((JRCrosstabColumnGroup)this.parentGroup).getPosition();
}
public int getHeight() {
return ((JRCrosstabColumnGroup)this.parentGroup).getHeight();
}
}

View File

@@ -0,0 +1,71 @@
package net.sf.jasperreports.crosstabs.fill;
import net.sf.jasperreports.crosstabs.JRCellContents;
import net.sf.jasperreports.crosstabs.JRCrosstabBucket;
import net.sf.jasperreports.crosstabs.JRCrosstabGroup;
import net.sf.jasperreports.engine.JRVariable;
import net.sf.jasperreports.engine.fill.JRFillCellContents;
import net.sf.jasperreports.engine.fill.JRFillObjectFactory;
import net.sf.jasperreports.engine.fill.JRFillVariable;
public abstract class JRFillCrosstabGroup implements JRCrosstabGroup {
protected JRCrosstabGroup parentGroup;
protected JRFillCellContents header;
protected JRFillCellContents totalHeader;
protected JRFillVariable variable;
public JRFillCrosstabGroup(JRCrosstabGroup group, JRFillObjectFactory factory) {
factory.put(group, this);
this.parentGroup = group;
this.header = factory.getCell(group.getHeader());
this.totalHeader = factory.getCell(group.getTotalHeader());
this.variable = factory.getVariable(group.getVariable());
}
public String getName() {
return this.parentGroup.getName();
}
public byte getTotalPosition() {
return this.parentGroup.getTotalPosition();
}
public boolean hasTotal() {
return this.parentGroup.hasTotal();
}
public JRCrosstabBucket getBucket() {
return this.parentGroup.getBucket();
}
public JRCellContents getHeader() {
return (JRCellContents)this.header;
}
public JRCellContents getTotalHeader() {
return (JRCellContents)this.totalHeader;
}
public JRFillCellContents getFillHeader() {
return this.header;
}
public JRFillCellContents getFillTotalHeader() {
return this.totalHeader;
}
public JRVariable getVariable() {
return (JRVariable)this.variable;
}
public JRFillVariable getFillVariable() {
return this.variable;
}
public Object clone() {
return null;
}
}

View File

@@ -0,0 +1,109 @@
package net.sf.jasperreports.crosstabs.fill;
import net.sf.jasperreports.crosstabs.JRCrosstabMeasure;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRVariable;
import net.sf.jasperreports.engine.fill.JRDefaultIncrementerFactory;
import net.sf.jasperreports.engine.fill.JRExtendedIncrementerFactory;
import net.sf.jasperreports.engine.fill.JRFillObjectFactory;
import net.sf.jasperreports.engine.fill.JRFillVariable;
import net.sf.jasperreports.engine.fill.JRIncrementerFactoryCache;
public class JRFillCrosstabMeasure implements JRCrosstabMeasure {
protected JRCrosstabMeasure parentMeasure;
protected JRFillVariable variable;
protected JRExtendedIncrementerFactory incrementerFactory;
protected JRPercentageCalculator percentageCalculator;
public JRFillCrosstabMeasure(JRCrosstabMeasure measure, JRFillObjectFactory factory) {
factory.put(measure, this);
this.parentMeasure = measure;
this.variable = factory.getVariable(measure.getVariable());
this.incrementerFactory = createIncrementerFactory();
this.percentageCalculator = createPercentageCalculator();
}
public String getName() {
return this.parentMeasure.getName();
}
public String getValueClassName() {
return this.parentMeasure.getValueClassName();
}
public Class getValueClass() {
return this.parentMeasure.getValueClass();
}
public JRExpression getValueExpression() {
return this.parentMeasure.getValueExpression();
}
public byte getCalculation() {
return this.parentMeasure.getCalculation();
}
public String getIncrementerFactoryClassName() {
return this.parentMeasure.getIncrementerFactoryClassName();
}
public Class getIncrementerFactoryClass() {
return this.parentMeasure.getIncrementerFactoryClass();
}
public byte getPercentageOfType() {
return this.parentMeasure.getPercentageOfType();
}
public JRVariable getVariable() {
return (JRVariable)this.variable;
}
public JRFillVariable getFillVariable() {
return this.variable;
}
public JRExtendedIncrementerFactory getIncrementerFactory() {
return this.incrementerFactory;
}
public JRPercentageCalculator getPercentageCalculator() {
return this.percentageCalculator;
}
private JRExtendedIncrementerFactory createIncrementerFactory() {
JRExtendedIncrementerFactory incrFactory;
String incrementerFactoryClassName = getIncrementerFactoryClassName();
if (incrementerFactoryClassName == null) {
incrFactory = JRDefaultIncrementerFactory.getFactory(getValueClass());
} else {
incrFactory = (JRExtendedIncrementerFactory)JRIncrementerFactoryCache.getInstance(getIncrementerFactoryClass());
}
return incrFactory;
}
public JRPercentageCalculator createPercentageCalculator() {
JRPercentageCalculator percentageCalc;
if (getPercentageOfType() == 1) {
percentageCalc = JRPercentageCalculatorFactory.getPercentageCalculator(getPercentageCalculatorClass(), getValueClass());
} else {
percentageCalc = null;
}
return percentageCalc;
}
public String getPercentageCalculatorClassName() {
return this.parentMeasure.getPercentageCalculatorClassName();
}
public Class getPercentageCalculatorClass() {
return this.parentMeasure.getPercentageCalculatorClass();
}
public Object clone() {
return null;
}
}

View File

@@ -0,0 +1,20 @@
package net.sf.jasperreports.crosstabs.fill;
import net.sf.jasperreports.crosstabs.JRCrosstabParameter;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.fill.JRFillObjectFactory;
import net.sf.jasperreports.engine.fill.JRFillParameter;
public class JRFillCrosstabParameter extends JRFillParameter implements JRCrosstabParameter {
private JRCrosstabParameter parentParameter;
public JRFillCrosstabParameter(JRCrosstabParameter parameter, JRFillObjectFactory factory) {
super((JRParameter)parameter, factory);
this.parentParameter = parameter;
}
public JRExpression getExpression() {
return this.parentParameter.getExpression();
}
}

View File

@@ -0,0 +1,19 @@
package net.sf.jasperreports.crosstabs.fill;
import net.sf.jasperreports.crosstabs.JRCrosstabGroup;
import net.sf.jasperreports.crosstabs.JRCrosstabRowGroup;
import net.sf.jasperreports.engine.fill.JRFillObjectFactory;
public class JRFillCrosstabRowGroup extends JRFillCrosstabGroup implements JRCrosstabRowGroup {
public JRFillCrosstabRowGroup(JRCrosstabRowGroup group, JRFillObjectFactory factory) {
super((JRCrosstabGroup)group, factory);
}
public byte getPosition() {
return ((JRCrosstabRowGroup)this.parentGroup).getPosition();
}
public int getWidth() {
return ((JRCrosstabRowGroup)this.parentGroup).getWidth();
}
}

View File

@@ -0,0 +1,7 @@
package net.sf.jasperreports.crosstabs.fill;
import net.sf.jasperreports.engine.fill.JRCalculable;
public interface JRPercentageCalculator {
Object calculatePercentage(JRCalculable paramJRCalculable1, JRCalculable paramJRCalculable2);
}

View File

@@ -0,0 +1,142 @@
package net.sf.jasperreports.crosstabs.fill;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.fill.JRCalculable;
public class JRPercentageCalculatorFactory {
private static final Map builtInCalculators = new HashMap();
static {
builtInCalculators.put(Float.class.getName(), new FloatPercentageCalculator());
builtInCalculators.put(Double.class.getName(), new DoublePercentageCalculator());
builtInCalculators.put(Integer.class.getName(), new IntegerPercentageCalculator());
builtInCalculators.put(Long.class.getName(), new LongPercentageCalculator());
builtInCalculators.put(Short.class.getName(), new ShortPercentageCalculator());
builtInCalculators.put(Byte.class.getName(), new BytePercentageCalculator());
builtInCalculators.put(BigDecimal.class.getName(), new BigDecimalPercentageCalculator());
builtInCalculators.put(BigInteger.class.getName(), new BigIntegerPercentageCalculator());
}
private static final Map cachedCalculators = new HashMap();
public static boolean hasBuiltInCalculator(Class valueClass) {
return builtInCalculators.containsKey(valueClass.getName());
}
public static JRPercentageCalculator getPercentageCalculator(Class percentageCalculatorClass, Class valueClass) {
JRPercentageCalculator calculator;
if (percentageCalculatorClass == null) {
calculator = (JRPercentageCalculator)builtInCalculators.get(valueClass.getName());
if (calculator == null)
throw new JRRuntimeException("Measure with type " + valueClass.getName() + " should specify a percentage calculator class.");
} else {
calculator = (JRPercentageCalculator)cachedCalculators.get(percentageCalculatorClass.getName());
if (calculator == null)
try {
calculator = percentageCalculatorClass.newInstance();
cachedCalculators.put(percentageCalculatorClass.getName(), calculator);
} catch (InstantiationException e) {
throw new JRRuntimeException("Error while creating percentage calculator instance of " + percentageCalculatorClass + ".", e);
} catch (IllegalAccessException e) {
throw new JRRuntimeException("Error while creating percentage calculator instance of " + percentageCalculatorClass + ".", e);
}
}
return calculator;
}
public static class BytePercentageCalculator implements JRPercentageCalculator {
public Object calculatePercentage(JRCalculable value, JRCalculable total) {
Byte totalVal = (Byte)total.getValue();
Byte val = (Byte)value.getValue();
byte percentage = 0;
if (totalVal != null && totalVal.byteValue() != 0)
percentage = (byte)(100 * val.byteValue() / totalVal.byteValue());
return new Byte(percentage);
}
}
public static class ShortPercentageCalculator implements JRPercentageCalculator {
public Object calculatePercentage(JRCalculable value, JRCalculable total) {
Short totalVal = (Short)total.getValue();
Short val = (Short)value.getValue();
short percentage = 0;
if (totalVal != null && totalVal.shortValue() != 0)
percentage = (short)(100 * val.shortValue() / totalVal.shortValue());
return new Short(percentage);
}
}
public static class IntegerPercentageCalculator implements JRPercentageCalculator {
public Object calculatePercentage(JRCalculable value, JRCalculable total) {
Integer totalVal = (Integer)total.getValue();
Integer val = (Integer)value.getValue();
int percentage = 0;
if (totalVal != null && totalVal.intValue() != 0)
percentage = 100 * val.intValue() / totalVal.intValue();
return new Integer(percentage);
}
}
public static class LongPercentageCalculator implements JRPercentageCalculator {
public Object calculatePercentage(JRCalculable value, JRCalculable total) {
Long totalVal = (Long)total.getValue();
Long val = (Long)value.getValue();
long percentage = 0L;
if (totalVal != null && totalVal.longValue() != 0L)
percentage = 100L * val.longValue() / totalVal.longValue();
return new Long(percentage);
}
}
public static class FloatPercentageCalculator implements JRPercentageCalculator {
public Object calculatePercentage(JRCalculable value, JRCalculable total) {
Float totalVal = (Float)total.getValue();
Float val = (Float)value.getValue();
float percentage = 0.0F;
if (totalVal != null && totalVal.floatValue() != 0.0F)
percentage = 100.0F * val.floatValue() / totalVal.floatValue();
return new Float(percentage);
}
}
public static class DoublePercentageCalculator implements JRPercentageCalculator {
public Object calculatePercentage(JRCalculable value, JRCalculable total) {
Double totalVal = (Double)total.getValue();
Double val = (Double)value.getValue();
double percentage = 0.0D;
if (totalVal != null && totalVal.doubleValue() != 0.0D)
percentage = 100.0D * val.doubleValue() / totalVal.doubleValue();
return new Double(percentage);
}
}
public static class BigDecimalPercentageCalculator implements JRPercentageCalculator {
public Object calculatePercentage(JRCalculable value, JRCalculable total) {
BigDecimal percentage, totalVal = (BigDecimal)total.getValue();
BigDecimal val = (BigDecimal)value.getValue();
if (totalVal != null && totalVal.doubleValue() != 0.0D) {
percentage = val.multiply(BigDecimal.valueOf(100L)).divide(totalVal, 4);
} else {
percentage = BigDecimal.valueOf(0L);
}
return percentage;
}
}
public static class BigIntegerPercentageCalculator implements JRPercentageCalculator {
public Object calculatePercentage(JRCalculable value, JRCalculable total) {
BigInteger percentage, totalVal = (BigInteger)total.getValue();
BigInteger val = (BigInteger)value.getValue();
if (totalVal != null && totalVal.doubleValue() != 0.0D) {
percentage = val.multiply(BigInteger.valueOf(100L)).divide(totalVal);
} else {
percentage = BigInteger.valueOf(0L);
}
return percentage;
}
}
}

View File

@@ -0,0 +1,139 @@
package net.sf.jasperreports.crosstabs.fill.calculation;
import java.util.Comparator;
import net.sf.jasperreports.engine.JRException;
import org.apache.commons.collections.comparators.ReverseComparator;
public class BucketDefinition {
public static final byte ORDER_ASCENDING = 1;
public static final byte ORDER_DESCENDING = 2;
public static final byte TOTAL_POSITION_NONE = 0;
public static final byte TOTAL_POSITION_START = 1;
public static final byte TOTAL_POSITION_END = 2;
protected static final byte VALUE_TYPE_VALUE = 0;
protected static final byte VALUE_TYPE_NULL = 1;
protected static final byte VALUE_TYPE_TOTAL = 2;
protected final Bucket VALUE_TOTAL = new Bucket((byte)2);
protected final Bucket VALUE_NULL = new Bucket((byte)1);
protected final Comparator comparator;
private final byte totalPosition;
private boolean computeTotal;
public BucketDefinition(Class valueClass, Comparator comparator, byte order, byte totalPosition) throws JRException {
if (comparator == null && !Comparable.class.isAssignableFrom(valueClass))
throw new JRException("The bucket expression values are not comparable and no comparator specified.");
switch (order) {
case 2:
if (comparator == null) {
this.comparator = (Comparator)new ReverseComparator();
break;
}
this.comparator = (Comparator)new ReverseComparator(comparator);
break;
default:
this.comparator = comparator;
break;
}
this.totalPosition = totalPosition;
this.computeTotal = (totalPosition != 0);
}
public boolean computeTotal() {
return this.computeTotal;
}
public void setComputeTotal() {
this.computeTotal = true;
}
public byte getTotalPosition() {
return this.totalPosition;
}
public Comparator getComparator() {
return this.comparator;
}
public Bucket create(Object value) {
if (value == null)
return this.VALUE_NULL;
return new Bucket(value);
}
public class Bucket implements Comparable {
private final Object value;
private final byte type;
private final BucketDefinition this$0;
protected Bucket(byte type) {
this.value = null;
this.type = type;
}
protected Bucket(Object value) {
this.value = value;
this.type = 0;
}
public Object getValue() {
return this.value;
}
public boolean equals(Object o) {
if (o == null || !(o instanceof Bucket))
return false;
if (o == this)
return true;
Bucket v = (Bucket)o;
if (this.type != 0)
return (this.type == v.type);
return (v.type == 0 && this.value.equals(v.value));
}
public int hashCode() {
int hash = this.type;
if (this.type == 0)
hash = 37 * hash + this.value.hashCode();
return hash;
}
public String toString() {
switch (this.type) {
case 1:
return "NULL";
case 2:
return "TOTAL";
}
return String.valueOf(this.value);
}
public int compareTo(Object o) {
Bucket val = (Bucket)o;
if (this.type != val.type)
return this.type - val.type;
if (this.type != 0)
return 0;
if (BucketDefinition.this.comparator != null)
return BucketDefinition.this.comparator.compare(this.value, val.value);
return ((Comparable)this.value).compareTo(val.value);
}
public boolean isTotal() {
return (this.type == 2);
}
}
}

View File

@@ -0,0 +1,843 @@
package net.sf.jasperreports.crosstabs.fill.calculation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.TreeMap;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.util.JRProperties;
public class BucketingService {
public static final String PROPERTY_BUCKET_MEASURE_LIMIT = "net.sf.jasperreports.crosstab.bucket.measure.limit";
protected static final byte DIMENSION_ROW = 0;
protected static final byte DIMENSION_COLUMN = 1;
protected static final int DIMENSIONS = 2;
protected final BucketDefinition[] allBuckets;
protected final BucketDefinition[][] buckets;
protected final int rowBucketCount;
protected final int colBucketCount;
protected final boolean[][] retrieveTotal;
private boolean[] rowRetrTotals;
private int rowRetrTotalMin;
private int rowRetrTotalMax;
private int[] rowRetrColMax;
protected final MeasureDefinition[] measures;
protected final int origMeasureCount;
protected final int[] measureIndexes;
protected final boolean sorted;
protected final BucketMap bucketValueMap;
protected long dataCount;
protected boolean processed;
protected HeaderCell[][] colHeaders;
protected HeaderCell[][] rowHeaders;
protected CrosstabCell[][] cells;
private final MeasureDefinition.MeasureValue[] zeroUserMeasureValues;
private final int bucketMeasureLimit;
private int runningBucketMeasureCount = 0;
public BucketingService(List rowBuckets, List columnBuckets, List measures, boolean sorted, boolean[][] retrieveTotal) {
this.sorted = sorted;
this.buckets = new BucketDefinition[2][];
this.rowBucketCount = rowBuckets.size();
this.buckets[0] = new BucketDefinition[this.rowBucketCount];
rowBuckets.toArray((Object[])this.buckets[0]);
this.colBucketCount = columnBuckets.size();
this.buckets[1] = new BucketDefinition[this.colBucketCount];
columnBuckets.toArray((Object[])this.buckets[1]);
this.allBuckets = new BucketDefinition[this.rowBucketCount + this.colBucketCount];
System.arraycopy(this.buckets[0], 0, this.allBuckets, 0, this.rowBucketCount);
System.arraycopy(this.buckets[1], 0, this.allBuckets, this.rowBucketCount, this.colBucketCount);
this.origMeasureCount = measures.size();
List measuresList = new ArrayList(measures.size() * 2);
List measureIndexList = new ArrayList(measures.size() * 2);
int i;
for (i = 0; i < measures.size(); i++) {
MeasureDefinition measure = measures.get(i);
addMeasure(measure, i, measuresList, measureIndexList);
}
this.measures = new MeasureDefinition[measuresList.size()];
measuresList.toArray((Object[])this.measures);
this.measureIndexes = new int[measureIndexList.size()];
for (i = 0; i < this.measureIndexes.length; i++)
this.measureIndexes[i] = ((Integer)measureIndexList.get(i)).intValue();
this.retrieveTotal = retrieveTotal;
checkTotals();
this.bucketValueMap = createBucketMap(0);
this.zeroUserMeasureValues = initUserMeasureValues();
this.bucketMeasureLimit = JRProperties.getIntegerProperty("net.sf.jasperreports.crosstab.bucket.measure.limit", 0);
}
protected void checkTotals() {
this.rowRetrTotalMin = this.rowBucketCount + 1;
this.rowRetrTotalMax = -1;
this.rowRetrTotals = new boolean[this.rowBucketCount + 1];
this.rowRetrColMax = new int[this.rowBucketCount + 1];
for (int row = 0; row <= this.rowBucketCount; row++) {
this.rowRetrColMax[row] = -1;
boolean total = false;
for (int i = 0; i <= this.colBucketCount; i++) {
if (this.retrieveTotal[row][i]) {
total = true;
this.rowRetrColMax[row] = i;
}
}
this.rowRetrTotals[row] = total;
if (total) {
if (row < this.rowRetrTotalMin)
this.rowRetrTotalMin = row;
this.rowRetrTotalMax = row;
if (row < this.rowBucketCount)
this.allBuckets[row].setComputeTotal();
}
}
for (int col = 0; col < this.colBucketCount; col++) {
BucketDefinition colBucket = this.allBuckets[this.rowBucketCount + col];
if (!colBucket.computeTotal()) {
boolean total = false;
for (int i = 0; !total && i <= this.rowBucketCount; i++)
total = this.retrieveTotal[i][col];
if (total)
colBucket.setComputeTotal();
}
}
for (int d = 0; d < 2; d++) {
boolean dTotal = false;
for (int i = 0; i < (this.buckets[d]).length; i++) {
if (dTotal) {
this.buckets[d][i].setComputeTotal();
} else {
dTotal = this.buckets[d][i].computeTotal();
}
}
}
}
public void clear() {
this.bucketValueMap.clear();
this.processed = false;
this.dataCount = 0L;
this.runningBucketMeasureCount = 0;
}
protected BucketMap createBucketMap(int level) {
BucketMap map;
if (this.sorted) {
map = new BucketListMap(level, false);
} else {
map = new BucketTreeMap(level);
}
return map;
}
protected BucketListMap createCollectBucketMap(int level) {
return new BucketListMap(level, true);
}
protected void addMeasure(MeasureDefinition measure, int index, List measuresList, List measureIndexList) {
MeasureDefinition sumMeasure, varianceMeasure, countMeasure, measureDefinition1;
switch (measure.getCalculation()) {
case 3:
case 7:
sumMeasure = MeasureDefinition.createHelperMeasure(measure, (byte)2);
addMeasure(sumMeasure, index, measuresList, measureIndexList);
measureDefinition1 = MeasureDefinition.createHelperMeasure(measure, (byte)1);
addMeasure(measureDefinition1, index, measuresList, measureIndexList);
break;
case 6:
varianceMeasure = MeasureDefinition.createHelperMeasure(measure, (byte)7);
addMeasure(varianceMeasure, index, measuresList, measureIndexList);
break;
case 10:
countMeasure = MeasureDefinition.createDistinctCountHelperMeasure(measure);
addMeasure(countMeasure, index, measuresList, measureIndexList);
break;
}
measuresList.add(measure);
measureIndexList.add(new Integer(index));
}
public void addData(Object[] bucketValues, Object[] measureValues) throws JRException {
if (this.processed)
throw new JRException("Crosstab data has already been processed.");
this.dataCount++;
BucketDefinition.Bucket[] bucketVals = getBucketValues(bucketValues);
MeasureDefinition.MeasureValue[] values = this.bucketValueMap.insertMeasureValues(bucketVals);
for (int i = 0; i < this.measures.length; i++)
values[i].addValue(measureValues[this.measureIndexes[i]]);
}
protected void bucketMeasuresCreated() {
this.runningBucketMeasureCount += this.origMeasureCount;
checkBucketMeasureCount(this.runningBucketMeasureCount);
}
protected BucketDefinition.Bucket[] getBucketValues(Object[] bucketValues) {
BucketDefinition.Bucket[] bucketVals = new BucketDefinition.Bucket[this.allBuckets.length];
for (int i = 0; i < this.allBuckets.length; i++) {
BucketDefinition bucket = this.allBuckets[i];
Object value = bucketValues[i];
bucketVals[i] = bucket.create(value);
}
return bucketVals;
}
protected MeasureDefinition.MeasureValue[] initMeasureValues() {
MeasureDefinition.MeasureValue[] values = new MeasureDefinition.MeasureValue[this.measures.length];
for (int i = 0; i < this.measures.length; i++) {
MeasureDefinition measure = this.measures[i];
measure.getClass();
values[i] = new MeasureDefinition.MeasureValue(measure);
switch (measure.getCalculation()) {
case 3:
case 7:
values[i].setHelper(values[i - 2], (byte)1);
values[i].setHelper(values[i - 1], (byte)0);
break;
case 6:
values[i].setHelper(values[i - 1], (byte)2);
case 10:
values[i].setHelper(values[i - 1], (byte)0);
break;
}
}
return values;
}
protected MeasureDefinition.MeasureValue[] initUserMeasureValues() {
MeasureDefinition.MeasureValue[] vals = new MeasureDefinition.MeasureValue[this.origMeasureCount];
for (int c = 0, i = 0; i < this.measures.length; i++) {
if (!this.measures[i].isSystemDefined()) {
this.measures[i].getClass();
vals[c] = new MeasureDefinition.MeasureValue(this.measures[i]);
c++;
}
}
return vals;
}
public void processData() throws JRException {
if (!this.processed) {
if (this.dataCount > 0L) {
if (this.allBuckets[this.rowBucketCount - 1].computeTotal() || this.allBuckets[this.allBuckets.length - 1].computeTotal())
computeTotals(this.bucketValueMap);
createCrosstab();
}
this.processed = true;
}
}
public boolean hasData() {
return (this.dataCount > 0L);
}
public HeaderCell[][] getColumnHeaders() {
return this.colHeaders;
}
public HeaderCell[][] getRowHeaders() {
return this.rowHeaders;
}
public CrosstabCell[][] getCrosstabCells() {
return this.cells;
}
public MeasureDefinition.MeasureValue[] getMeasureValues(BucketDefinition.Bucket[] bucketValues) {
BucketMap map = this.bucketValueMap;
for (int i = 0; map != null && i < this.allBuckets.length - 1; i++)
map = (BucketMap)map.get(bucketValues[i]);
return (map == null) ? null : (MeasureDefinition.MeasureValue[])map.get(bucketValues[this.allBuckets.length - 1]);
}
protected MeasureDefinition.MeasureValue[] getUserMeasureValues(MeasureDefinition.MeasureValue[] values) {
MeasureDefinition.MeasureValue[] vals = new MeasureDefinition.MeasureValue[this.origMeasureCount];
for (int c = 0, i = 0; i < this.measures.length; i++) {
if (!this.measures[i].isSystemDefined()) {
vals[c] = values[i];
c++;
}
}
return vals;
}
public MeasureDefinition.MeasureValue[] getGrandTotals() {
BucketMap map = this.bucketValueMap;
for (int i = 0; map != null && i < this.allBuckets.length - 1; i++)
map = (BucketMap)map.getTotalEntry().getValue();
return (map == null) ? null : (MeasureDefinition.MeasureValue[])map.getTotalEntry().getValue();
}
protected void computeTotals(BucketMap bucketMap) throws JRException {
byte dimension = (bucketMap.level < this.rowBucketCount) ? 0 : 1;
if (dimension == 1 && !this.allBuckets[this.allBuckets.length - 1].computeTotal())
return;
if (!bucketMap.last)
for (Iterator it = bucketMap.entryIterator(); it.hasNext(); ) {
Map.Entry entry = it.next();
computeTotals((BucketMap)entry.getValue());
}
if (this.allBuckets[bucketMap.level].computeTotal())
if (dimension == 1) {
computeColumnTotal(bucketMap);
} else {
computeRowTotals(bucketMap);
}
}
protected void sumVals(MeasureDefinition.MeasureValue[] totals, MeasureDefinition.MeasureValue[] vals) throws JRException {
for (int i = 0; i < this.measures.length; i++)
totals[i].addValue(vals[i]);
}
protected void computeColumnTotal(BucketMap bucketMap) throws JRException {
MeasureDefinition.MeasureValue[] totals = initMeasureValues();
for (Iterator it = bucketMap.entryIterator(); it.hasNext(); ) {
Map.Entry entry = it.next();
for (int j = bucketMap.level + 1; j < this.allBuckets.length; j++)
entry = ((BucketMap)entry.getValue()).getTotalEntry();
sumVals(totals, (MeasureDefinition.MeasureValue[])entry.getValue());
}
for (int i = bucketMap.level + 1; i < this.allBuckets.length; i++)
bucketMap = bucketMap.addTotalNextMap();
bucketMap.addTotalEntry(totals);
}
protected void computeRowTotals(BucketMap bucketMap) throws JRException {
BucketListMap totals = createCollectBucketMap(this.rowBucketCount);
for (Iterator it = bucketMap.entryIterator(); it.hasNext(); ) {
Map.Entry entry = it.next();
for (int j = bucketMap.level + 1; j < this.rowBucketCount; j++)
entry = ((BucketMap)entry.getValue()).getTotalEntry();
totals.collectVals((BucketMap)entry.getValue(), true);
}
BucketMap totalBucketMap = bucketMap;
for (int i = bucketMap.level + 1; i < this.rowBucketCount; i++)
totalBucketMap = totalBucketMap.addTotalNextMap();
totalBucketMap.addTotalEntry(totals);
}
protected static class MapEntry implements Map.Entry, Comparable {
final BucketDefinition.Bucket key;
final Object value;
MapEntry(BucketDefinition.Bucket key, Object value) {
this.key = key;
this.value = value;
}
public Object getKey() {
return this.key;
}
public Object getValue() {
return this.value;
}
public Object setValue(Object value) {
throw new UnsupportedOperationException();
}
public int compareTo(Object o) {
return this.key.compareTo(((MapEntry)o).key);
}
public String toString() {
return this.key + ":" + this.value;
}
}
protected abstract class BucketMap {
final int level;
final boolean last;
final BucketDefinition.Bucket totalKey;
private final BucketingService this$0;
BucketMap(int level) {
this.level = level;
this.last = (level == BucketingService.this.allBuckets.length - 1);
this.totalKey = (BucketingService.this.allBuckets[level]).VALUE_TOTAL;
}
BucketMap addTotalNextMap() {
BucketMap nextMap = BucketingService.this.createBucketMap(this.level + 1);
addTotalEntry(nextMap);
return nextMap;
}
abstract void set(BucketDefinition.Bucket param1Bucket, Object param1Object);
abstract void clear();
abstract Iterator entryIterator();
abstract Object get(BucketDefinition.Bucket param1Bucket);
abstract MeasureDefinition.MeasureValue[] insertMeasureValues(BucketDefinition.Bucket[] param1ArrayOfBucket);
abstract void addTotalEntry(Object param1Object);
abstract int size();
abstract Map.Entry getTotalEntry();
}
protected class BucketTreeMap extends BucketMap {
TreeMap map;
private final BucketingService this$0;
BucketTreeMap(int level) {
super(level);
this.map = new TreeMap();
}
void clear() {
this.map.clear();
}
Iterator entryIterator() {
return this.map.entrySet().iterator();
}
Object get(BucketDefinition.Bucket key) {
return this.map.get(key);
}
MeasureDefinition.MeasureValue[] insertMeasureValues(BucketDefinition.Bucket[] bucketValues) {
BucketTreeMap levelMap = (BucketTreeMap)BucketingService.this.bucketValueMap;
for (int i = 0; i < bucketValues.length - 1; i++) {
BucketTreeMap nextMap = (BucketTreeMap)levelMap.get(bucketValues[i]);
if (nextMap == null) {
nextMap = new BucketTreeMap(i + 1);
levelMap.map.put(bucketValues[i], nextMap);
}
levelMap = nextMap;
}
MeasureDefinition.MeasureValue[] values = (MeasureDefinition.MeasureValue[])levelMap.get(bucketValues[bucketValues.length - 1]);
if (values == null) {
values = BucketingService.this.initMeasureValues();
levelMap.map.put(bucketValues[bucketValues.length - 1], values);
BucketingService.this.bucketMeasuresCreated();
}
return values;
}
int size() {
return this.map.size();
}
void addTotalEntry(Object value) {
this.map.put(this.totalKey, value);
}
Map.Entry getTotalEntry() {
Object value = get(this.totalKey);
return (value == null) ? null : new BucketingService.MapEntry(this.totalKey, value);
}
public String toString() {
return this.map.toString();
}
void set(BucketDefinition.Bucket key, Object value) {
this.map.put(key, value);
}
}
protected class BucketListMap extends BucketMap {
List entries;
private final BucketingService this$0;
BucketListMap(int level, boolean linked) {
super(level);
if (linked) {
this.entries = new LinkedList();
} else {
this.entries = new ArrayList();
}
}
void clear() {
this.entries.clear();
}
Iterator entryIterator() {
return this.entries.iterator();
}
private void add(BucketDefinition.Bucket key, Object value) {
this.entries.add(new BucketingService.MapEntry(key, value));
}
Object get(BucketDefinition.Bucket key) {
int idx = Collections.binarySearch(this.entries, new BucketingService.MapEntry(key, null));
return (idx >= 0) ? ((BucketingService.MapEntry)this.entries.get(idx)).value : null;
}
MeasureDefinition.MeasureValue[] insertMeasureValues(BucketDefinition.Bucket[] bucketValues) {
int i = 0;
Object levelObj = this;
BucketListMap map = null;
while (i < BucketingService.this.allBuckets.length) {
map = (BucketListMap)levelObj;
int size = map.entries.size();
if (size == 0)
break;
BucketingService.MapEntry lastEntry = map.entries.get(size - 1);
if (!lastEntry.key.equals(bucketValues[i]))
break;
i++;
levelObj = lastEntry.value;
}
if (i == BucketingService.this.allBuckets.length)
return (MeasureDefinition.MeasureValue[])levelObj;
while (i < BucketingService.this.allBuckets.length - 1) {
BucketListMap nextMap = new BucketListMap(i + 1, false);
map.add(bucketValues[i], nextMap);
map = nextMap;
i++;
}
MeasureDefinition.MeasureValue[] values = BucketingService.this.initMeasureValues();
map.add(bucketValues[i], values);
BucketingService.this.bucketMeasuresCreated();
return values;
}
int size() {
return this.entries.size();
}
void addTotalEntry(Object value) {
add(this.totalKey, value);
}
Map.Entry getTotalEntry() {
BucketingService.MapEntry lastEntry = this.entries.get(this.entries.size() - 1);
if (lastEntry.key.isTotal())
return lastEntry;
return null;
}
void set(BucketDefinition.Bucket key, Object value) {
BucketingService.MapEntry mapEntry = new BucketingService.MapEntry(key, value);
int idx = Collections.binarySearch(this.entries, mapEntry);
int ins = -idx - 1;
this.entries.add(ins, mapEntry);
}
void collectVals(BucketingService.BucketMap map, boolean sum) throws JRException {
ListIterator totalIt = this.entries.listIterator();
BucketingService.MapEntry totalItEntry = totalIt.hasNext() ? totalIt.next() : null;
Iterator it = map.entryIterator();
Map.Entry entry = it.hasNext() ? it.next() : null;
while (entry != null) {
BucketDefinition.Bucket key = (BucketDefinition.Bucket)entry.getKey();
int compare = (totalItEntry == null) ? -1 : key.compareTo(totalItEntry.key);
if (compare <= 0) {
Object addVal = null;
if (this.last) {
if (sum) {
MeasureDefinition.MeasureValue[] totalVals = (compare == 0) ? (MeasureDefinition.MeasureValue[])totalItEntry.value : null;
if (totalVals == null) {
totalVals = BucketingService.this.initMeasureValues();
addVal = totalVals;
}
BucketingService.this.sumVals(totalVals, (MeasureDefinition.MeasureValue[])entry.getValue());
}
} else {
BucketListMap nextTotals = (compare == 0) ? (BucketListMap)totalItEntry.value : null;
if (nextTotals == null) {
nextTotals = BucketingService.this.createCollectBucketMap(this.level + 1);
addVal = nextTotals;
}
nextTotals.collectVals((BucketingService.BucketMap)entry.getValue(), sum);
}
if (compare < 0) {
if (totalItEntry != null)
totalIt.previous();
totalIt.add(new BucketingService.MapEntry(key, addVal));
if (totalItEntry != null)
totalIt.next();
}
entry = it.hasNext() ? it.next() : null;
}
if (compare >= 0)
totalItEntry = totalIt.hasNext() ? totalIt.next() : null;
}
}
}
protected void createCrosstab() throws JRException {
BucketListMap collectedCols;
CollectedList[] collectedHeaders = new CollectedList[2];
collectedHeaders[0] = createHeadersList((byte)0, this.bucketValueMap, 0, false);
if (this.allBuckets[0].computeTotal()) {
BucketMap map = this.bucketValueMap;
for (int i = 0; i < this.rowBucketCount; i++)
map = (BucketMap)map.getTotalEntry().getValue();
collectedCols = (BucketListMap)map;
} else {
collectedCols = createCollectBucketMap(this.rowBucketCount);
collectCols(collectedCols, this.bucketValueMap);
}
collectedHeaders[1] = createHeadersList((byte)1, collectedCols, 0, false);
int rowBuckets = (collectedHeaders[0]).span;
int colBuckets = (collectedHeaders[1]).span;
int bucketMeasureCount = rowBuckets * colBuckets * this.origMeasureCount;
checkBucketMeasureCount(bucketMeasureCount);
this.colHeaders = createHeaders((byte)1, collectedHeaders);
this.rowHeaders = createHeaders((byte)0, collectedHeaders);
this.cells = new CrosstabCell[rowBuckets][colBuckets];
fillCells(collectedHeaders, this.bucketValueMap, 0, new int[] { 0, 0 }, new ArrayList(), new ArrayList());
}
protected void checkBucketMeasureCount(int bucketMeasureCount) {
if (this.bucketMeasureLimit > 0 && bucketMeasureCount > this.bucketMeasureLimit)
throw new JRRuntimeException("Crosstab bucket/measure limit (" + this.bucketMeasureLimit + ") exceeded.");
}
protected void collectCols(BucketListMap collectedCols, BucketMap bucketMap) throws JRException {
if (this.allBuckets[bucketMap.level].computeTotal()) {
BucketMap map = bucketMap;
for (int i = bucketMap.level; i < this.rowBucketCount; i++)
map = (BucketMap)map.getTotalEntry().getValue();
collectedCols.collectVals(map, false);
return;
}
for (Iterator it = bucketMap.entryIterator(); it.hasNext(); ) {
Map.Entry entry = it.next();
BucketMap nextMap = (BucketMap)entry.getValue();
if (bucketMap.level == this.rowBucketCount - 1) {
collectedCols.collectVals(nextMap, false);
continue;
}
collectCols(collectedCols, nextMap);
}
}
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 = it.next();
BucketDefinition.Bucket bucketValue = (BucketDefinition.Bucket)entry.getKey();
boolean totalBucket = bucketValue.isTotal();
byte totalPosition = this.allBuckets[bucketMap.level].getTotalPosition();
boolean createHeader = (!totalBucket || total || totalPosition != 0);
if (createHeader) {
CollectedList nextHeaders;
if (level + 1 < (this.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 == 1) {
headers.addFirst(nextHeaders);
continue;
}
headers.add(nextHeaders);
continue;
}
headers.add(nextHeaders);
}
}
if (headers.span == 0)
headers.span = 1;
return headers;
}
protected HeaderCell[][] createHeaders(byte dimension, CollectedList[] headersLists) {
HeaderCell[][] headers = new HeaderCell[(this.buckets[dimension]).length][(headersLists[dimension]).span];
List vals = new ArrayList();
fillHeaders(dimension, headers, 0, 0, headersLists[dimension], vals);
return headers;
}
protected void fillHeaders(byte dimension, HeaderCell[][] headers, int level, int col, CollectedList list, List vals) {
if (level == (this.buckets[dimension]).length)
return;
for (Iterator it = list.iterator(); it.hasNext(); ) {
CollectedList subList = (CollectedList)it.next();
vals.add(subList.key);
int depthSpan = subList.key.isTotal() ? ((this.buckets[dimension]).length - level) : 1;
BucketDefinition.Bucket[] values = new BucketDefinition.Bucket[(this.buckets[dimension]).length];
vals.toArray(values);
headers[level][col] = new HeaderCell(values, subList.span, depthSpan);
if (!subList.key.isTotal())
fillHeaders(dimension, headers, level + 1, col, subList, vals);
col += subList.span;
vals.remove(vals.size() - 1);
}
}
protected void fillCells(CollectedList[] collectedHeaders, BucketMap bucketMap, int level, int[] pos, List vals, List bucketMaps) {
bucketMaps.add(bucketMap);
byte dimension = (level < this.rowBucketCount) ? 0 : 1;
boolean last = (level == this.allBuckets.length - 1);
CollectedList[] nextCollected = null;
if (!last) {
nextCollected = new CollectedList[2];
for (int d = 0; d < 2; d++) {
if (d != dimension)
nextCollected[d] = collectedHeaders[d];
}
}
boolean incrementRow = (level == (this.buckets[0]).length - 1);
CollectedList collectedList = collectedHeaders[dimension];
Iterator bucketIt = (bucketMap == null) ? null : bucketMap.entryIterator();
Map.Entry bucketItEntry = (bucketIt != null && bucketIt.hasNext()) ? 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() ? 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[0] + 1;
pos[1] = 0;
}
}
bucketMaps.remove(bucketMaps.size() - 1);
}
protected void fillCell(int[] pos, List vals, List bucketMaps, Map.Entry bucketEntry) {
Iterator valsIt = vals.iterator();
BucketDefinition.Bucket[] rowValues = new BucketDefinition.Bucket[(this.buckets[0]).length];
for (int i = 0; i < rowValues.length; i++)
rowValues[i] = valsIt.next();
BucketDefinition.Bucket[] columnValues = new BucketDefinition.Bucket[(this.buckets[1]).length];
for (int j = 0; j < columnValues.length; j++)
columnValues[j] = valsIt.next();
MeasureDefinition.MeasureValue[] measureVals = (bucketEntry == null) ? this.zeroUserMeasureValues : getUserMeasureValues((MeasureDefinition.MeasureValue[])bucketEntry.getValue());
MeasureDefinition.MeasureValue[][][] totals = retrieveTotals(vals, bucketMaps);
this.cells[pos[0]][pos[1]] = new CrosstabCell(rowValues, columnValues, measureVals, totals);
pos[1] = pos[1] + 1;
}
protected MeasureDefinition.MeasureValue[][][] retrieveTotals(List vals, List bucketMaps) {
MeasureDefinition.MeasureValue[][][] totals = new MeasureDefinition.MeasureValue[this.rowBucketCount + 1][this.colBucketCount + 1][];
for (int row = this.rowRetrTotalMax; row >= this.rowRetrTotalMin; row--) {
if (this.rowRetrTotals[row]) {
BucketMap rowMap = bucketMaps.get(row);
for (int i = row; rowMap != null && i < this.rowBucketCount; i++) {
Map.Entry totalEntry = rowMap.getTotalEntry();
rowMap = (totalEntry == null) ? null : (BucketMap)totalEntry.getValue();
}
for (int col = 0; col <= this.rowRetrColMax[row]; col++) {
BucketMap colMap = rowMap;
if (col < this.colBucketCount - 1)
if (row == this.rowBucketCount) {
rowMap = bucketMaps.get(this.rowBucketCount + col + 1);
} else if (rowMap != null) {
rowMap = (BucketMap)rowMap.get(vals.get(this.rowBucketCount + col));
}
if (this.retrieveTotal[row][col]) {
for (int j = col + 1; colMap != null && j < this.colBucketCount; j++)
colMap = (BucketMap)colMap.getTotalEntry().getValue();
if (colMap != null)
if (col == this.colBucketCount) {
MeasureDefinition.MeasureValue[] measureValues = (MeasureDefinition.MeasureValue[])colMap.get(vals.get(this.rowBucketCount + this.colBucketCount - 1));
totals[row][col] = getUserMeasureValues(measureValues);
} else {
Map.Entry totalEntry = colMap.getTotalEntry();
if (totalEntry != null) {
MeasureDefinition.MeasureValue[] totalValues = (MeasureDefinition.MeasureValue[])totalEntry.getValue();
totals[row][col] = getUserMeasureValues(totalValues);
}
}
if (totals[row][col] == null)
totals[row][col] = this.zeroUserMeasureValues;
}
}
}
}
return totals;
}
protected static class CollectedList extends LinkedList {
private static final long serialVersionUID = 10200L;
int span = 0;
BucketDefinition.Bucket key;
public boolean add(Object o) {
boolean added = super.add(o);
incrementSpan(o);
return added;
}
public void addFirst(Object o) {
super.addFirst(o);
incrementSpan(o);
}
public void addLast(Object o) {
super.add(o);
incrementSpan(o);
}
private void incrementSpan(Object o) {
if (o != null && o instanceof CollectedList) {
this.span += ((CollectedList)o).span;
} else {
this.span++;
}
}
public String toString() {
return this.key + "/" + this.span + ": " + super.toString();
}
}
}

View File

@@ -0,0 +1,55 @@
package net.sf.jasperreports.crosstabs.fill.calculation;
public class CrosstabCell {
private final BucketDefinition.Bucket[] rowBucketValues;
private final int rowTotalGroupIndex;
private final BucketDefinition.Bucket[] columnBucketValues;
private final int columnTotalGroupIndex;
private final MeasureDefinition.MeasureValue[] mesureValues;
private final MeasureDefinition.MeasureValue[][][] totals;
public CrosstabCell(BucketDefinition.Bucket[] rowBucketValues, BucketDefinition.Bucket[] columnBucketValues, MeasureDefinition.MeasureValue[] mesureValues, MeasureDefinition.MeasureValue[][][] totals) {
this.rowBucketValues = rowBucketValues;
this.rowTotalGroupIndex = getTotalIndex(rowBucketValues);
this.columnBucketValues = columnBucketValues;
this.columnTotalGroupIndex = getTotalIndex(columnBucketValues);
this.mesureValues = mesureValues;
this.totals = totals;
}
private static int getTotalIndex(BucketDefinition.Bucket[] values) {
int i = 0;
while (i < values.length && !values[i].isTotal())
i++;
return i;
}
public MeasureDefinition.MeasureValue[] getMesureValues() {
return this.mesureValues;
}
public BucketDefinition.Bucket[] getColumnBucketValues() {
return this.columnBucketValues;
}
public BucketDefinition.Bucket[] getRowBucketValues() {
return this.rowBucketValues;
}
public int getColumnTotalGroupIndex() {
return this.columnTotalGroupIndex;
}
public int getRowTotalGroupIndex() {
return this.rowTotalGroupIndex;
}
public MeasureDefinition.MeasureValue[][][] getTotals() {
return this.totals;
}
}

View File

@@ -0,0 +1,45 @@
package net.sf.jasperreports.crosstabs.fill.calculation;
public class HeaderCell {
private final BucketDefinition.Bucket[] bucketValues;
private final int levelSpan;
private final int depthSpan;
private final boolean isTotal;
public HeaderCell(BucketDefinition.Bucket[] bucketValues, int levelSpan, int depthSpan) {
this.bucketValues = bucketValues;
this.levelSpan = levelSpan;
this.depthSpan = depthSpan;
boolean foundTotal = false;
for (int i = 0; i < bucketValues.length; i++) {
if (bucketValues[i] != null && bucketValues[i].isTotal()) {
foundTotal = true;
break;
}
}
this.isTotal = foundTotal;
}
public BucketDefinition.Bucket[] getBucketValues() {
return this.bucketValues;
}
public int getLevelSpan() {
return this.levelSpan;
}
public int getDepthSpan() {
return this.depthSpan;
}
public boolean isTotal() {
return this.isTotal;
}
public static HeaderCell createLevelSpanCopy(HeaderCell cell, int newLevelSpan) {
return new HeaderCell(cell.bucketValues, newLevelSpan, cell.getDepthSpan());
}
}

View File

@@ -0,0 +1,129 @@
package net.sf.jasperreports.crosstabs.fill.calculation;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.fill.AbstractValueProvider;
import net.sf.jasperreports.engine.fill.JRCalculable;
import net.sf.jasperreports.engine.fill.JRDistinctCountExtendedIncrementerFactory;
import net.sf.jasperreports.engine.fill.JRExtendedIncrementer;
import net.sf.jasperreports.engine.fill.JRExtendedIncrementerFactory;
public class MeasureDefinition {
protected final byte calculation;
protected final JRExtendedIncrementerFactory incrementerFactory;
protected final Class valueClass;
protected final boolean isSystemDefined;
public MeasureDefinition(Class valueClass, byte calculation, JRExtendedIncrementerFactory incrementerFactory) {
this(valueClass, calculation, incrementerFactory, false);
}
protected MeasureDefinition(Class valueClass, byte calculation, JRExtendedIncrementerFactory incrementerFactory, boolean isSystemDefined) {
this.valueClass = valueClass;
this.calculation = calculation;
this.incrementerFactory = incrementerFactory;
this.isSystemDefined = isSystemDefined;
}
public static MeasureDefinition createHelperMeasure(MeasureDefinition measure, byte helperCalculation) {
return new MeasureDefinition(measure.valueClass, helperCalculation, measure.incrementerFactory, true);
}
public static MeasureDefinition createDistinctCountHelperMeasure(MeasureDefinition measure) {
return new MeasureDefinition(measure.valueClass, (byte)0, (JRExtendedIncrementerFactory)JRDistinctCountExtendedIncrementerFactory.getInstance(), true);
}
public byte getCalculation() {
return this.calculation;
}
public JRExtendedIncrementerFactory getIncrementerFactory() {
return this.incrementerFactory;
}
public JRExtendedIncrementer getIncrementer() {
return this.incrementerFactory.getExtendedIncrementer(this.calculation);
}
protected boolean isSystemDefined() {
return this.isSystemDefined;
}
public Class getValueClass() {
return this.valueClass;
}
protected static final AbstractValueProvider VALUE_PROVIDER = new AbstractValueProvider() {
public Object getValue(JRCalculable calculable) {
return calculable.getValue();
}
};
public class MeasureValue implements JRCalculable {
private Object value;
private MeasureValue[] helpers;
private boolean initialized;
private JRExtendedIncrementer incrementer;
private final MeasureDefinition this$0;
public MeasureValue() {
this.value = null;
this.helpers = new MeasureValue[3];
this.incrementer = MeasureDefinition.this.getIncrementer();
init();
}
protected void init() {
this.value = this.incrementer.initialValue();
setInitialized(true);
}
public void addValue(Object addValue) throws JRException {
this.value = this.incrementer.increment(this, addValue, MeasureDefinition.VALUE_PROVIDER);
setInitialized(false);
}
public void addValue(MeasureValue measureValue) throws JRException {
if (!measureValue.isInitialized()) {
this.value = this.incrementer.combine(this, measureValue, MeasureDefinition.VALUE_PROVIDER);
setInitialized(false);
}
}
public Object getValue() {
return this.value;
}
public String toString() {
return String.valueOf(getValue());
}
public MeasureValue setHelper(MeasureValue helperVariable, byte type) {
MeasureValue old = this.helpers[type];
this.helpers[type] = helperVariable;
return old;
}
public boolean isInitialized() {
return this.initialized;
}
public Object getIncrementedValue() {
return this.value;
}
public JRCalculable getHelperVariable(byte helperType) {
return this.helpers[helperType];
}
public void setInitialized(boolean isInitialized) {
this.initialized = isInitialized;
}
}
}