Parcourir la source

no message

master
[email protected] il y a 4 jours
Parent
révision
b066a991d1
1 fichiers modifiés avec 133 ajouts et 161 suppressions
  1. +133
    -161
      src/main/java/com/ffii/lioner/modules/lioner/pdf/service/PdfService.java

+ 133
- 161
src/main/java/com/ffii/lioner/modules/lioner/pdf/service/PdfService.java Voir le fichier

@@ -10,6 +10,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@@ -18,6 +19,7 @@ import org.apache.commons.lang3.math.NumberUtils;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDButton;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -231,214 +233,184 @@ public class PdfService extends AbstractBaseEntityService<Pdf, Long, PdfReposito

//This included the common fields getting
public byte[] getTemplateForm(byte[] pdfBytes, Long clientId, Long templateId) throws IOException {
// --- 1. Initial Data Loading & Extraction Phase (iText Read) ---
Map<String, Object> template = templateService.loadTemplate(templateId);

//Search if there have an old form having the form code
Map<String, Object> sourcePdf = getLastPdf(clientId, templateId);
if (sourcePdf == null) { sourcePdf = template; }
// Search if there have an old form having the form code
Map<String, Object> sourcePdf = getLastPdf(clientId, templateId);
if (sourcePdf == null) { sourcePdf = template; }
byte[] sourcePdfBytes = (byte[])sourcePdf.get("blobValue");
String formCode = (String)template.get("remarks");
Client client = clientService.find(clientId).orElseThrow();

//byte[] modifiedPdfBytes = pdfBytes;

PdfAcroForm sourceForm = null;
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(sourcePdfBytes);
ByteArrayOutputStream sourceOutputStream = new ByteArrayOutputStream()) {
// Map to hold ALL extracted field data from the source PDF (historical values)
Map<String, String> sourceFieldValues = new HashMap<>();

PdfReader sourceReader = new PdfReader(inputStream);
PdfWriter sourceWriter = new PdfWriter(sourceOutputStream);
PdfDocument sourcePdfDoc = new PdfDocument(sourceReader, sourceWriter);
sourceForm = PdfAcroForm.getAcroForm(sourcePdfDoc, true);
}
logger.info("form set start:");
byte[] modifiedPdfBytes = pdfBytes;
// Load common field data (used by both phases)
Long commonFieldId = commonFieldService.getByClientId(clientId);
CommonField commonField = commonFieldService.find(commonFieldId).orElse(null);
if(commonField == null){
commonField = new CommonField();
commonField.setClientId(clientId);
commonFieldService.save(commonField);
}
// --- 1A. Extract ALL Field Values from Historical Source PDF (iText Read Only) ---
// This uses iText to reliably read field data BEFORE any writing/modification happens.
if (sourcePdfBytes != null) {
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(sourcePdfBytes)) {
PdfReader sourceReader = new PdfReader(inputStream);
PdfDocument sourcePdfDoc = new PdfDocument(sourceReader);
PdfAcroForm sourceForm = PdfAcroForm.getAcroForm(sourcePdfDoc, true);
if (sourceForm != null) {
for (Map.Entry<String, PdfFormField> entry : sourceForm.getFormFields().entrySet()) {
PdfFormField sourceField = entry.getValue();
if (sourceField.getFieldName() != null && sourceField.getValue() != null) {
sourceFieldValues.put(sourceField.getFieldName().toUnicodeString(), sourceField.getValueAsString());
}
}
}
sourcePdfDoc.close();
}
}
// --- 2. Phase 1: Text Field Filling (iText Write) ---
logger.info("Phase 1 (iText): Starting text field processing for form code: {}" + formCode);
byte[] modifiedPdfBytes = pdfBytes;

try (ByteArrayInputStream inputStream = new ByteArrayInputStream(pdfBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(pdfBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

PdfReader reader = new PdfReader(inputStream);
PdfWriter writer = new PdfWriter(outputStream);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);

logger.info("form:" + (form != null));
if (form != null) {
logger.info("sourceForm:" + (sourceForm != null));
/* START of copying the source fields if exist */
if(sourceForm != null){
for (Map.Entry<String, PdfFormField> entry : sourceForm.getFormFields().entrySet()) {
PdfFormField sourceField = entry.getValue();

if(sourceField.getFieldName() != null){
String sourceFieldName = sourceField.getFieldName().toUnicodeString();
if(sourceField.getValue() != null){
String sourceFieldValue = sourceField.getValueAsString();
PdfFormField targetField = form.getField(sourceFieldName);
//logger.info("Field '" + sourceFieldName + "' as '" + sourceFieldValue + "' from source set in target PDF.");

if (targetField != null && sourceField.getFormType().equals(PdfName.Tx)) {
targetField.setValue(sourceFieldValue); // Set the value in the target field
} else {
//System.out.println("Field '" + sourceFieldName + "' from source not found in target PDF.");
}
}
}
}
}
/* END of copying the source fields */

// --- START DEBUGGING CODE TO LIST ALL PDF FORM FIELDS ---
// logger.info("--- Listing all form fields in the PDF (for ID: {}) ---", id);
// if (form.getFormFields().isEmpty()) {
// logger.info("No form fields found in this PDF.");
// } else {
// form.getFormFields().forEach((fieldName, pdfFormField) -> {
// logger.info(" - Field Name: '{}', Type: '{}'", fieldName, pdfFormField.getFormType());
// });
// }
// logger.info("--- End of form fields list ---");
// --- END DEBUGGING CODE ---

// Load common field data
Long commonFieldId = commonFieldService.getByClientId(clientId);
// logger.info("id? " + id);
CommonField commonField = commonFieldService.find(commonFieldId).orElse(null);

if(commonField == null){
//logger.info("No common field data found for clientId: " + clientId);
commonField = new CommonField();
commonField.setClientId(clientId);
commonFieldService.save(commonField);
// ** START: Historical Text Field Copy **
logger.info("Copying historical text fields...");
for (Map.Entry<String, String> entry : sourceFieldValues.entrySet()) {
String sourceFieldName = entry.getKey();
String sourceFieldValue = entry.getValue();
PdfFormField targetField = form.getField(sourceFieldName);
if (targetField != null && targetField.getFormType().equals(PdfName.Tx)) {
targetField.setValue(sourceFieldValue);
logger.info("Historical Text Field '{}' set." + sourceFieldName);
}
}
// ** END: Historical Text Field Copy **

logger.info(formCode);
// It's highly recommended to check if the field exists before setting its value
// This prevents NullPointerExceptions if a field is missing in a template
//temp using the remarks as form code
if("IDA".equals(formCode)){ // This is IDA
// Apply current business logic to Text Fields
logger.info("Applying form code text fields: {}" + formCode);
if("IDA".equals(formCode)){
IDA_textBox(form, commonField, client);
} else if("FNA".equals(formCode)){ // This is FNA
} else if("FNA".equals(formCode)){
FNA_textBox(form, commonField, client);
} else if("HSBCFIN".equals(formCode)){ // This is HSBCFIN
} else if("HSBCFIN".equals(formCode)){
HSBCFIN_textBox(form, commonField, client);
}else if ("MLB03S".equals(formCode)) {
} else if ("MLB03S".equals(formCode)) {
MLB03S_textBox(form, commonField, client);
} else if("MLFNA_EN".equals(formCode)){ // This is ML FNA EN
MLFNA_EN_textBox(form, commonField, client);
} else if("MLFNA_CHI".equals(formCode)){ // This is ML FNA CHI
} else if("MLFNA_EN".equals(formCode) || "MLFNA_CHI".equals(formCode)){
MLFNA_EN_textBox(form, commonField, client);
} else if("SLFNA_EN".equals(formCode)){ // This is SL FNA EN
} else if("SLFNA_EN".equals(formCode) || "SLFNA_CHI".equals(formCode)){
SLFNA_EN_textBox(form, commonField, client);
} else if("SLFNA_CHI".equals(formCode)){ // This is SL FNA CHI
SLFNA_EN_textBox(form, commonField, client);
}else if("SLAPP".equals(formCode)){
} else if("SLAPP".equals(formCode)){
SLAPP_textBox(form, commonField, client);
}else if("HSBCA31".equals(formCode)){ // This is HSBC A31
} else if("HSBCA31".equals(formCode)){
HSBCA31_textBox(form, commonField, client);
}else if("SLGII".equals(formCode)){
} else if("SLGII".equals(formCode)){
SLGII_textBox(form, commonField, client);
}

//form.flattenFields(); // Flatten fields after setting all values

pdfDoc.close();
modifiedPdfBytes = outputStream.toByteArray();
} else {
// logger.warn("No AcroForm found in PDF for ID: " + id + ". PDF might not have fillable fields.");
logger.warn("iText found no AcroForm. Proceeding to PDFBox phase with original bytes.");
}

pdfDoc.close();
modifiedPdfBytes = outputStream.toByteArray();
//logger.info("Modified PDF byte array length: " + modifiedPdfBytes.length);

} catch (IOException e) {
// logger.error("Error processing PDF with iText for ID: " + id, e);
logger.error("Error during iText text field processing.", e);
throw e;
}

try (PDDocument sourceDoc = Loader.loadPDF(modifiedPdfBytes);
//PDDocument pdfDoc = Loader.loadPDF(modifiedPdfBytes);
// --- 3. Phase 2: Checkbox Filling (PDFBox Write) ---
logger.info("Phase 2 (PDFBox): Starting checkbox processing.");

try (PDDocument targetDoc = Loader.loadPDF(modifiedPdfBytes); // Load iText's output
ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
PDAcroForm sourceForm2 = sourceDoc.getDocumentCatalog().getAcroForm();
PDAcroForm form2 = sourceDoc.getDocumentCatalog().getAcroForm();
PDAcroForm form2 = targetDoc.getDocumentCatalog().getAcroForm();

if (form2 != null) {
if (sourceForm2 != null) {
for (PDField sourceField : sourceForm2.getFields()) {
String sourceFieldName = sourceField.getPartialName();
if (sourceFieldName != null) {
String sourceFieldValue = sourceField.getValueAsString();
PDField targetField = form2.getField(sourceFieldName);
//only do for check box
if ("Btn".equals(sourceField.getFieldType()) || "Ch".equals(sourceField.getFieldType())
&& targetField != null && sourceFieldValue != null) {
try{
targetField.setValue(sourceFieldValue);
}catch (Exception e){
logger.info("sourceFieldName error:" + sourceFieldName);
}
}
// ** START: Historical Checkbox/Button Copy **
logger.info("Copying historical button fields from map...");
for (Map.Entry<String, String> entry : sourceFieldValues.entrySet()) {
String sourceFieldName = entry.getKey();
String sourceValue = entry.getValue();

PDField targetField = form2.getField(sourceFieldName);

// CRITICAL: Check the field type before casting!
if (targetField instanceof PDButton) {
PDButton button = (PDButton) targetField;
Set<String> onValues = button.getOnValues();
if (sourceValue != null && onValues != null && onValues.contains(sourceValue)) {
button.setValue(sourceValue);
logger.info("Historical Checkbox '{}' set to CHECKED." + sourceFieldName);
} else {
button.setValue("Off");
logger.info("Historical Checkbox '{}' set to UNCHECKED." + sourceFieldName);
}
}
}
// Ignore other field types (Text was handled by iText).
}
// ** END: Historical Checkbox/Button Copy **

Long commonFieldId = commonFieldService.getByClientId(clientId);
CommonField commonField = commonFieldService.find(commonFieldId).orElse(null);
if (commonField != null) {
if ("IDA".equals(formCode)) {
IDA_checkBox(form2, commonField);
} else if ("FNA".equals(formCode)) {
FNA_checkBox(form2, commonField);
} else if ("HSBCFIN".equals(formCode)) {
HSBCFIN_checkBox(form2, commonField);
}else if ("MLB03S".equals(formCode)) {
MLB03S_checkBox(form2, commonField);
}else if("MLFNA_EN".equals(formCode)){ // This is ML FNA EN
MLFNA_EN_checkBox(form2, commonField, client);
} else if("MLFNA_CHI".equals(formCode)){ // This is ML FNA CHI
MLFNA_EN_checkBox(form2, commonField, client);
} else if("SLFNA_EN".equals(formCode)){ // This is SL FNA EN
SLFNA_EN_checkBox(form2, commonField);
} else if("SLFNA_CHI".equals(formCode)){ // This is SL FNA CHI
SLFNA_EN_checkBox(form2, commonField);
}else if("SLAPP".equals(formCode)){
SLAPP_checkBox(form2, commonField);
} else if("HSBCA31".equals(formCode)){
HSBCA31_checkBox(form2, commonField);
}else if ("SLGII".equals(formCode)) {
SLGII_checkBox(form2, commonField);
}
// Apply current business logic to Checkboxes/Buttons (overwrites historical)
logger.info("Applying form code checkbox fields: {}" + formCode);
if ("IDA".equals(formCode)) {
IDA_checkBox(form2, commonField);
} else if ("FNA".equals(formCode)) {
FNA_checkBox(form2, commonField);
} else if ("HSBCFIN".equals(formCode)) {
HSBCFIN_checkBox(form2, commonField);
} else if ("MLB03S".equals(formCode)) {
MLB03S_checkBox(form2, commonField);
} else if("MLFNA_EN".equals(formCode) || "MLFNA_CHI".equals(formCode)){
MLFNA_EN_checkBox(form2, commonField, client);
} else if("SLFNA_EN".equals(formCode) || "SLFNA_CHI".equals(formCode)){
SLFNA_EN_checkBox(form2, commonField);
} else if("SLAPP".equals(formCode)){
SLAPP_checkBox(form2, commonField);
} else if("HSBCA31".equals(formCode)){
HSBCA31_checkBox(form2, commonField);
} else if ("SLGII".equals(formCode)) {
SLGII_checkBox(form2, commonField);
}
// Save the modified document to the output stream
sourceDoc.save(outputStream);
sourceDoc.close();
// Save the final modified document
targetDoc.save(outputStream);
targetDoc.close();
return outputStream.toByteArray();
} else {
return pdfBytes; // Return original bytes if no form found
logger.warn("PDFBox found no AcroForm. Returning iText output.");
return modifiedPdfBytes;
}
} catch (IOException e) {
// logger.error("Error processing PDF with iText for ID: " + id, e);
} catch (Exception e) {
logger.error("Error during PDFBox checkbox processing.", e);
throw new IOException("Failed to process checkboxes with PDFBox.", e);
}

// try (InputStream is = pdfFile.getInputStream()) {
// return pdfBytes;
// } catch (Exception e) {
// throw new UnprocessableEntityException("Fail to load PDF: " + e);
// }
return modifiedPdfBytes;
// return fileService.getfileBlob((long) 2);
}
}

private void IDA_textBox(PdfAcroForm form, CommonField commonField, Client client){
logger.info("Processing IDA form (ID: 1)");


Chargement…
Annuler
Enregistrer