Done ticket GEPAFINBE-236

This commit is contained in:
rajesh
2025-09-30 20:24:55 +05:30
parent 47db22e69c
commit baa7ea8d55
27 changed files with 524 additions and 77 deletions

View File

@@ -0,0 +1,140 @@
package net.gepafin.tendermanagement.util;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3URI;
import com.amazonaws.services.s3.model.S3Object;
import net.gepafin.tendermanagement.model.request.AttachmentRequest;
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.Base64;
public class S3DocxProcessor {
private final AmazonS3 s3Client;
public static final Logger log = LoggerFactory.getLogger(S3DocxProcessor.class);
public S3DocxProcessor(AmazonS3 s3Client) {
this.s3Client = s3Client;
}
/**
* Fetches DOCX files from S3, replaces placeholders, and returns updated files
* as AttachmentRequest objects (ready for PEC API).
*
* @param s3Urls List of S3 file URLs
* @param replacements Map of placeholder -> value
* @return Map of original file name -> AttachmentRequest
* @throws IOException
*/
public Map<String, AttachmentRequest> processFiles(List<String> s3Urls,
Map<String, String> replacements) throws IOException {
Map<String, AttachmentRequest> processedFiles = new HashMap<>();
for (String s3Url : s3Urls) {
// Extract bucket & key from URL
AmazonS3URI s3Uri = new AmazonS3URI(s3Url);
String bucket = s3Uri.getBucket();
String key = s3Uri.getKey();
try (S3Object s3Object = s3Client.getObject(bucket, key);
InputStream originalStream = new BufferedInputStream(s3Object.getObjectContent())) {
byte[] updatedBytes=null;
if (isDocxFile(originalStream)) {
log.warn("Skipping non-DOCX file from S3: bucket={}, key={}", bucket, key);
updatedBytes = replacePlaceholders(originalStream, replacements);
}else {
// non-DOCX → just copy raw stream
updatedBytes = originalStream.readAllBytes();
log.info("Skipped placeholder replacement, copied file as-is: {}", key);
}
// convert to base64
String base64 = Base64.getEncoder().encodeToString(updatedBytes);
String fileString = "data:application/octet-stream;base64," + base64;
// create attachment request
AttachmentRequest attachment = new AttachmentRequest();
attachment.setName(extractFileName(key));
attachment.setFile(fileString);
processedFiles.put(key, attachment);
}
}
return processedFiles;
}
private byte[] replacePlaceholders(InputStream docInputStream,
Map<String, String> replacements) throws IOException {
try (XWPFDocument document = new XWPFDocument(docInputStream);
ByteArrayOutputStream out = new ByteArrayOutputStream()) {
// replace in body paragraphs
replaceInParagraphs(document.getParagraphs(), replacements);
// replace inside tables
for (XWPFTable table : document.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
replaceInParagraphs(cell.getParagraphs(), replacements);
}
}
}
document.write(out);
return out.toByteArray();
}
}
private void replaceInParagraphs(List<XWPFParagraph> paragraphs, Map<String, String> replacements) {
for (XWPFParagraph paragraph : paragraphs) {
String paragraphText = paragraph.getText();
if (paragraphText != null && !paragraphText.isEmpty()) {
// Apply all replacements
for (Map.Entry<String, String> entry : replacements.entrySet()) {
paragraphText = paragraphText.replace(entry.getKey(), entry.getValue());
}
// Remove old runs
int runCount = paragraph.getRuns().size();
for (int i = runCount - 1; i >= 0; i--) {
paragraph.removeRun(i);
}
// Add one new run with replaced text
XWPFRun newRun = paragraph.createRun();
newRun.setText(paragraphText);
}
}
}
private String extractFileName(String key) {
int lastSlash = key.lastIndexOf('/');
if (lastSlash >= 0 && lastSlash < key.length() - 1) {
return key.substring(lastSlash + 1);
}
return key;
}
private boolean isDocxFile(InputStream inputStream) throws IOException {
inputStream.mark(4);
byte[] header = new byte[2];
int read = inputStream.read(header, 0, 2);
inputStream.reset();
// DOCX = ZIP = should start with PK (0x50 0x4B)
return read == 2 && header[0] == 0x50 && header[1] == 0x4B;
}
}