336 lines
12 KiB
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);
|
|
} |