added pdf implementation demo files
This commit is contained in:
336
PdfConverter.java
Normal file
336
PdfConverter.java
Normal file
@@ -0,0 +1,336 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user