Files
OpenPDF-Integration/PdfConverter.java

336 lines
12 KiB
Java

package com.example.reporting.services.impl.pdf;
import static com.example.reporting.util.DateUtil.formatDate;
import static com.example.reporting.util.Constants.MARGIN_2;
import static com.example.reporting.util.Constants.MARGIN_2_9;
import static com.example.reporting.util.Constants.WHITE_COLOR;
import static com.example.reporting.util.Constants.GREEN_COLOR;
import static com.example.reporting.util.Constants.LIGHTEST_GREEN_COLOR;
import static com.example.reporting.util.PdfUtil.getPdfPTable;
import static com.example.reporting.util.PdfUtil.getPdfPCellSpaningAcross;
import static com.example.reporting.util.PdfUtil.getPdfPCell;
import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.imageio.ImageIO;
import org.springframework.http.ResponseEntity;
import com.lowagie.text.BadElementException;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.Image;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfTemplate;
import com.lowagie.text.pdf.PdfWriter;
import com.example.reporting.dto.database.ReportDto;
import com.example.reporting.dto.database.TeamDto;
import com.example.reporting.services.database.ITeamService;
import com.example.reporting.util.DateUtil;
import com.example.reporting.util.ReportUtil;
import com.example.reporting.util.NumberUtils;
import com.example.reporting.util.SessionUtil;
/**
* Abstract class for PDF conversion.
*
* @param <P> the type of the parameter used for conversion
*/
public abstract class PdfConverter<P extends PdfParameter> {
protected final SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
protected final SimpleDateFormat dateFormatSimple = new SimpleDateFormat("dd.MM.yyyy");
protected final SimpleDateFormat timeFormatSimple = new SimpleDateFormat("HH:mm");
protected final SimpleDateFormat dateTimeFormatSimple = new SimpleDateFormat("dd.MM.yyyy HH:mm");
protected BaseFont baseFont;
protected final Font fontBold22;
protected final Font fontBold16;
protected final Font fontBold14;
protected final Font font14;
protected final Font font12;
protected final Font fontBold9;
protected final Font fontBold10;
protected final Font font10;
protected Color conditionalColorStatus;
protected Color conditionalColorTeam;
protected Color conditionalColorUnit;
protected Color conditionalColorId;
protected final Document document = new Document();
protected final ByteArrayOutputStream baos = new ByteArrayOutputStream();
protected PdfConverter() throws DocumentException, IOException {
try {
// loading DejaVu from resources
this.baseFont = BaseFont.createFont("font/DejaVuSans.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
} catch (DocumentException | IOException e) {
// fallback to Helvetica if loading of DejaVu fails
this.baseFont = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
}
this.fontBold22 = new Font(this.baseFont, 22, Font.BOLD);
this.fontBold16 = new Font(this.baseFont, 16, Font.BOLD);
this.fontBold14 = new Font(this.baseFont, 14, Font.BOLD);
this.font14 = new Font(this.baseFont, 14, Font.NORMAL);
this.font12 = new Font(this.baseFont, 12, Font.NORMAL);
this.fontBold9 = new Font(this.baseFont, 9, Font.BOLD);
this.fontBold10 = new Font(this.baseFont, 10, Font.BOLD);
this.font10 = new Font(this.baseFont, 10, Font.NORMAL);
}
/**
* This class is used to create a header and footer for the PDF document.
*/
public static class HeaderFooterPageEvent extends PdfPageEventHelper {
private String headerText;
private Image headerImage;
private int currentPageNumber;
private BaseFont baseFont;
private PdfTemplate totalPageTemplate;
private String entityId;
/**
* Constructor for HeaderFooterPageEvent.
*
* @param headerText the text to be displayed in the header
* @param baseFont the font to be used for the header text
* @param headerImage the image to be displayed in the header
* @param entityId the ID of the entity
* @throws BadElementException if there is an error
*/
public HeaderFooterPageEvent(String headerText, BaseFont baseFont, Image headerImage, String entityId) {
this.headerText = headerText;
this.headerImage = headerImage;
this.currentPageNumber = 0;
this.baseFont = baseFont;
this.entityId = entityId;
}
@Override
public void onOpenDocument(PdfWriter writer, Document document) {
this.totalPageTemplate = writer.getDirectContent().createTemplate(50, 50);
}
@Override
public void onEndPage(PdfWriter writer, Document document) {
PdfContentByte cb = writer.getDirectContent();
// Increment the current page number
this.currentPageNumber++;
String[] lines = headerText.split("\\|");
// Split the header text if it contains a pipe character
if (currentPageNumber == 1) {
// Page text for title page
cb.beginText();
cb.setFontAndSize(this.baseFont, 8);
String entityText = "Entity-ID: " + this.entityId;
cb.setTextMatrix(MARGIN_2, (MARGIN_2_9 / 2));
cb.showText(entityText);
cb.endText();
} else {
// Header for regular pages - first line
cb.beginText();
cb.setFontAndSize(this.baseFont, 10);
cb.setTextMatrix(MARGIN_2, document.getPageSize().getHeight() - (MARGIN_2_9 / 2));
cb.showText(lines[0]);
cb.endText();
// Second line (if exists)
if (lines.length > 1) {
cb.beginText();
cb.setFontAndSize(this.baseFont, 10);
cb.setTextMatrix(MARGIN_2, document.getPageSize().getHeight() - (MARGIN_2_9 / 2) - 12);
cb.showText(lines[1]);
cb.endText();
}
// Header image for regular pages
float imageX = document.getPageSize().getWidth() - headerImage.getScaledWidth() - MARGIN_2;
headerImage.setAbsolutePosition(imageX, document.getPageSize().getHeight() - (MARGIN_2_9 / 2 + 10));
cb.addImage(headerImage);
// Footer for regular pages
cb.beginText();
cb.setFontAndSize(this.baseFont, 8);
String footerText = "Page " + currentPageNumber + " of ";
// Calculate the width of the footer text
float textWidth = baseFont.getWidthPoint(footerText, 8);
float rightAlignX = document.getPageSize().getWidth() - textWidth - MARGIN_2 - 11;
cb.setTextMatrix(rightAlignX, (MARGIN_2_9 / 2));
cb.showText(footerText);
cb.endText();
cb.addTemplate(totalPageTemplate, rightAlignX + textWidth, (MARGIN_2_9 / 2));
cb.beginText();
cb.setFontAndSize(this.baseFont, 8);
String entityText = "Entity-ID: " + this.entityId;
cb.setTextMatrix(MARGIN_2, (MARGIN_2_9 / 2));
cb.showText(entityText);
cb.endText();
}
}
@Override
public void onCloseDocument(PdfWriter writer, Document document) {
totalPageTemplate.beginText();
totalPageTemplate.setFontAndSize(baseFont, 8);
totalPageTemplate.setTextMatrix(0, 0);
totalPageTemplate.showText(String.valueOf(currentPageNumber));
totalPageTemplate.endText();
}
}
protected void generateTitlePage(ReportDto reportDto, PdfWriter writer) throws IOException {
try (InputStream imageStream = getClass().getClassLoader().getResourceAsStream("logo/logo.png")) {
Image logoImage = Image.getInstance(ImageIO.read(imageStream), null);
logoImage.scaleToFit(154, 25); // Resize the image if necessary
// Create a clone of the image for the header/footer
Image headerLogoImage = Image.getInstance(logoImage);
writer.setPageEvent(new HeaderFooterPageEvent(getHeaderText(reportDto), this.baseFont,
headerLogoImage, reportDto.getEntityId())); // Pass the logo image
document.setMargins(MARGIN_2, MARGIN_2, MARGIN_2_9, MARGIN_2);
document.open();
logoImage.setAlignment(Element.ALIGN_LEFT);
document.add(logoImage);
document.add(new Paragraph("\n", fontBold22));
// Title
Paragraph title = getPdfTitle(reportDto);
title.setAlignment(Element.ALIGN_CENTER);
document.add(title);
document.add(new Paragraph("\n", font14)); // Add a blank line
// Owner
generateParagraphWithBlankLine("Owner: " + reportDto.getOwnerName());
// Location
generateParagraphWithBlankLine("Location: " + reportDto.getLocationName());
// Entity name
generateParagraphWithBlankLine("Entity Name: " + reportDto.getEntityName());
// Unit type
generateParagraphWithBlankLine("Unit Type: " + reportDto.getUnitType());
// Version
generateParagraphWithBlankLine("Version: " + reportDto.getVersion());
getTeamDetails(reportDto);
// Query date
generateParagraphWithBlankLine("Query Date: " + formatDate(new Date(), dateFormat));
// Query by
generateParagraphWithBlankLine("Query By: " + SessionUtil.getCurrentSession().getCurrentUser().getFullname());
// Force a new page
document.newPage();
}
}
protected void generateStatusPage(ReportDto reportDto) {
// Status title
Paragraph statusTitle = new Paragraph("STATUS", fontBold16);
statusTitle.setAlignment(Element.ALIGN_LEFT);
document.add(statusTitle);
// Status Table
PdfPTable statusTable = getPdfPTable(2);
// Add headers to the table
statusTable.addCell(getPdfPCellSpaningAcross("Processing Status", fontBold14, GREEN_COLOR, 2)); // header
// row 1
statusTable.addCell(getPdfPCell("Version", fontBold10, WHITE_COLOR));
statusTable.addCell(
getPdfPCell(NumberUtils.getStringFromBigDecimal(reportDto.getVersion()), font10, WHITE_COLOR));
// row 2
statusTable.addCell(getPdfPCell("Status", fontBold10, LIGHTEST_GREEN_COLOR));
getReportStatus(reportDto, statusTable);
this.conditionalColorStatus = WHITE_COLOR;
this.conditionalColorTeam = WHITE_COLOR;
// row 3
getTeamDetails(reportDto, statusTable, conditionalColorTeam);
statusTable.addCell(getPdfPCell("Submission Date", fontBold10, conditionalColorStatus));
statusTable.addCell(getPdfPCell(DateUtil.formatDate(reportDto.getSubmissionDate(), dateTimeFormatSimple),
font10, conditionalColorStatus));
document.add(statusTable);
// Force a new page
document.newPage();
}
protected void getReportStatus(ReportDto reportDto, PdfPTable statusTable) {
statusTable.addCell(getPdfPCell(ReportUtil.convertStatusToString(reportDto.getStatus()),
font10, LIGHTEST_GREEN_COLOR));
}
protected void getTeamDetails(ReportDto reportDto, PdfPTable statusTable, Color conditionalColorTeam) {
// to override in subclass
}
protected void addTeamDetails(ReportDto reportDto, PdfPTable statusTable,
ITeamService teamService, Color conditionalColorTeam) {
TeamDto teamDto = teamService.getTeamByRootRef(reportDto.getRootRef());
String teamName = teamDto != null ? teamDto.getTeamName() : "No team assigned/found";
statusTable.addCell(getPdfPCell("Assigned Team", fontBold10, conditionalColorTeam));
statusTable.addCell(getPdfPCell(teamName, font10, conditionalColorTeam));
this.conditionalColorStatus = LIGHTEST_GREEN_COLOR;
this.conditionalColorUnit = WHITE_COLOR;
this.conditionalColorId = WHITE_COLOR;
}
/**
* This method is used to convert into PDF
*
* @param param the parameter to be converted to a PDF document and returns it as a byte array.
*
* @return a ResponseEntity containing the PDF document as a byte array
*
* @throws IOException possible exception
*/
public abstract ResponseEntity<byte[]> convert(P param) throws IOException;
abstract String getHeaderText(ReportDto reportDto);
protected void getTeamDetails(ReportDto reportDto) {
// implementation for specific types
}
protected void generateParagraphWithBlankLine(String text) {
Paragraph paragraph = new Paragraph(text, font14);
paragraph.setAlignment(Element.ALIGN_CENTER);
document.add(paragraph);
document.add(new Paragraph("\n", font14)); // Add a blank line
}
abstract Paragraph getPdfTitle(ReportDto reportDto);
}