package com.kodcu.service.convert.pdf;
import com.kodcu.controller.ApplicationController;
import com.kodcu.other.Current;
import com.kodcu.other.ExtensionFilters;
import com.kodcu.other.IOHelper;
import com.kodcu.service.DirectoryService;
import com.kodcu.service.PathResolverService;
import com.kodcu.service.ThreadService;
import com.kodcu.service.convert.DocumentConverter;
import com.kodcu.service.convert.docbook.DocBookConverter;
import com.kodcu.service.ui.IndikatorService;
import org.apache.fop.apps.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import java.util.function.Consumer;
import static java.nio.file.StandardOpenOption.*;
/**
* Created by usta on 09.04.2015.
*/
@Component
public class PdfBookConverter implements DocumentConverter<String> {
private final Logger logger = LoggerFactory.getLogger(PdfBookConverter.class);
private final ApplicationController asciiDocController;
private final DocBookConverter docBookConverter;
private final IndikatorService indikatorService;
private final ThreadService threadService;
private final DirectoryService directoryService;
private final Current current;
private final PathResolverService pathResolverService;
private FopFactory fopFactory;
@Autowired
public PdfBookConverter(final ApplicationController asciiDocController, final DocBookConverter docBookConverter,
final IndikatorService indikatorService,
final ThreadService threadService, final DirectoryService directoryService, final Current current, PathResolverService pathResolverService) {
this.asciiDocController = asciiDocController;
this.docBookConverter = docBookConverter;
this.indikatorService = indikatorService;
this.threadService = threadService;
this.directoryService = directoryService;
this.current = current;
this.pathResolverService = pathResolverService;
}
@Override
public void convert(boolean askPath, Consumer<String>... nextStep) {
final Path currentTabPath = current.currentPath().get();
final Path currentTabPathDir = currentTabPath.getParent();
final Path configPath = asciiDocController.getConfigPath();
threadService.runActionLater(() -> {
final Path pdfPath = directoryService.getSaveOutputPath(ExtensionFilters.PDF, askPath);
docBookConverter.convert(false, docbook -> {
indikatorService.startProgressBar();
logger.debug("PDF conversion started");
final Path docbookTempfile = IOHelper.createTempFile(currentTabPathDir, ".xml");
IOHelper.writeToFile(docbookTempfile, docbook, CREATE, WRITE, TRUNCATE_EXISTING);
try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(pdfPath.toFile()));) {
// Setup XSLT
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(configPath.resolve("docbook-config/fo-pdf.xsl").toFile()));
transformer.setParameter("highlight.xslthl.config", configPath.resolve("docbook-config/xslthl-config.xml").toUri().toASCIIString());
transformer.setParameter("admon.graphics.path", configPath.resolve("docbook/images/").toUri().toASCIIString());
transformer.setParameter("callout.graphics.path", configPath.resolve("docbook/images/callouts/").toUri().toASCIIString());
if (Objects.isNull(fopFactory)) {
fopFactory = FopFactory.newInstance(configPath.resolve("docbook-config/fop.xconf.xml").toFile());
}
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, outputStream);
// Setup input for XSLT transformation
Source src = new StreamSource(docbookTempfile.toFile());
// Resulting SAX events (the generated FO) must be piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());
// Step 6: Start XSLT transformation and FOP processing
transformer.transform(src, res);
Files.deleteIfExists(docbookTempfile);
// Result processing
FormattingResults foResults = fop.getResults();
logger.info("Generated {} pages in total.", foResults.getPageCount());
} catch (Exception e) {
logger.error("Problem occured while converting to PDF", e);
} finally {
indikatorService.stopProgressBar();
logger.debug("PDF conversion ended");
asciiDocController.addRemoveRecentList(pdfPath);
}
});
});
}
}