Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 

467 Zeilen
15 KiB

/*******************************************************************************
* Copyright 2017 Bstek
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
******************************************************************************/
package com.bstek.ureport.build;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.bstek.ureport.Utils;
import com.bstek.ureport.build.cell.CellBuilder;
import com.bstek.ureport.build.cell.NoneExpandBuilder;
import com.bstek.ureport.build.cell.down.DownExpandBuilder;
import com.bstek.ureport.build.cell.right.RightExpandBuilder;
import com.bstek.ureport.build.paging.BasePagination;
import com.bstek.ureport.build.paging.Page;
import com.bstek.ureport.definition.Band;
import com.bstek.ureport.definition.CellStyle;
import com.bstek.ureport.definition.Expand;
import com.bstek.ureport.definition.Orientation;
import com.bstek.ureport.definition.PagingMode;
import com.bstek.ureport.definition.Paper;
import com.bstek.ureport.definition.ReportDefinition;
import com.bstek.ureport.definition.datasource.BuildinDatasource;
import com.bstek.ureport.definition.datasource.BuildinDatasourceDefinition;
import com.bstek.ureport.definition.datasource.DatasourceDefinition;
import com.bstek.ureport.definition.datasource.DatasourceProvider;
import com.bstek.ureport.definition.datasource.JdbcDatasourceDefinition;
import com.bstek.ureport.definition.datasource.SpringBeanDatasourceDefinition;
import com.bstek.ureport.exception.ReportComputeException;
import com.bstek.ureport.model.Cell;
import com.bstek.ureport.model.Column;
import com.bstek.ureport.model.Report;
import com.bstek.ureport.model.Row;
/**
* @author Jacky.gao
* @since 2016年11月1日
*/
public class ReportBuilder extends BasePagination implements ApplicationContextAware{
public static final String BEAN_ID="ureport.reportBuilder";
private static final Logger log=Logger.getGlobal();
private ApplicationContext applicationContext;
private Map<String,DatasourceProvider> datasourceProviderMap=new HashMap<String,DatasourceProvider>();
private Map<Expand,CellBuilder> cellBuildersMap=new HashMap<Expand,CellBuilder>();
private NoneExpandBuilder noneExpandBuilder=new NoneExpandBuilder();
public ReportBuilder() {
cellBuildersMap.put(Expand.Right,new RightExpandBuilder());
cellBuildersMap.put(Expand.Down,new DownExpandBuilder());
cellBuildersMap.put(Expand.None,noneExpandBuilder);
}
public Report buildReport(ReportDefinition reportDefinition,Map<String,Object> parameters) {
Report report = reportDefinition.newReport();
Map<String,Dataset> datasetMap=buildDatasets(reportDefinition, parameters, applicationContext);
Context context = new Context(this,report,datasetMap,applicationContext,parameters);
long start=System.currentTimeMillis();
List<Cell> cells=new ArrayList<Cell>();
cells.add(report.getRootCell());
do {
buildCell(context,cells);
cells = context.nextUnprocessedCells();
} while (cells != null);
doFillBlankRows(report,context);
recomputeCells(report,context);
long end=System.currentTimeMillis();
log.info("Report compute completed:"+(end-start)+"ms");
return report;
}
public void buildCell(Context context,List<Cell> cells){
if(cells==null){
cells=context.nextUnprocessedCells();
}
if(cells==null){
return;
}
for(Cell cell:cells){
List<BindData> dataList=context.buildCellData(cell);
cell.setProcessed(true);
int size=dataList.size();
Cell lastCell=cell;
if(size==1){
lastCell=noneExpandBuilder.buildCell(dataList, cell, context);
}else if(size>1){
CellBuilder cellBuilder=cellBuildersMap.get(cell.getExpand());
lastCell=cellBuilder.buildCell(dataList,cell, context);
}
if(lastCell.isFillBlankRows() && lastCell.getMultiple()>0){
int result=size % lastCell.getMultiple();
if(result>0){
int value=lastCell.getMultiple()-result;
context.addFillBlankRow(lastCell.getRow(), value);
}
}
}
}
private Map<String,Dataset> buildDatasets(ReportDefinition reportDefinition,Map<String,Object> parameters,ApplicationContext applicationContext){
Map<String,Dataset> datasetMap=new HashMap<String,Dataset>();
List<DatasourceDefinition> datasources=reportDefinition.getDatasources();
if(datasources==null){
return datasetMap;
}
for(DatasourceDefinition dsDef:datasources){
if(dsDef instanceof JdbcDatasourceDefinition){
String dsName=dsDef.getName();
Connection conn=null;
if(datasourceProviderMap.containsKey(dsName)){
conn=datasourceProviderMap.get(dsName).getConnection();
}
JdbcDatasourceDefinition ds=(JdbcDatasourceDefinition)dsDef;
List<Dataset> ls=ds.buildDatasets(conn, parameters);
if(ls!=null){
for(Dataset dataset:ls){
datasetMap.put(dataset.getName(), dataset);
}
}
}else if(dsDef instanceof SpringBeanDatasourceDefinition){
SpringBeanDatasourceDefinition ds=(SpringBeanDatasourceDefinition)dsDef;
List<Dataset> ls=ds.getDatasets(applicationContext, parameters);
if(ls!=null){
for(Dataset dataset:ls){
datasetMap.put(dataset.getName(), dataset);
}
}
}else if(dsDef instanceof BuildinDatasourceDefinition){
String dsName=dsDef.getName();
Connection conn=null;
if(datasourceProviderMap.containsKey(dsName)){
conn=datasourceProviderMap.get(dsName).getConnection();
}
for(BuildinDatasource datasource:Utils.getBuildinDatasources()){
if(datasource.name().equals(dsName)){
conn=datasource.getConnection();
break;
}
}
if(conn==null){
throw new ReportComputeException("Buildin datasource ["+dsName+"] not exist.");
}
BuildinDatasourceDefinition ds=(BuildinDatasourceDefinition)dsDef;
List<Dataset> ls=ds.buildDatasets(conn, parameters);
if(ls!=null){
for(Dataset dataset:ls){
datasetMap.put(dataset.getName(), dataset);
}
}
}
}
return datasetMap;
}
private void doFillBlankRows(Report report,Context context){
List<Column> columns=report.getColumns();
Map<Row, Map<Column, Cell>> rowMap=report.getRowColCellMap();
Map<Row, Integer> map=context.getFillBlankRowsMap();
List<Row> newRowList=new ArrayList<Row>();
for(Row row:map.keySet()){
Map<Column,Cell> cellMap=rowMap.get(row);
int size=map.get(row);
for(int i=0;i<size;i++){
Row newRow=row.newRow();
newRow.setBand(null);
newRowList.add(newRow);
Map<Column,Cell> newCellMap=new HashMap<Column,Cell>();
rowMap.put(newRow, newCellMap);
for(Column col:columns){
Cell newCell=newBlankCell(cellMap, col,report);
newCell.setRow(newRow);
newRow.getCells().add(newCell);
newCellMap.put(col, newCell);
}
}
if(newRowList.size()>0){
int rowNumber=row.getRowNumber();
report.insertRows(rowNumber+1, newRowList);
newRowList.clear();
}
}
}
private Cell newBlankCell(Map<Column,Cell> cellMap,Column column,Report report){
if(cellMap!=null){
Cell cell=cellMap.get(column);
if(cell!=null){
Cell newCell=new Cell();
newCell.setData("");
newCell.setConditionPropertyItems(cell.getConditionPropertyItems());
report.addLazyCell(newCell);
newCell.setCellStyle(cell.getCellStyle());
newCell.setName(cell.getName());
newCell.setColumn(column);
column.getCells().add(newCell);
Cell leftParent=cell.getLeftParentCell();
if(leftParent!=null){
newCell.setLeftParentCell(leftParent);
leftParent.addRowChild(newCell);
}
Cell topParent=cell.getTopParentCell();
if(topParent!=null){
newCell.setTopParentCell(topParent);
topParent.addColumnChild(newCell);
}
return newCell;
}
}
Cell newCell=new Cell();
newCell.setData("");
newCell.setCellStyle(new CellStyle());
newCell.setName("");
newCell.setColumn(column);
column.getCells().add(newCell);
return newCell;
}
private void recomputeCells(Report report,Context context){
List<Cell> lazyCells=report.getLazyComputeCells();
for(Cell cell:lazyCells){
cell.doCompute(context);
}
context.setDoPaging(true);
List<Row> rows=report.getRows();
int rowSize=rows.size();
Paper paper = report.getPaper();
PagingMode pagingMode=paper.getPagingMode();
List<Row> headerRows=report.getHeaderRepeatRows();
List<Row> footerRows=report.getFooterRepeatRows();
List<Row> titleRows=report.getTitleRows();
List<Row> summaryRows=report.getSummaryRows();
List<Page> pages=new ArrayList<Page>();
List<Row> pageRows=new ArrayList<Row>();
int pageIndex=1;
List<Row> pageRepeatHeaders=new ArrayList<Row>();
List<Row> pageRepeatFooters=new ArrayList<Row>();
pageRepeatHeaders.addAll(headerRows);
pageRepeatFooters.addAll(footerRows);
if(pagingMode.equals(PagingMode.fitpage)){
int height=paper.getHeight()-paper.getBottomMargin()-paper.getTopMargin();
if(paper.getOrientation().equals(Orientation.landscape)){
height=paper.getWidth()-paper.getBottomMargin()-paper.getTopMargin();
}
int repeatHeaderRowHeight=report.getRepeatHeaderRowHeight(),repeatFooterRowHeight=report.getRepeatFooterRowHeight();
int titleRowHeight=report.getTitleRowsHeight();
int rowHeight=titleRowHeight+repeatHeaderRowHeight+repeatFooterRowHeight;
for(int i=0;i<rowSize;i++){
Row row=rows.get(i);
int rowRealHeight=row.getRealHeight();
Band band=row.getBand();
if(band!=null && rowRealHeight>0){
String rowKey=row.getRowKey();
int index=-1;
if(band.equals(Band.headerrepeat)){
for(int j=0;j<pageRepeatHeaders.size();j++){
Row headerRow=pageRepeatHeaders.get(j);
if(headerRow.getRowKey().equals(rowKey)){
index=j;
break;
}
}
pageRepeatHeaders.remove(index);
pageRepeatHeaders.add(index,row);
}else if(band.equals(Band.footerrepeat)){
for(int j=0;j<pageRepeatFooters.size();j++){
Row footerRow=pageRepeatFooters.get(j);
if(footerRow.getRowKey().equals(rowKey)){
index=j;
break;
}
}
pageRepeatFooters.remove(index);
pageRepeatFooters.add(index,row);
}
}
if(rowRealHeight>1 && band==null){
rowHeight+=rowRealHeight;
pageRows.add(row);
boolean overflow=false;
if((i+1)<rows.size()){
Row nextRow=rows.get(i+1);
if((rowHeight+nextRow.getRealHeight()) > height){
overflow=true;
}
}
if(!overflow && row.isPageBreak()){
overflow=true;
}
if(overflow){
Page newPage=buildPage(pageRows,pageRepeatHeaders,pageRepeatFooters,titleRows,pageIndex,report);
pageIndex++;
pages.add(newPage);
rowHeight=repeatHeaderRowHeight+repeatFooterRowHeight;
pageRows=new ArrayList<Row>();
}
}
processRowColumn(report, i, row);
}
if(pageRows.size()>0){
Page newPage=buildPage(pageRows,pageRepeatHeaders,pageRepeatFooters,titleRows,pageIndex,report);
pages.add(newPage);
}
buildPageHeaderFooter(pages, report);
}else{
int fixRows=paper.getFixRows()-headerRows.size()-footerRows.size();
if(fixRows<0){
fixRows=1;
}
for(int i=0;i<rowSize;i++){
Row row=rows.get(i);
processRowColumn(report, i, row);
int height=row.getRealHeight();
Band band=row.getBand();
if(band!=null && height>0){
String rowKey=row.getRowKey();
int index=-1;
if(band.equals(Band.headerrepeat)){
for(int j=0;j<pageRepeatHeaders.size();j++){
Row headerRow=pageRepeatHeaders.get(j);
if(headerRow.getRowKey().equals(rowKey)){
index=j;
break;
}
}
pageRepeatHeaders.remove(index);
pageRepeatHeaders.add(index,row);
}else if(band.equals(Band.footerrepeat)){
for(int j=0;j<pageRepeatFooters.size();j++){
Row footerRow=pageRepeatFooters.get(j);
if(footerRow.getRowKey().equals(rowKey)){
index=j;
break;
}
}
pageRepeatFooters.remove(index);
pageRepeatFooters.add(index,row);
}
if(index==-1){
throw new ReportComputeException("Invalid row["+band+"] with key "+rowKey+".");
}
}
if(height<1 || band!=null){
continue;
}
pageRows.add(row);
if((pageRows.size()+footerRows.size()) >= fixRows){
pageRows.addAll(footerRows);
Page newPage=buildPage(pageRows,pageRepeatHeaders,pageRepeatFooters,titleRows,pageIndex,report);
pageIndex++;
pages.add(newPage);
pageRows=new ArrayList<Row>();
}
}
if(pageRows.size()>0){
pageRows.addAll(footerRows);
Page newPage=buildPage(pageRows,pageRepeatHeaders,pageRepeatFooters,titleRows,pageIndex,report);
pages.add(newPage);
}
buildPageHeaderFooter(pages, report);
}
buildSummaryRows(summaryRows, pages);
report.setPages(pages);
}
private void processRowColumn(Report report, int i, Row row) {
Map<Row, Map<Column, Cell>> cellMap=report.getRowColCellMap();
Map<Column,Cell> map=cellMap.get(row);
if(map==null){
return;
}
List<Row> rows=report.getRows();
List<Column> columns=report.getColumns();
int colSize=columns.size();
for(int j=0;j<colSize;j++){
Column col=columns.get(j);
if(col==null){
continue;
}
Cell cell=map.get(col);
if(cell==null){
continue;
}
int colWidth=col.getWidth();
int colSpan=cell.getColSpan();
if(colWidth<1){
if(colSpan>1){
colSpan--;
if(colSpan<2)colSpan=0;
cell.setColSpan(colSpan);
Column nextCol=columns.get(j+1);
map.put(nextCol, cell);
}
map.remove(col);
}else{
if(colSpan>1){
int start=j+1,end=j+colSpan;
for(int num=start;num<end;num++){
Column nextCol=columns.get(num);
if(nextCol.getWidth()<1){
colSpan--;
}
}
if(colSpan<2){
colSpan=0;
}
cell.setColSpan(colSpan);
}
}
int rowHeight=row.getRealHeight();
int rowSpan=cell.getRowSpan();
if(rowHeight<1){
if(rowSpan>1){
rowSpan--;
if(rowSpan<2)rowSpan=0;
cell.setRowSpan(rowSpan);
Row nextRow=rows.get(i+1);
Map<Column,Cell> cmap=cellMap.get(nextRow);
cmap.put(col, cell);
}
}else{
if(rowSpan>1){
int start=i+1,end=i+rowSpan;
for(int num=start;num<end;num++){
Row nextRow=rows.get(num);
if(nextRow.getRealHeight()<1){
rowSpan--;
}
}
if(rowSpan<2){
rowSpan=0;
}
cell.setRowSpan(rowSpan);
}
}
}
if(row.getRealHeight()<1){
cellMap.remove(row);
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
Collection<DatasourceProvider> datasourceProviders=applicationContext.getBeansOfType(DatasourceProvider.class).values();
for(DatasourceProvider dp: datasourceProviders){
datasourceProviderMap.put(dp.getName(), dp);
}
new Splash().doPrint();
}
}