Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
net.sf.jasperreports.components.table.TableCompiler Maven / Gradle / Ivy
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2023 Cloud Software Group, Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see .
*/
package net.sf.jasperreports.components.table;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import net.sf.jasperreports.engine.JRDatasetRun;
import net.sf.jasperreports.engine.JRElement;
import net.sf.jasperreports.engine.JRExpressionCollector;
import net.sf.jasperreports.engine.JRGroup;
import net.sf.jasperreports.engine.base.JRBaseObjectFactory;
import net.sf.jasperreports.engine.component.Component;
import net.sf.jasperreports.engine.component.ComponentCompiler;
import net.sf.jasperreports.engine.design.JRDesignDataset;
import net.sf.jasperreports.engine.design.JRVerifier;
/**
*
*
* @author Lucian Chirita ([email protected] )
*/
public class TableCompiler implements ComponentCompiler
{
@Override
public void collectExpressions(Component component,
JRExpressionCollector collector)
{
TableComponent table = (TableComponent) component;
JRDatasetRun datasetRun = table.getDatasetRun();
collector.collect(datasetRun);
JRExpressionCollector datasetCollector = collector.getDatasetCollector(
datasetRun.getDatasetName());
ColumnExpressionCollector columnCollector = new ColumnExpressionCollector(
collector, datasetCollector);
columnCollector.collectColumns(table.getColumns());
RowExpressionCollector rowCollector = new RowExpressionCollector(datasetCollector);
rowCollector.collectRow(table.getTableHeader());
rowCollector.collectRow(table.getTableFooter());
rowCollector.collectGroupRows(table.getGroupHeaders());
rowCollector.collectGroupRows(table.getGroupFooters());
rowCollector.collectRow(table.getColumnHeader());
rowCollector.collectRow(table.getColumnFooter());
rowCollector.collectRow(table.getDetail());
columnCollector.collectCell(table.getNoData());
}
@Override
public Component toCompiledComponent(Component component,
JRBaseObjectFactory baseFactory)
{
TableComponent table = (TableComponent) component;
return new StandardTable(table, baseFactory);
}
@Override
public void verify(Component component, JRVerifier verifier)
{
TableComponent table = (TableComponent) component;
JRDatasetRun datasetRun = table.getDatasetRun();
if (datasetRun == null)
{
verifier.addBrokenRule("No list subdataset run set", table);
}
else
{
verifier.verifyDatasetRun(datasetRun);
}
List columns = table.getColumns();
if (columns == null || columns.isEmpty())
{
verifier.addBrokenRule("No columns defined in the table", table);
}
else
{
if (!detectLoops(verifier, columns))
{
String subdataset = datasetRun == null ? null : datasetRun.getDatasetName();
if (subdataset != null)
{
verifier.pushSubdatasetContext(subdataset);
}
try
{
verifyColumns(table, verifier);
}
finally
{
if (subdataset != null)
{
verifier.popSubdatasetContext();
}
}
verifyColumnHeights(table, verifier);
}
}
}
protected boolean detectLoops(JRVerifier verifier, List columns)
{
Set parents = new HashSet<>();
return detectLoops(verifier, columns, parents);
}
protected boolean detectLoops(final JRVerifier verifier, List columns,
final Set parents)
{
boolean loop = false;
for (BaseColumn column : columns)
{
if (parents.contains(column))
{
verifier.addBrokenRule("Table column is its own ancestor", column);
loop = true;
}
else
{
loop = column.visitColumn(new ColumnVisitor()
{
@Override
public Boolean visitColumn(Column column)
{
return false;
}
@Override
public Boolean visitColumnGroup(ColumnGroup columnGroup)
{
parents.add(columnGroup);
boolean loopDetected = detectLoops(verifier,
columnGroup.getColumns(), parents);
parents.remove(columnGroup);
return loopDetected;
}
});
}
if (loop)
{
break;
}
}
return false;
}
protected void verifyColumns(final TableComponent table, final JRVerifier verifier)
{
ColumnVisitor columnVerifier = new ColumnVisitor()
{
@Override
public Void visitColumn(Column column)
{
verifyColumn(table, column, verifier);
return null;
}
@Override
public Void visitColumnGroup(ColumnGroup columnGroup)
{
verifyBaseColumn(table, columnGroup, verifier);
List subcolumns = columnGroup.getColumns();
if (subcolumns == null || subcolumns.isEmpty())
{
verifier.addBrokenRule("No columns defined in column group", columnGroup);
}
else
{
int subwidth = 0;
boolean subwidthValid = true;
for (BaseColumn column : columnGroup.getColumns())
{
column.visitColumn(this);
Integer width = column.getWidth();
if (width == null)
{
subwidthValid = false;
}
else
{
subwidth += width;
}
}
if (subwidthValid && columnGroup.getWidth() != null
&& columnGroup.getWidth() != subwidth)
{
verifier.addBrokenRule("Column group width " + columnGroup.getWidth()
+ " does not match sum of subcolumn widths " + subwidth, columnGroup);
}
}
return null;
}
};
for (BaseColumn column : table.getColumns())
{
column.visitColumn(columnVerifier);
}
}
protected void verifyBaseColumn(TableComponent table, BaseColumn column, JRVerifier verifier)
{
Integer width = column.getWidth();
if (width == null)
{
verifier.addBrokenRule("Column width not set", column);
}
else if (width < 0)
{
verifier.addBrokenRule("Negative column width", column);
}
else
{
verifyCell(column.getTableHeader(), width, "table header", verifier);
verifyCell(column.getTableFooter(), width, "table footer", verifier);
verifyGroupCells(table, column.getGroupHeaders(), width, "group header", verifier);
verifyGroupCells(table, column.getGroupFooters(), width, "group footer", verifier);
verifyCell(column.getColumnHeader(), width, "column header", verifier);
verifyCell(column.getColumnFooter(), width, "column footer", verifier);
}
}
protected void verifyGroupCells(TableComponent table, List cells, int width,
String cellName, JRVerifier verifier)
{
if (cells != null)
{
Set groupNames = new HashSet<>();
for (GroupCell groupCell : cells)
{
String groupName = groupCell.getGroupName();
if (groupName == null)
{
verifier.addBrokenRule("No group name set for table column group cell", groupCell);
}
else
{
if (!groupNames.add(groupName))
{
verifier.addBrokenRule("Duplicate " + cellName + " for group \"" + groupName + "\"",
groupCell);
}
JRDatasetRun datasetRun = table.getDatasetRun();
if (datasetRun != null)
{
JRDesignDataset dataset = (JRDesignDataset) verifier.getReportDesign().getDatasetMap().get(
datasetRun.getDatasetName());
if (dataset != null && dataset.getGroupsMap().get(groupName) == null)
{
verifier.addBrokenRule("No group named \"" + groupName
+ "\" found in subdataset " + datasetRun.getDatasetName(),
groupCell);
}
}
}
verifyCell(groupCell.getCell(), width, cellName, verifier);
}
}
}
protected void verifyCell(Cell cell, int width, String cellName, JRVerifier verifier)
{
if (cell == null)
{
return;
}
if (cell.getRowSpan() != null && cell.getRowSpan() < 1)
{
verifier.addBrokenRule("Negative or zero cell row span", cell);
}
Integer height = cell.getHeight();
if (height == null)
{
verifier.addBrokenRule("Cell height not set", cell);
}
else if (height < 0)
{
verifier.addBrokenRule("Negative cell height", cell);
}
else
{
JRElement[] elements = cell.getElements();
if (elements != null && elements.length > 0)
{
int topPadding = cell.getLineBox().getTopPadding();
int leftPadding = cell.getLineBox().getLeftPadding();
int bottomPadding = cell.getLineBox().getBottomPadding();
int rightPadding = cell.getLineBox().getRightPadding();
int avlblWidth = width - leftPadding - rightPadding;
int avlblHeight = height - topPadding - bottomPadding;
for (JRElement element : elements)
{
verifier.verifyElement(element);
if (element.getX() < 0 || element.getY() < 0)
{
verifier.addBrokenRule("Element must be placed at positive coordinates.",
element);
}
if (element.getY() + element.getHeight() > avlblHeight)
{
verifier.addBrokenRule("Element reaches outside table " + cellName + " contents height: y = "
+ element.getY() + ", height = " + element.getHeight()
+ ", cell available height = " + avlblHeight + ".", element);
}
if (element.getX() + element.getWidth() > avlblWidth)
{
verifier.addBrokenRule("Element reaches outside table " + cellName + " contents width: x = "
+ element.getX() + ", width = " + element.getWidth()
+ ", cell available width = " + avlblWidth + ".", element);
}
}
}
}
}
protected void verifyColumn(TableComponent table, Column column, JRVerifier verifier)
{
verifyBaseColumn(table, column, verifier);
if (column.getWidth() != null)
{
Cell detailCell = column.getDetailCell();
verifyCell(detailCell, column.getWidth(), "detail", verifier);
}
}
protected interface ColumnCellSelector
{
Cell getCell(Column column);
Cell getCell(ColumnGroup group);
String getCellName();
}
protected void verifyColumnHeights(TableComponent table,
JRVerifier verifier)
{
verifyColumnHeights(table, verifier, new BaseColumnCellSelector()
{
@Override
protected Cell getCell(BaseColumn column)
{
return column.getTableHeader();
}
@Override
public String getCellName()
{
return "table header";
}
});
verifyColumnHeights(table, verifier, new BaseColumnCellSelector()
{
@Override
protected Cell getCell(BaseColumn column)
{
return column.getTableFooter();
}
@Override
public String getCellName()
{
return "table footer";
}
});
JRDatasetRun datasetRun = table.getDatasetRun();
if (datasetRun != null)
{
JRDesignDataset dataset = (JRDesignDataset) verifier.getReportDesign().getDatasetMap().get(
datasetRun.getDatasetName());
if (dataset != null)
{
JRGroup[] groups = dataset.getGroups();
if (groups != null)
{
for (int i = 0; i < groups.length; i++)
{
final String groupName = groups[i].getName();
verifyColumnHeights(table, verifier, new BaseColumnCellSelector()
{
@Override
protected Cell getCell(BaseColumn column)
{
return column.getGroupHeader(groupName);
}
@Override
public String getCellName()
{
return "group " + groupName + " header";
}
});
verifyColumnHeights(table, verifier, new BaseColumnCellSelector()
{
@Override
protected Cell getCell(BaseColumn column)
{
return column.getGroupFooter(groupName);
}
@Override
public String getCellName()
{
return "group " + groupName + " footer";
}
});
}
}
}
}
verifyColumnHeights(table, verifier, new BaseColumnCellSelector()
{
@Override
protected Cell getCell(BaseColumn column)
{
return column.getColumnHeader();
}
@Override
public String getCellName()
{
return "column header";
}
});
verifyColumnHeights(table, verifier, new BaseColumnCellSelector()
{
@Override
protected Cell getCell(BaseColumn column)
{
return column.getColumnFooter();
}
@Override
public String getCellName()
{
return "column footer";
}
});
verifyColumnHeights(table, verifier, new ColumnCellSelector()
{
@Override
public Cell getCell(Column column)
{
return column.getDetailCell();
}
@Override
public Cell getCell(ColumnGroup group)
{
return null;
}
@Override
public String getCellName()
{
return "detail";
}
});
}
protected abstract class BaseColumnCellSelector implements ColumnCellSelector
{
@Override
public Cell getCell(Column column)
{
return getCell((BaseColumn) column);
}
@Override
public Cell getCell(ColumnGroup group)
{
return getCell((BaseColumn) group);
}
protected abstract Cell getCell(BaseColumn column);
}
protected void verifyColumnHeights(TableComponent table,
JRVerifier verifier,
final ColumnCellSelector cellSelector)
{
final List> tableCellRows = new ArrayList<>();
ColumnVisitor cellCollector = new ColumnVisitor()
{
int rowIdx = 0;
protected List getRow()
{
int currentRowCount = tableCellRows.size();
if (rowIdx >= currentRowCount)
{
for (int i = currentRowCount; i <= rowIdx; i++)
{
tableCellRows.add(new ArrayList<>());
}
}
return tableCellRows.get(rowIdx);
}
@Override
public Void visitColumn(Column column)
{
Cell cell = cellSelector.getCell(column);
if (cell != null)
{
getRow().add(cell);
}
return null;
}
@Override
public Void visitColumnGroup(ColumnGroup columnGroup)
{
Cell cell = cellSelector.getCell(columnGroup);
if (cell != null)
{
getRow().add(cell);
}
int span = cell == null ? 0 : 1;
if (cell != null && cell.getRowSpan() != null && cell.getRowSpan() > 1)
{
span = cell.getRowSpan();
}
rowIdx += span;
for (BaseColumn subcolumn : columnGroup.getColumns())
{
subcolumn.visitColumn(this);
}
rowIdx -= span;
return null;
}
};
for (BaseColumn column : table.getColumns())
{
column.visitColumn(cellCollector);
}
boolean validRowHeights = true;
List rowHeights = new ArrayList<>(tableCellRows.size());
for (int rowIdx = 0; rowIdx < tableCellRows.size(); ++rowIdx)
{
Integer rowHeight = null;
// going back on rows in order to determine row height
int spanHeight = 0;
prevRowLoop:
for (int idx = rowIdx; idx >= 0; --idx)
{
for (Cell cell : tableCellRows.get(idx))
{
int rowSpan = cell.getRowSpan() == null ? 1 : cell.getRowSpan();
if (idx + rowSpan - 1 == rowIdx && cell.getHeight() != null)
{
rowHeight = cell.getHeight() - spanHeight;
break prevRowLoop;
}
}
if (rowIdx > 0)
{
spanHeight += rowHeights.get(rowIdx - 1);
}
}
if (rowHeight == null)
{
verifier.addBrokenRule("Unable to determine " + cellSelector.getCellName()
+ " row #" + (rowIdx + 1) + " height.",
table);
validRowHeights = false;
}
else
{
rowHeights.add(rowHeight);
}
}
// don't do any more verifications if row heights could not be determined
if (validRowHeights)
{
for (ListIterator> rowIt = tableCellRows.listIterator(); rowIt.hasNext();)
{
List row = rowIt.next();
int rowIdx = rowIt.previousIndex();
int rowHeight = rowHeights.get(rowIdx);
for (Cell cell : row)
{
Integer rowSpan = cell.getRowSpan();
Integer height = cell.getHeight();
if ((rowSpan == null || rowSpan >= 1)
&& height != null)
{
int span = rowSpan == null ? 1 : rowSpan;
if (rowIdx + span > tableCellRows.size())
{
verifier.addBrokenRule("Row span of " + cellSelector.getCellName()
+ " exceeds number of rows", cell);
}
else
{
int spanHeight = rowHeight;
for (int idx = 1; idx < span; ++idx)
{
spanHeight += rowHeights.get(rowIdx + idx);
}
if (cell.getHeight() != spanHeight)
{
verifier.addBrokenRule("Height " + cell.getHeight() + " of " + cellSelector.getCellName()
+ " does not match computed row height of " + spanHeight, cell);
}
}
}
}
}
}
}
}
| |