Merge branch 'RED-10289' into 'master'

RED-10289: Fixed png image placeholders

Closes RED-10289

See merge request redactmanager/redaction-report-service!102
This commit is contained in:
Dominique Eifländer 2024-10-29 12:09:00 +01:00
commit abcdb63152
7 changed files with 122 additions and 57 deletions

View File

@ -11,5 +11,5 @@ commit_hash=$(git rev-parse --short=5 HEAD)
# Combine branch and commit hash
buildName="${USER}-${branch}-${commit_hash}"
gradle bootBuildImage --cleanCache --publishImage -PbuildbootDockerHostNetwork=true -Pversion=$buildName
gradle bootBuildImage --cleanCache --publishImage -Pversion=$buildName
echo "nexus.knecon.com:5001/red/${dir}-server-v1:$buildName"

View File

@ -9,5 +9,10 @@ public class ImagePlaceholder {
private String placeholder;
private byte[] image;
private ImageType imageType;
public enum ImageType{
PNG, JPEG
}
}

View File

@ -281,9 +281,9 @@ public class ExcelReportGenerationService {
PixelUtil.heightUnits2Pixel(cell.getRow().getHeight()));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", baos);
ImageIO.write(image, imagePlaceholder.getImageType().equals(ImagePlaceholder.ImageType.PNG) ? "png" : "jpg", baos);
baos.flush();
int pictureIdx = workbook.addPicture(baos.toByteArray(), SXSSFWorkbook.PICTURE_TYPE_JPEG);
int pictureIdx = workbook.addPicture(baos.toByteArray(), imagePlaceholder.getImageType().equals(ImagePlaceholder.ImageType.PNG) ? SXSSFWorkbook.PICTURE_TYPE_PNG : SXSSFWorkbook.PICTURE_TYPE_JPEG);
baos.close();
CreationHelper helper = getCreationHelper(workbook);

View File

@ -43,6 +43,7 @@ public class GeneratePlaceholderService {
private final DossierAttributesClient dossierAttributesClient;
private final DossierAttributesConfigClient dossierAttributesConfigClient;
private final RSSPoc2Service rSSService;
public static String PNG_IMAGE_REGEX = "data:image/png;base64.*";
public PlaceholderModel buildPlaceholders(Dossier dossier) {
@ -63,10 +64,15 @@ public class GeneratePlaceholderService {
if (dossierAttribute.getValue() != null) {
if (dossierAttribute.getValue().startsWith("data:")) {
imagePlaceholders.add(new ImagePlaceholder(attributeConfig.getPlaceholder(),
Base64.getDecoder().decode(dossierAttribute.getValue().split(",")[1])));
Base64.getDecoder().decode(dossierAttribute.getValue().split(",")[1]),
isPng(dossierAttribute.getValue()) ? ImagePlaceholder.ImageType.PNG : ImagePlaceholder.ImageType.JPEG));
} else {
imagePlaceholders.add(new ImagePlaceholder(attributeConfig.getPlaceholder(), Base64.getDecoder().decode(dossierAttribute.getValue())));
imagePlaceholders.add(new ImagePlaceholder(attributeConfig.getPlaceholder(),
Base64.getDecoder().decode(dossierAttribute.getValue()),
ImagePlaceholder.ImageType.JPEG));
}
}
} else {
@ -90,6 +96,12 @@ public class GeneratePlaceholderService {
}
private boolean isPng(String imageString) {
return imageString.startsWith("data:image/png");
}
private Map<String, String> getFileAttributePlaceholders(String dossierTemplateId) {
Map<String, String> fileAttributePlaceholders = new HashMap<>();
@ -103,14 +115,14 @@ public class GeneratePlaceholderService {
public Set<String> getDefaultPlaceholders() {
return new HashSet<>(Set.of(FILE_NAME_PLACEHOLDER,
FORMAT_DATE_ISO_PLACEHOLDER,
FORMAT_DATE_GER_PLACEHOLDER,
FORMAT_DATE_ENG_PLACEHOLDER,
FORMAT_TIME_ISO_PLACEHOLDER,
DOSSIER_NAME_PLACEHOLDER,
IUCLID_FUNCTION_PLACEHOLDER,
SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER,
SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER));
FORMAT_DATE_ISO_PLACEHOLDER,
FORMAT_DATE_GER_PLACEHOLDER,
FORMAT_DATE_ENG_PLACEHOLDER,
FORMAT_TIME_ISO_PLACEHOLDER,
DOSSIER_NAME_PLACEHOLDER,
IUCLID_FUNCTION_PLACEHOLDER,
SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER,
SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER));
}
@ -130,7 +142,8 @@ public class GeneratePlaceholderService {
Map<String, String> rssPlaceholders = new HashMap<>();
if (!rssResponse.getFiles().isEmpty()) {
for (Map.Entry<String, SCMComponent> rssEntry : rssResponse.getFiles().get(0).getResult().entrySet()) {
for (Map.Entry<String, SCMComponent> rssEntry : rssResponse.getFiles()
.get(0).getResult().entrySet()) {
rssPlaceholders.put(RSS_PLACEHOLDER_BASE + rssEntry.getKey() + "}}", rssEntry.getValue().getOriginalValue());
}
}

View File

@ -82,6 +82,7 @@ import lombok.extern.slf4j.Slf4j;
public class WordReportGenerationService {
private final IuclidFunctionService iuclidFunctionService;
public static String PNG_IMAGE_REGEX = "data:image/png;base64.*";
@Timed("redactmanager_generateWordReport")
@ -95,7 +96,9 @@ public class WordReportGenerationService {
long start = System.currentTimeMillis();
List<ReportRedactionEntry> reportEntries = allReportEntries.stream().filter(entry -> !entry.isSkipped()).collect(Collectors.toList());
List<ReportRedactionEntry> reportEntries = allReportEntries.stream()
.filter(entry -> !entry.isSkipped())
.collect(Collectors.toList());
int sumOfChars = 0;
@ -118,12 +121,12 @@ public class WordReportGenerationService {
}
log.info("Report Generation took: {} for file with id {}, pageCount: {}, entityLogEntryCount: {}, reportName: {}, className: {}",
System.currentTimeMillis() - start,
fileModel.getId(),
fileModel.getNumberOfPages(),
reportEntries.size(),
reportTemplateName,
getClass().getSimpleName());
System.currentTimeMillis() - start,
fileModel.getId(),
fileModel.getNumberOfPages(),
reportEntries.size(),
reportTemplateName,
getClass().getSimpleName());
} catch (Exception e) {
log.error(e.getMessage() + " in file: " + fileModel.getFilename());
@ -140,8 +143,11 @@ public class WordReportGenerationService {
return;
}
for (int j = 0; j < table.getRows().size(); j++) {
for (int i = 0; i < table.getRows().get(j).getTableCells().size(); i++) {
XWPFTableCell cell = table.getRows().get(j).getTableCells().get(i);
for (int i = 0; i < table.getRows()
.get(j).getTableCells().size(); i++) {
XWPFTableCell cell = table.getRows()
.get(j).getTableCells()
.get(i);
if (containsRedactionPlaceholder(cell.getText())) {
table.removeRow(j);
return;
@ -195,11 +201,13 @@ public class WordReportGenerationService {
}
if (placeholderModel.getFileAttributeValueByPlaceholder().containsKey(placeholder)) {
return placeholderModel.getFileAttributeValueByPlaceholder().get(placeholder);
return placeholderModel.getFileAttributeValueByPlaceholder()
.get(placeholder);
}
if (placeholderModel.getDossierAttributesValueByPlaceholder().containsKey(placeholder)) {
return placeholderModel.getDossierAttributesValueByPlaceholder().get(placeholder);
return placeholderModel.getDossierAttributesValueByPlaceholder()
.get(placeholder);
}
return "";
@ -212,15 +220,22 @@ public class WordReportGenerationService {
String paragraphText = p.getText();
if (paragraphText.contains(imagePlaceholder.getPlaceholder())) {
try {
XWPFRun run = p.getRuns()
.get(0);
run.setText("", 0);
run.addBreak();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", baos);
ImageIO.write(img, imagePlaceholder.getImageType().equals(ImagePlaceholder.ImageType.PNG) ? "png" : "jpg", baos);
baos.flush();
ByteArrayInputStream is = new ByteArrayInputStream(baos.toByteArray());
XWPFRun run = p.getRuns().get(0);
run.setText("", 0);
run.addBreak();
run.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, "image.jpg", Units.toEMU(img.getWidth()), Units.toEMU(img.getHeight()));
run.addPicture(is,
imagePlaceholder.getImageType().equals(ImagePlaceholder.ImageType.PNG) ? XWPFDocument.PICTURE_TYPE_PNG : XWPFDocument.PICTURE_TYPE_JPEG,
imagePlaceholder.getImageType().equals(ImagePlaceholder.ImageType.PNG) ? "image.png" : "image.jpg",
Units.toEMU(img.getWidth()),
Units.toEMU(img.getHeight()));
for (int i = p.getRuns().size() - 1; i > 0; i--) {
p.removeRun(i);
@ -286,7 +301,8 @@ public class WordReportGenerationService {
String escapedReplace = Matcher.quoteReplacement(replace);
try {
paragraphText = paragraphText.replaceAll(escapedSearch, escapedReplace);
XWPFRun run = p.getRuns().get(0);
XWPFRun run = p.getRuns()
.get(0);
run.setText(paragraphText, 0);
sumOfChars += paragraphText.length();
} catch (Exception e) {
@ -330,7 +346,8 @@ public class WordReportGenerationService {
private void splitIntoRuns(XWPFParagraph p, String[] stringsOnNewLines, int i) {
p.insertNewRun(i);
XWPFRun newRun = p.getRuns().get(i);
XWPFRun newRun = p.getRuns()
.get(i);
setTextToRun(newRun, stringsOnNewLines[i]);
newRun.addCarriageReturn();
}
@ -353,7 +370,8 @@ public class WordReportGenerationService {
if (i < newLineParagraphs.size()) {
doc.setParagraph(newLineParagraphs.get(i), i);
} else {
paragraphsToRemove.add(doc.getParagraphs().get(i));
paragraphsToRemove.add(doc.getParagraphs()
.get(i));
}
}
@ -377,10 +395,17 @@ public class WordReportGenerationService {
for (XWPFTable tbl : doc.getTables()) {
String tblText = tbl.getText();
if (tblText.contains(PAGE_PLACEHOLDER) || tblText.contains(PARAGRAPH_PLACEHOLDER) || tblText.contains(PARAGRAPH_INDEX_PLACEHOLDER) || tblText.contains(JUSTIFICATION_PLACEHOLDER) || tblText.contains(EXCERPT_PLACEHOLDER) || tblText.contains(
JUSTIFICATION_PARAGRAPH_PLACEHOLDER) || tblText.contains(JUSTIFICATION_REASON_PLACEHOLDER) || tblText.contains(JUSTIFICATION_LEGAL_BASIS_PLACEHOLDER) || tblText.contains(
JUSTIFICATION_TEXT_PLACEHOLDER) || tblText.contains(SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER) || tblText.contains(
SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER)) {
if (tblText.contains(PAGE_PLACEHOLDER)
|| tblText.contains(PARAGRAPH_PLACEHOLDER)
|| tblText.contains(PARAGRAPH_INDEX_PLACEHOLDER)
|| tblText.contains(JUSTIFICATION_PLACEHOLDER)
|| tblText.contains(EXCERPT_PLACEHOLDER)
|| tblText.contains(JUSTIFICATION_PARAGRAPH_PLACEHOLDER)
|| tblText.contains(JUSTIFICATION_REASON_PLACEHOLDER)
|| tblText.contains(JUSTIFICATION_LEGAL_BASIS_PLACEHOLDER)
|| tblText.contains(JUSTIFICATION_TEXT_PLACEHOLDER)
|| tblText.contains(SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER)
|| tblText.contains(SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER)) {
return tbl;
}
}
@ -390,12 +415,22 @@ public class WordReportGenerationService {
private boolean containsRedactionPlaceholder(String text) {
return text.startsWith(DOSSIER_ATTRIBUTE_PLACEHOLDER_BASE) || text.startsWith(FILE_ATTRIBUTE_PLACEHOLDER_BASE) || text.contains(FILE_NAME_PLACEHOLDER) || text.contains(
PAGE_PLACEHOLDER) || text.contains(PARAGRAPH_PLACEHOLDER) || text.contains(PARAGRAPH_INDEX_PLACEHOLDER) || text.contains(JUSTIFICATION_PLACEHOLDER) || text.contains(EXCERPT_PLACEHOLDER) || text.contains(
JUSTIFICATION_PARAGRAPH_PLACEHOLDER) || text.contains(JUSTIFICATION_REASON_PLACEHOLDER) || text.contains(REDACTION_VALUE_PLACEHOLDER) || text.contains(
JUSTIFICATION_LEGAL_BASIS_PLACEHOLDER) || text.contains(JUSTIFICATION_TEXT_PLACEHOLDER) || text.contains(
SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER) || text.contains(SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER) || text.contains(
REDACTION_ENTITY_DISPLAY_NAME_PLACEHOLDER);
return text.startsWith(DOSSIER_ATTRIBUTE_PLACEHOLDER_BASE)
|| text.startsWith(FILE_ATTRIBUTE_PLACEHOLDER_BASE)
|| text.contains(FILE_NAME_PLACEHOLDER)
|| text.contains(PAGE_PLACEHOLDER)
|| text.contains(PARAGRAPH_PLACEHOLDER)
|| text.contains(PARAGRAPH_INDEX_PLACEHOLDER)
|| text.contains(JUSTIFICATION_PLACEHOLDER)
|| text.contains(EXCERPT_PLACEHOLDER)
|| text.contains(JUSTIFICATION_PARAGRAPH_PLACEHOLDER)
|| text.contains(JUSTIFICATION_REASON_PLACEHOLDER)
|| text.contains(REDACTION_VALUE_PLACEHOLDER)
|| text.contains(JUSTIFICATION_LEGAL_BASIS_PLACEHOLDER)
|| text.contains(JUSTIFICATION_TEXT_PLACEHOLDER)
|| text.contains(SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER)
|| text.contains(SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER)
|| text.contains(REDACTION_ENTITY_DISPLAY_NAME_PLACEHOLDER);
}
@ -406,8 +441,11 @@ public class WordReportGenerationService {
if (table != null) {
for (int j = 0; j < table.getRows().size(); j++) {
for (int i = 0; i < table.getRows().get(j).getTableCells().size(); i++) {
XWPFTableCell cell = table.getRows().get(j).getTableCells().get(i);
for (int i = 0; i < table.getRows()
.get(j).getTableCells().size(); i++) {
XWPFTableCell cell = table.getRows()
.get(j).getTableCells()
.get(i);
if (containsRedactionPlaceholder(cell.getText())) {
placeholderCellPos.put(i, getFunctionForPlaceHolder(cell.getText(), foundPlaceHolder, placeholderModel));
} else if (cell.getText().isEmpty()) {
@ -467,7 +505,7 @@ public class WordReportGenerationService {
}
if (placeholder.equals(PARAGRAPH_INDEX_PLACEHOLDER)) {
foundPlaceholders.add(PARAGRAPH_INDEX_PLACEHOLDER);
return input -> String.valueOf(input.getEntry().getParagraphIdx());
return input -> String.valueOf(input.getEntry().getParagraphIdx());
}
if (placeholder.equals(PARAGRAPH_PLACEHOLDER)) {
foundPlaceholders.add(PARAGRAPH_PLACEHOLDER);
@ -499,7 +537,8 @@ public class WordReportGenerationService {
}
if (placeholder.equals(REDACTION_VALUE_PLACEHOLDER)) {
foundPlaceholders.add(REDACTION_VALUE_PLACEHOLDER);
return input -> input.getEntry().getValue() != null ? input.getEntry().getValue().replaceAll("\n", " ").replaceAll(" {2}", " ") : input.getEntry().getEntityDisplayName();
return input -> input.getEntry().getValue() != null ? input.getEntry().getValue().replaceAll("\n", " ").replaceAll(" {2}", " ") : input.getEntry()
.getEntityDisplayName();
}
if (placeholder.equals(REDACTION_ENTITY_DISPLAY_NAME_PLACEHOLDER)) {
foundPlaceholders.add(REDACTION_ENTITY_DISPLAY_NAME_PLACEHOLDER);
@ -508,7 +547,10 @@ public class WordReportGenerationService {
if (placeholder.equals(SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER)) {
foundPlaceholders.add(SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER);
return input -> computePageRanges(input.getRedactionsPerJustificationEntry().getValue().stream().map(ReportRedactionEntry::getPage).collect(Collectors.toSet()));
return input -> computePageRanges(input.getRedactionsPerJustificationEntry().getValue()
.stream()
.map(ReportRedactionEntry::getPage)
.collect(Collectors.toSet()));
}
if (placeholder.equals(SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER)) {
@ -517,12 +559,14 @@ public class WordReportGenerationService {
if (placeholderModel.getFileAttributeValueByPlaceholder().containsKey(placeholder)) {
foundPlaceholders.add(placeholder);
return input -> input.getPlaceholderModel().getFileAttributeValueByPlaceholder().get(placeholder);
return input -> input.getPlaceholderModel().getFileAttributeValueByPlaceholder()
.get(placeholder);
}
if (placeholderModel.getDossierAttributesValueByPlaceholder().containsKey(placeholder)) {
foundPlaceholders.add(placeholder);
return input -> input.getPlaceholderModel().getDossierAttributesValueByPlaceholder().get(placeholder);
return input -> input.getPlaceholderModel().getDossierAttributesValueByPlaceholder()
.get(placeholder);
}
return input -> "";
@ -612,7 +656,9 @@ public class WordReportGenerationService {
private Map<String, List<ReportRedactionEntry>> getRedactionsPerJustification(List<ReportRedactionEntry> reportRedactionEntryList) {
return reportRedactionEntryList.stream().sorted(Comparator.comparing(ReportRedactionEntry::getPage)).collect(Collectors.groupingBy(ReportRedactionEntry::getJustification));
return reportRedactionEntryList.stream()
.sorted(Comparator.comparing(ReportRedactionEntry::getPage))
.collect(Collectors.groupingBy(ReportRedactionEntry::getJustification));
}

View File

@ -177,7 +177,7 @@ public class RedactionReportIntegrationTest {
List<ReportRedactionEntry> reportEntries = entityLogConverterService.convertAndSort(DOSSIER_ID, FILE_ID, entityLog, legalBasisMapping, new HashMap<>());
var wordTemplateResource = new ClassPathResource("templates/Justification Appendix A1.docx");
var imageResource = new ClassPathResource("files/exampleImage.jpg");
var imageResource = new ClassPathResource("files/signature-40145.png");
var placeholders = buildPlaceHolderModel(Map.of("{{dossier.attribute.ActiveSubstance}}",
"Aktive Substanz \n Test Return",
@ -190,7 +190,8 @@ public class RedactionReportIntegrationTest {
"{{dossier.attribute.Date}}",
"2021-11-09T23:00:00.000Z"),
Map.of("{{file.attribute.placeholder}}", "Test"),
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()))));
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()),
ImagePlaceholder.ImageType.PNG)));
XWPFDocument doc = new XWPFDocument(wordTemplateResource.getInputStream());
wordReportGenerationService.generateWordReport(reportEntries, placeholders, "test", doc, fileModel, dossier, true);
@ -240,7 +241,7 @@ public class RedactionReportIntegrationTest {
"{{dossier.attribute.Date}}",
"2021-11-09T23:00:00.000Z"),
Map.of("{{file.attribute.placeholder}}", "Test"),
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()))));
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()), ImagePlaceholder.ImageType.JPEG)));
XWPFDocument doc = new XWPFDocument(wordTemplateResource.getInputStream());
wordReportGenerationService.generateWordReport(reportEntries, placeholders, "test", doc, fileModel, dossier, true);
@ -404,7 +405,7 @@ public class RedactionReportIntegrationTest {
"{{dossier.attribute.Date}}",
"2021-11-09T23:00:00.000Z"),
Map.of("{{file.attribute.placeholder}}", "Test"),
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()))));
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()), ImagePlaceholder.ImageType.JPEG)));
XWPFDocument doc = new XWPFDocument(wordTemplateResource.getInputStream());
wordReportGenerationService.generateWordReport(reportEntries, placeholders, "test", doc, fileModel, dossier, true);
@ -545,7 +546,7 @@ public class RedactionReportIntegrationTest {
var placeholders = buildPlaceHolderModel(Map.of("{{dossier_attribute.test1}}", "replaced_dossier_test1"),
Map.of("{{file_attribute.test1}}", "replaced_file_test1", "{{file_attribute.test2}}", "replaced_file_test2"),
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()))));
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()), ImagePlaceholder.ImageType.JPEG)));
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
var excelModel = excelTemplateReportGenerationService.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
@ -578,7 +579,7 @@ public class RedactionReportIntegrationTest {
var placeholders = buildPlaceHolderModel(Map.of("{{dossier_attribute.test1}}", "replaced_dossier_test1"),
Map.of("{{file_attribute.test1}}", "replaced_file_test1", "{{file_attribute.test2}}", "replaced_file_test2"),
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()))));
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()), ImagePlaceholder.ImageType.JPEG)));
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
var excelModel = excelTemplateReportGenerationService.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 KiB