/*
* Copyright (C) 2010---2014 星星(wuweixing)<349446658@qq.com>
*
* This file is part of Wabacus
*
* Wabacus 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.wabacus.system.assistant;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.AcroFields.Item;
import com.wabacus.config.component.IComponentConfigBean;
import com.wabacus.config.component.application.report.AbsReportDataPojo;
import com.wabacus.config.component.application.report.ColBean;
import com.wabacus.config.component.application.report.ReportBean;
import com.wabacus.config.dataexport.PDFExportBean;
import com.wabacus.exception.WabacusRuntimeException;
import com.wabacus.system.ReportRequest;
import com.wabacus.system.component.IComponentType;
import com.wabacus.system.component.application.report.abstractreport.AbsReportType;
import com.wabacus.system.component.application.report.configbean.ColDisplayData;
import com.wabacus.util.Consts;
import com.wabacus.util.Tools;
public class PdfAssistant
{
private final static PdfAssistant instance=new PdfAssistant();
private final static Log log=LogFactory.getLog(PdfAssistant.class);
private BaseFont bfChinese=null;
private PdfAssistant()
{
try
{
bfChinese=BaseFont.createFont("STSong-Light","UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
}catch(Exception e)
{
throw new WabacusRuntimeException("获取PDF中文字体失败",e);
}
}
public static PdfAssistant getInstance()
{
return instance;
}
public BaseFont getBfChinese()
{
return bfChinese;
}
public ByteArrayOutputStream showReportDataOnPdfWithTpl(ReportRequest rrequest,IComponentConfigBean ccbean)
{
boolean ispdfprint=rrequest.isPdfPrintAction();
PDFExportBean pdfbean=null;
if(ispdfprint)
{
pdfbean=ccbean.getPdfPrintBean();
}else if(ccbean.getDataExportsBean()!=null)
{//是PDF导出,且配置了PDF的<dataexport/>
pdfbean=(PDFExportBean)ccbean.getDataExportsBean().getDataExportBean(Consts.DATAEXPORT_PDF);
}
if(pdfbean==null||pdfbean.getPdftemplate()==null||pdfbean.getPdftemplate().trim().equals("")) return null;
if(pdfbean.getLstIncludeApplicationids()==null||pdfbean.getLstIncludeApplicationids().size()==0) return null;
Map<String,AbsReportType> mReportTypeObjs=new HashMap<String,AbsReportType>();
IComponentType cctypeObj;
AbsReportType reportTypeObjTmp;
int maxrowcount=0;
for(String appidTmp:pdfbean.getLstIncludeApplicationids())
{//取到本组件导出PDF时所需的所有报表类型对象
if(mReportTypeObjs.containsKey(appidTmp)) continue;
cctypeObj=rrequest.getComponentTypeObj(appidTmp,null,false);
if(cctypeObj==null||!(cctypeObj instanceof AbsReportType)) continue;
reportTypeObjTmp=(AbsReportType)cctypeObj;
mReportTypeObjs.put(appidTmp,reportTypeObjTmp);
if(reportTypeObjTmp.getLstReportData()!=null&&reportTypeObjTmp.getLstReportData().size()>maxrowcount)
{
maxrowcount=reportTypeObjTmp.getLstReportData().size();
}
}
if(mReportTypeObjs.size()==0||maxrowcount==0) return null;
try
{
Document document=new Document();
ByteArrayOutputStream baosResult=new ByteArrayOutputStream();
PdfCopy pdfCopy=new PdfCopy(document,baosResult);
document.open();
for(int i=0;i<maxrowcount;i++)
{
addPdfPageToDocument(pdfCopy,showReportOneRowDataOnPdf(rrequest,mReportTypeObjs,ccbean,pdfbean,i));
}
document.close();
return baosResult;
}catch(Exception e)
{
throw new WabacusRuntimeException("导出"+ccbean.getPath()+"数据到pdf文件失败",e);
}
}
private ByteArrayOutputStream showReportOneRowDataOnPdf(ReportRequest rrequest,Map<String,AbsReportType> mReportTypeObjs,
IComponentConfigBean ccbean,PDFExportBean pdfbean,int rowidx) throws Exception
{
PdfReader pdfTplReader=null;
InputStream istream=null;
ByteArrayOutputStream baos=new ByteArrayOutputStream();
try
{
istream=WabacusAssistant.getInstance().readFile(pdfbean.getPdftemplate());
if(istream==null) return null;
pdfTplReader=new PdfReader(new BufferedInputStream(istream));
PdfStamper stamp=new PdfStamper(pdfTplReader,baos);
/* 取出报表模板中的所有字段 */
AcroFields form=stamp.getAcroFields();
form.addSubstitutionFont(bfChinese);
boolean flag=true;
if(pdfbean!=null&&pdfbean.getInterceptorObj()!=null)
{
flag=pdfbean.getInterceptorObj().beforeDisplayPdfPageWithTemplate(ccbean,mReportTypeObjs,rowidx,stamp);
}
if(flag)
{
Map<String,Item> mFields=form.getFields();
if(mFields!=null)
{
String fieldValueTmp=null;
for(String fieldNameTmp:mFields.keySet())
{
fieldValueTmp=getPdfFieldValueByName(rrequest,mReportTypeObjs,ccbean,fieldNameTmp,rowidx);//取出此域的真正内容
if(pdfbean!=null&&pdfbean.getInterceptorObj()!=null)
{
fieldValueTmp=pdfbean.getInterceptorObj().beforeDisplayFieldWithTemplate(ccbean,mReportTypeObjs,rowidx,stamp,
fieldNameTmp,fieldValueTmp);
}
if(fieldValueTmp!=null) form.setField(fieldNameTmp,fieldValueTmp);
}
}
}
if(pdfbean!=null&&pdfbean.getInterceptorObj()!=null)
{
pdfbean.getInterceptorObj().afterDisplayPdfPageWithTemplate(ccbean,mReportTypeObjs,rowidx,stamp);
}
stamp.setFormFlattening(true);
stamp.close();
}finally
{
try
{
if(istream!=null) istream.close();
}catch(IOException e)
{
e.printStackTrace();
}
if(pdfTplReader!=null) pdfTplReader.close();
}
return baos;
}
private String getPdfFieldValueByName(ReportRequest rrequest,Map<String,AbsReportType> mReportTypeObjs,IComponentConfigBean ccbean,
String fieldname,int rowidx)
{
if(fieldname==null||fieldname.trim().equals("")) return null;
if(WabacusAssistant.getInstance().isGetRequestContextValue(fieldname))
{//从request/session中取数据
return WabacusAssistant.getInstance().getRequestContextStringValue(rrequest,fieldname,"");
}
if(fieldname.indexOf(".")<=0) return null;
List<String> lstParts=Tools.parseStringToList(fieldname,".",false);
if(lstParts.size()==1) return null;
String reportid=lstParts.get(0);
AbsReportDataPojo dataObjTmp=null;
if(reportid.equals("this"))
{
if(!(ccbean instanceof ReportBean))
{
throw new WabacusRuntimeException("导出组件"+ccbean.getPath()+"到PDF失败,此组件不是报表,因此不能在其PDF模板中使用this");
}
reportid=ccbean.getId();
}
AbsReportType reportTypeObjTmp=mReportTypeObjs.get(reportid);
if(reportTypeObjTmp==null)
{
throw new WabacusRuntimeException("导出组件"+ccbean.getPath()+"到PDF文件失败,在其PDF模板中指定的ID为"+reportid+"的报表没有出现在其<dataexport/>的include属性中");
}
if(reportTypeObjTmp.getLstReportData()!=null&&reportTypeObjTmp.getLstReportData().size()>rowidx)
{
dataObjTmp=reportTypeObjTmp.getLstReportData().get(rowidx);
}
String part=lstParts.get(1);
if(part==null||part.trim().equals("")) return null;
if(part.equals("title"))
{
if(!rrequest.checkPermission(reportid,Consts.TITLE_PART,null,Consts.PERMISSION_TYPE_DISPLAY)) return null;//如果本报表不显示标题
if(lstParts.size()==2||!"subtitle".equals(lstParts.get(2)))
{
return reportTypeObjTmp.getReportBean().getTitle(rrequest);
}else
{
return reportTypeObjTmp.getReportBean().getSubtitle(rrequest);
}
}else if(part.equals("data"))
{
if(lstParts.size()==2)
{
log.warn("导出组件"+ccbean.getPath()+"到PDF文件失败,在其PDF模板中指定的"+fieldname+"不合法");
return null;
}
String colproperty=lstParts.get(2);
if(colproperty==null||colproperty.trim().equals(""))
{
log.warn("导出组件"+ccbean.getPath()+"到PDF文件失败,在其PDF模板中指定的"+fieldname+"不合法");
return null;
}
ColBean cbean=reportTypeObjTmp.getReportBean().getDbean().getColBeanByColProperty(colproperty);
if(cbean==null)
{
throw new WabacusRuntimeException("导出报表"+reportTypeObjTmp.getReportBean().getPath()+"到PDF文件失败,此报表不存在property为"+colproperty+"的<col/>");
}
if(rrequest.getCdb(reportid).getColDisplayModeAfterAuthorize(cbean,false)<=0) return null;
ColDisplayData colDisplayData=null;
if(lstParts.size()==3||!"label".equals(lstParts.get(3)))
{//显示此列的数据部分
String col_displayvalue=dataObjTmp.getColStringValue(cbean);
colDisplayData=ColDisplayData.getColDataFromInterceptor(reportTypeObjTmp,cbean,dataObjTmp,rowidx,null,col_displayvalue);
}else
{
colDisplayData=ColDisplayData.getColDataFromInterceptor(reportTypeObjTmp,cbean,null,-1,null,cbean.getLabel(rrequest));
}
return colDisplayData.getValue();
}else
{
log.warn("导出组件"+ccbean.getPath()+"到PDF文件失败,在其PDF模板中指定的"+fieldname+"不合法");
return null;
}
}
public void addPdfPageToDocument(PdfCopy pdfCopy,ByteArrayOutputStream baos)
{
if(baos==null) return;
PdfReader readerTmp=null;
try
{
readerTmp=new PdfReader(baos.toByteArray());
for(int i=1,len=readerTmp.getNumberOfPages();i<=len;i++)
{
pdfCopy.addPage(pdfCopy.getImportedPage(readerTmp,i));
}
}catch(Exception e)
{
throw new WabacusRuntimeException("写PDF文件失败",e);
}finally
{
try
{
if(baos!=null) baos.close();
}catch(IOException e)
{
e.printStackTrace();
}
readerTmp.close();
}
}
}