package org.akaza.openclinica.bean.service;
import org.akaza.openclinica.dao.core.CoreResources;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.FormattingResults;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.apps.PageSequenceResults;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Source;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.sax.SAXResult;
/**
* PdfProcessingFunction, a post-processing function for Extract Data
* By Tom Hickerson, 09/2010
* @author thickerson
*
*/
public class PdfProcessingFunction extends ProcessingFunction {
protected final Logger logger = LoggerFactory.getLogger(getClass().getName());
public PdfProcessingFunction() {
fileType = "pdf";
}
/*
* The run() method. Note that we will assume that all variables (i.e. file
* paths) are set here.
*
* Running this will open a file stream, perform a transform with the *.fo
* file (note, does not necessarily have to have a *.fo suffix) and then
* return a success/fail message.
* (non-Javadoc)
* @see org.akaza.openclinica.bean.service.ProcessingInterface#run()
*/
public ProcessingResultType run() {
// FopFactory fopFactory = FopFactory.newInstance();
FopFactory fopFactory = FopFactory.newInstance();
// FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
OutputStream out = null;
File outputFile =null;
String zipName = "_";
File xslFile = null;
try
{
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
//set the renderer to be PDF
// the expected sequence here will be xml -> xslt -> fo -> pdf
// where fo is the transformed file
File procExportDirectory;
File oldFiles[] = null;
if(this.getExportFileName()!=null && this.getLocation()!=null)
{
procExportDirectory = new File(this.getLocation());
if(!procExportDirectory.isDirectory())
{
procExportDirectory.mkdir();
}
outputFile = new File(procExportDirectory+File.separator+this.getExportFileName()+".pdf");
zipName = (procExportDirectory+File.separator+this.getExportFileName()+".zip");
}
else
{
outputFile = new File(this.getODMXMLFileName() + ".pdf");//getODMFILENAme is a path of .fo object
zipName = this.getODMXMLFileName() + ".zip";
}
xslFile = new File(this.getTransformFileName());//transformfilename is abs path+file name(.fo) transformFileName and odmxmlfile name are same?
out = new FileOutputStream(outputFile);
out = new BufferedOutputStream(out);
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); // identity transformer
Source src = new StreamSource(xslFile);
// Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
// Start XSLT transformation and FOP processing
transformer.transform(src, res);
// Result processing
FormattingResults foResults = fop.getResults();
java.util.List pageSequences = foResults.getPageSequences();
for (java.util.Iterator it = pageSequences.iterator(); it.hasNext();) {
PageSequenceResults pageSequenceResults = (PageSequenceResults)it.next();
logger.debug("PageSequence "
+ (String.valueOf(pageSequenceResults.getID()).length() > 0
? pageSequenceResults.getID() : "<no id>")
+ " generated " + pageSequenceResults.getPageCount() + " pages.");
}
logger.debug("Generated " + foResults.getPageCount() + " pages in total.");
out.close();
if(isZip())
{
if(outputFile!=null)
{
ZipOutputStream zipOut = null;
FileInputStream fis = null;
try{
fis = new FileInputStream(outputFile);
zipOut = new ZipOutputStream(new FileOutputStream(new File( zipName)));
zipOut.putNextEntry(new ZipEntry(outputFile.getName()));
int bytesRead;
byte[] buff = new byte[512];
while ((bytesRead = fis.read(buff)) != -1) {
zipOut.write(buff, 0, bytesRead);
}
zipOut.closeEntry();
zipOut.finish();
}catch(Exception e){
e.printStackTrace();
}finally{
if(zipOut!=null)zipOut.close();
if(fis!=null)fis.close();
}
}
setArchivedFileName(new File(zipName).getName());
}
else
setArchivedFileName(outputFile.getName());
} catch (Exception e) {
e.printStackTrace();
ProcessingResultType resultError = ProcessingResultType.FAIL;
resultError.setUrl(CoreResources.getField("sysURL.base") + "ViewDatasets"); // view datasets page
resultError.setArchiveMessage("Failure thrown: " + e.getMessage());
resultError.setDescription("Your job failed with the message of: " + e.getMessage());
return resultError;
} finally {
}
if(isDeleteOld())
{
deleteOldFiles(this.getOldFiles(),outputFile,zipName);
}
if(isZip())
{
outputFile.delete();
}
//delete intermediatory .fo file
if(xslFile!=null)xslFile.delete();
// otherwise return a success with the URL link
ProcessingResultType resultSuccess = ProcessingResultType.SUCCESS;
resultSuccess.setUrl(CoreResources.getField("sysURL.base") +
"AccessFile?fileId="); // to the pdf
resultSuccess.setArchiveMessage("Success");
resultSuccess.setDescription("Your job succeeded please find the URL below");
return resultSuccess;
}
private void deleteOldFiles(File[] oldFiles,File outputFile, String zipFile) {
//File[] files = complete.listFiles();
File zip= new File(zipFile);
for(int i=0;i<oldFiles.length;i++)
{
if(!outputFile.getName().equals(oldFiles[i].getName())&& !zip.getName().equals(oldFiles[i].getName()))
oldFiles[i].delete();
}
}
}