From 62c9c4d8b3d7cf4b4b79f57b88918e3cacaf85be Mon Sep 17 00:00:00 2001 From: aoezyetimoglu Date: Wed, 27 Apr 2022 12:03:01 +0200 Subject: [PATCH] RED-3748: Update justification form for Seeds and make it a multi-file-report --- .../report/v1/api/model/ReportType.java | 2 +- .../pom.xml | 4 +- .../v1/server/model/MultiFileDocument.java | 19 +++ .../service/ReportGenerationService.java | 53 +++++-- .../service/WordReportGenerationService.java | 150 ++++++++++++------ .../RedactionReportIntegrationTest.java | 76 ++++----- .../templates/Seeds-NewJustificationForm.docx | Bin 0 -> 62329 bytes 7 files changed, 194 insertions(+), 110 deletions(-) create mode 100644 redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/MultiFileDocument.java create mode 100644 redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/templates/Seeds-NewJustificationForm.docx diff --git a/redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/model/ReportType.java b/redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/model/ReportType.java index e622b53..415aaa2 100644 --- a/redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/model/ReportType.java +++ b/redaction-report-service-v1/redaction-report-service-api-v1/src/main/java/com/iqser/red/service/redaction/report/v1/api/model/ReportType.java @@ -1,5 +1,5 @@ package com.iqser.red.service.redaction.report.v1.api.model; public enum ReportType { - WORD_SINGLE_FILE, EXCEL_TEMPLATE_SINGLE_FILE, EXCEL_TEMPLATE_MULTI_FILE + WORD_SINGLE_FILE, WORD_TEMPLATE_MULTI_FILE, EXCEL_TEMPLATE_SINGLE_FILE, EXCEL_TEMPLATE_MULTI_FILE } diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/pom.xml b/redaction-report-service-v1/redaction-report-service-server-v1/pom.xml index e8e1088..888cc17 100644 --- a/redaction-report-service-v1/redaction-report-service-server-v1/pom.xml +++ b/redaction-report-service-v1/redaction-report-service-server-v1/pom.xml @@ -14,8 +14,8 @@ 1.0-SNAPSHOT - 1.98.0 - 3.86.0 + 1.160.0 + 3.108.0 diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/MultiFileDocument.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/MultiFileDocument.java new file mode 100644 index 0000000..4d81a54 --- /dev/null +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/MultiFileDocument.java @@ -0,0 +1,19 @@ +package com.iqser.red.service.redaction.report.v1.server.model; + +import java.util.List; + +import org.apache.poi.xwpf.usermodel.XWPFDocument; + +import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.dossier.file.FileModel; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class MultiFileDocument { + + private XWPFDocument document; + private String templateId; + +} diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/ReportGenerationService.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/ReportGenerationService.java index ae0fb1d..8a27c51 100644 --- a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/ReportGenerationService.java +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/ReportGenerationService.java @@ -10,6 +10,7 @@ import com.iqser.red.service.redaction.report.v1.server.client.DossierClient; import com.iqser.red.service.redaction.report.v1.server.client.FileStatusClient; import com.iqser.red.service.redaction.report.v1.server.client.RedactionLogClient; import com.iqser.red.service.redaction.report.v1.server.client.ReportTemplateClient; +import com.iqser.red.service.redaction.report.v1.server.model.MultiFileDocument; import com.iqser.red.service.redaction.report.v1.server.model.MultiFileWorkbook; import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEntry; import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService; @@ -20,6 +21,7 @@ import com.iqser.red.storage.commons.exception.StorageObjectDoesNotExist; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.springframework.stereotype.Service; import java.io.ByteArrayInputStream; @@ -51,17 +53,29 @@ public class ReportGenerationService { List singleFilesTemplates = new ArrayList<>(); List multiFileWorkbooks = new ArrayList<>(); + List multiFileDocuments = new ArrayList<>(); for (String templateId : reportMessage.getTemplateIds()) { try { ReportTemplate reportTemplate = reportTemplateClient.getReportTemplate(reportMessage.getDossierTemplateId(), templateId); if (reportTemplate.isMultiFileReport()) { - byte[] excelTemplate = reportStorageService.getReportTemplate(reportTemplate.getStorageId()); - try (ByteArrayInputStream is = new ByteArrayInputStream(excelTemplate)) { - XSSFWorkbook workbook = new XSSFWorkbook(is); - MultiFileWorkbook multiFileWorkbook = new MultiFileWorkbook(workbook, templateId); - multiFileWorkbooks.add(multiFileWorkbook); - } catch (IOException e) { - throw new RuntimeException("Could not generate multifile excel report."); + if(reportTemplate.getFileName().endsWith(".xlsx")) { + byte[] excelTemplate = reportStorageService.getReportTemplate(reportTemplate.getStorageId()); + try (ByteArrayInputStream is = new ByteArrayInputStream(excelTemplate)) { + XSSFWorkbook workbook = new XSSFWorkbook(is); + MultiFileWorkbook multiFileWorkbook = new MultiFileWorkbook(workbook, templateId); + multiFileWorkbooks.add(multiFileWorkbook); + } catch (IOException e) { + throw new RuntimeException("Could not generate multifile excel report."); + } + } else { + byte[] wordTemplate = reportStorageService.getReportTemplate(reportTemplate.getStorageId()); + try (ByteArrayInputStream is = new ByteArrayInputStream(wordTemplate)) { + XWPFDocument doc = new XWPFDocument(is); + MultiFileDocument multiFileDocument = new MultiFileDocument(doc, templateId); + multiFileDocuments.add(multiFileDocument); + } catch (IOException e) { + throw new RuntimeException("Could not generate multifile word report."); + } } } else { singleFilesTemplates.add(reportTemplate); @@ -86,9 +100,12 @@ public class ReportGenerationService { excelTemplateReportGenerationService.generateReport(reportEntries, reportMessage.getDossierTemplateId(), multiFileWorkbook.getWorkbook(), fileStatus, project, j == reportMessage.getFileIds() .size() - 1); } + for (MultiFileDocument multiFileDocument : multiFileDocuments) { + wordReportGenerationService.generateReport(ReportType.WORD_TEMPLATE_MULTI_FILE, reportEntries, reportMessage.getDossierTemplateId(), multiFileDocument.getDocument(), fileStatus, project, j == reportMessage.getFileIds() + .size() - 1); + } for (ReportTemplate reportTemplate : singleFilesTemplates) { if (reportTemplate.getFileName().endsWith(".xlsx")) { - byte[] excelTemplate = reportStorageService.getReportTemplate(reportTemplate.getStorageId()); try (ByteArrayInputStream is = new ByteArrayInputStream(excelTemplate)) { XSSFWorkbook workbook = new XSSFWorkbook(is); @@ -101,10 +118,16 @@ public class ReportGenerationService { throw new RuntimeException("Could not generate singlefile excel report."); } } else { - byte[] template = wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, reportMessage.getDossierTemplateId(), reportTemplate, fileStatus, project); - String storageId = reportStorageService.storeObject(reportMessage.getDownloadId(), template); - storedFileInformation.add(new StoredFileInformation(reportMessage.getFileIds() - .get(j), storageId, ReportType.WORD_SINGLE_FILE, reportTemplate.getTemplateId())); + byte[] wordTemplate= reportStorageService.getReportTemplate(reportTemplate.getStorageId()); + try (ByteArrayInputStream is = new ByteArrayInputStream(wordTemplate)) { + XWPFDocument doc = new XWPFDocument(is); + wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, reportMessage.getDossierTemplateId(), doc, fileStatus, project, true); + byte[] template = wordReportGenerationService.toByteArray(doc); + String storageId = reportStorageService.storeObject(reportMessage.getDownloadId(), template); + storedFileInformation.add(new StoredFileInformation(reportMessage.getFileIds().get(j), storageId, ReportType.WORD_SINGLE_FILE, reportTemplate.getTemplateId())); + } catch (IOException e) { + throw new RuntimeException("Could not generate singlefile word report."); + } } } @@ -120,6 +143,12 @@ public class ReportGenerationService { storedFileInformation.add(new StoredFileInformation(null, storageId, ReportType.EXCEL_TEMPLATE_MULTI_FILE, multiFileWorkbook.getTemplateId())); } + for (MultiFileDocument multiFileDocument : multiFileDocuments) { + byte[] template = wordReportGenerationService.toByteArray(multiFileDocument.getDocument()); + String storageId = reportStorageService.storeObject(reportMessage.getDownloadId(), template); + storedFileInformation.add(new StoredFileInformation( null, storageId, ReportType.WORD_TEMPLATE_MULTI_FILE, multiFileDocument.getTemplateId())); + } + return storedFileInformation; } diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/WordReportGenerationService.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/WordReportGenerationService.java index 11d6bd0..662981b 100644 --- a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/WordReportGenerationService.java +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/WordReportGenerationService.java @@ -35,6 +35,9 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -51,6 +54,7 @@ import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.apache.poi.xwpf.usermodel.XWPFTableRow; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; import org.springframework.stereotype.Service; import com.iqser.red.service.persistence.service.v1.api.model.dossiertemplate.DossierAttributeConfig; @@ -69,6 +73,7 @@ import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEnt import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService; import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @Slf4j @@ -77,15 +82,13 @@ import lombok.extern.slf4j.Slf4j; public class WordReportGenerationService { private final FileAttributesConfigClient fileAttributesClient; - private final ReportStorageService reportStorageService; private final DossierAttributesClient dossierAttributesClient; private final DossierAttributesConfigClient dossierAttributesConfigClient; private final IuclidFunctionService iuclidFunctionService; - public byte[] generateReport(ReportType reportType, List reportEntries, - String dossierTemplateId, ReportTemplate reportTemplate, FileModel fileStatus, - Dossier dossier) { + public XWPFDocument generateReport(ReportType reportType, List reportEntries, String dossierTemplateId, XWPFDocument doc, FileModel fileStatus, + Dossier dossier, boolean isLastFile) { List placeholders = getDefaultPlaceholders(); List imagePlaceholders = new ArrayList<>(); @@ -105,8 +108,7 @@ public class WordReportGenerationService { imagePlaceholders.add(new ImagePlaceholder(attributeConfig.getPlaceholder(), Base64.getDecoder() .decode(dossierAttribute.getValue().split(",")[1]))); } else { - imagePlaceholders.add(new ImagePlaceholder(attributeConfig.getPlaceholder(), Base64.getDecoder() - .decode(dossierAttribute.getValue()))); + imagePlaceholders.add(new ImagePlaceholder(attributeConfig.getPlaceholder(), Base64.getDecoder().decode(dossierAttribute.getValue()))); } } } else { @@ -127,25 +129,25 @@ public class WordReportGenerationService { placeholders.addAll(fileAttributePlaceholders.keySet()); placeholders.addAll(dossierAttributesPlaceholder.keySet()); - byte[] template; - String storageId = reportTemplate.getStorageId(); - template = reportStorageService.getReportTemplate(storageId); - try (ByteArrayInputStream is = new ByteArrayInputStream(template)) { - XWPFDocument doc = new XWPFDocument(is); + try { + for (ImagePlaceholder imagePlaceholder : imagePlaceholders) { replaceImagePlaceholders(doc, imagePlaceholder); } - addTableRows(doc, reportEntries, fileStatus.getFilename(), fileStatus, fileAttributePlaceholders); + XWPFTable table = getRedactionTable(doc); + Map placeholderCellPos = computePlaceholderPos(table); + addTableRows(table, reportEntries, fileStatus.getFilename(), fileStatus, fileAttributePlaceholders, placeholderCellPos); for (String placeholder : placeholders) { String placeholderValue = getPlaceholderValue(placeholder, dossier, fileStatus, fileAttributePlaceholders, dossierAttributesPlaceholder, reportEntries); if (placeholderValue != null) { replaceTextPlaceholders(doc, placeholder, placeholderValue); } } - return toByteArray(doc); - } catch (IOException e) { - throw new RuntimeException(e); + if(!isLastFile) { + readdPlaceholders(table, placeholderCellPos); + } + return doc; } catch (Exception e) { log.error(e.getMessage() + " in file: " + fileStatus.getFilename()); throw new RuntimeException(e); @@ -186,10 +188,8 @@ public class WordReportGenerationService { } - private String getPlaceholderValue(String placeholder, Dossier project, FileModel fileStatus, - Map fileAttributePlaceholders, - Map dossierAttributesPlaceholders, - List reportRedactionEntries) { + private String getPlaceholderValue(String placeholder, Dossier project, FileModel fileStatus, Map fileAttributePlaceholders, + Map dossierAttributesPlaceholders, List reportRedactionEntries) { if (placeholder.equals(FORMAT_DATE_ISO_PLACEHOLDER)) { return OffsetDateTime.now().format(FORMAT_DATE_ISO); @@ -228,8 +228,7 @@ public class WordReportGenerationService { } - private void replaceParagraphForImagePlaceholder(List paragraphs, - ImagePlaceholder imagePlaceholder) { + private void replaceParagraphForImagePlaceholder(List paragraphs, ImagePlaceholder imagePlaceholder) { for (XWPFParagraph p : paragraphs) { String paragraphText = p.getText(); @@ -324,30 +323,33 @@ public class WordReportGenerationService { } - private void addTableRows(XWPFDocument doc, List reportEntries, String filename, - FileModel fileStatus, Map fileAttributePlaceholders) { + private Map computePlaceholderPos(XWPFTable table) { + Map placeholderCellPos = new HashMap<>(); + + if(table != null) { + int placeholderRow = -1; + 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); + if (containsRedactionPlaceholder(cell.getText())) { + placeholderCellPos.put(i, cell.getText()); + placeholderRow = j; + } else if (cell.getText().isEmpty()) { + placeholderCellPos.put(i, ""); + } + } + } + table.removeRow(placeholderRow); + } + return placeholderCellPos; + } + + private void addTableRows(XWPFTable table, List reportEntries, String filename, FileModel fileStatus, Map fileAttributePlaceholders, Map placeholderCellPos) { - XWPFTable table = getRedactionTable(doc); if (table == null) { return; } - Map placeholderCellPos = new HashMap<>(); - - int placeholderRow = -1; - 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); - if (containsRedactionPlaceholder(cell.getText())) { - placeholderCellPos.put(i, cell.getText()); - placeholderRow = j; - } else if (cell.getText().isEmpty()) { - placeholderCellPos.put(i, ""); - } - } - } - table.removeRow(placeholderRow); - if (placeholderCellPos.containsValue(SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER)) { var redactionsPerJustification = getRedactionsPerJustification(reportEntries); for (Map.Entry> entry : redactionsPerJustification.entrySet()) { @@ -374,6 +376,14 @@ public class WordReportGenerationService { } } + private void readdPlaceholders(XWPFTable table, Map placeholderCellPos) { + XWPFTableRow newRow = table.createRow(); + for(int i = 0; i < table.getRow(0).getTableCells().size(); i++) { + String placeholder = placeholderCellPos.get(i); + setText(newRow.getCell(i), placeholder); + } + } + private String replaceTextPlaceholderWithEntries(ReportRedactionEntry entry, String filename, String placeholder) { @@ -411,17 +421,13 @@ public class WordReportGenerationService { } - private String replaceSeedsPlaceholder(Map.Entry> entry, String filename, - String placeholder, FileModel fileStatus, + private String replaceSeedsPlaceholder(Map.Entry> entry, String filename, String placeholder, FileModel fileStatus, Map fileAttributePlaceholders) { if (placeholder.equals(SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER)) { - return entry.getValue() - .stream() - .map(ReportRedactionEntry::getPage) - .distinct() - .map(Object::toString) - .collect(Collectors.joining(", ")); + var pages = entry.getValue().stream().map(ReportRedactionEntry::getPage).collect(Collectors.toSet()); + return computePageRanges(pages); + } if (placeholder.equals(SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER)) { return entry.getKey(); @@ -442,6 +448,49 @@ public class WordReportGenerationService { } + private String computePageRanges(Set pages) { + + StringBuilder result = new StringBuilder(); + + SortedSet numbers = new TreeSet(pages); + + Integer start = null; + Integer end = null; + + for (Integer num : numbers) { + //initialize + if (start == null || end == null) { + start = num; + end = num; + } + //next number in range + else if (end.equals(num - 1)) { + end = num; + } + //there's a gap + else { + //range length 1 + if (start.equals(end)) { + result.append(start).append(","); + } + //range lenth 2 and more + else { + result.append(start).append("-").append(end).append(","); + } + + start = num; + end = num; + } + } + if (start.equals(end)) { + result.append(start); + } else { + result.append(start).append("-").append(end); + } + return result.toString(); + } + + private Dimension2DDouble getImageDimension(ByteArrayInputStream bais) throws IOException { BufferedImage bufImg = ImageIO.read(bais); @@ -474,12 +523,15 @@ public class WordReportGenerationService { return new ColoredText(textForLine, null); } + private Map> getRedactionsPerJustification(List reportRedactionEntryList) { + return reportRedactionEntryList.stream().sorted(Comparator.comparing(ReportRedactionEntry::getPage)).collect(Collectors.groupingBy(ReportRedactionEntry::getJustification)); } - private byte[] toByteArray(XWPFDocument doc) throws IOException { + @SneakyThrows + public byte[] toByteArray(XWPFDocument doc) { try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { doc.write(byteArrayOutputStream); diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/RedactionReportIntegrationTest.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/RedactionReportIntegrationTest.java index 0823db3..16203b9 100644 --- a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/RedactionReportIntegrationTest.java +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/java/com/iqser/red/service/redaction/report/v1/server/RedactionReportIntegrationTest.java @@ -28,6 +28,7 @@ import com.iqser.red.storage.commons.service.StorageService; import lombok.SneakyThrows; import org.apache.commons.io.IOUtils; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -168,15 +169,10 @@ public class RedactionReportIntegrationTest { .build()); ClassPathResource templateResource = new ClassPathResource("templates/Seeds - New Justification Form.docx"); - when(reportStorageService.getReportTemplate(storageId)).thenReturn(IOUtils.toByteArray(templateResource.getInputStream())); - ReportTemplate reportTemplate = ReportTemplate.builder() - .dossierTemplateId("dossierTemplateId") - .templateId("templateId") - .fileName("fileName") - .storageId("storageId") - .uploadDate(OffsetDateTime.now()) - .build(); - byte[] report = wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, reportTemplate, fileStatus, project); + + XWPFDocument doc = new XWPFDocument(templateResource.getInputStream()); + wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, doc, fileStatus, project, true); + byte[] report = wordReportGenerationService.toByteArray(doc); try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/efsa_template_wrg.docx")) { fileOutputStream.write(report); @@ -207,7 +203,7 @@ public class RedactionReportIntegrationTest { List reportEntries = redactionLogConverterService.convertAndSort(redactionLog, legalBasisMapping); List reportEntries2 = redactionLogConverterService.convertAndSort(redactionLog2, legalBasisMapping); - DossierAttributeConfig dossierAttributeConfig = new DossierAttributeConfig("id", "label", true, "{{dossier.attribute.name}}", DossierAttributeType.TEXT, dossierTemplateId);// + DossierAttributeConfig dossierAttributeConfig = new DossierAttributeConfig("id", "label", true, "{{dossier.attribute.name}}", DossierAttributeType.TEXT, dossierTemplateId); DossierAttributeConfig dossierAttributeConfig2 = new DossierAttributeConfig("id2", "label2", false, "{{dossier.attribute.Signature}}", DossierAttributeType.IMAGE, dossierTemplateId); when(dossierAttributesConfigClient.getDossierAttributes(dossierTemplateId)).thenReturn(List.of(dossierAttributeConfig, dossierAttributeConfig2)); @@ -293,27 +289,17 @@ public class RedactionReportIntegrationTest { .build()); ClassPathResource wordTemplateResource = new ClassPathResource("templates/Justification Appendix A1.docx"); - when(reportStorageService.getReportTemplate(storageId)).thenReturn(IOUtils.toByteArray(wordTemplateResource.getInputStream())); - ReportTemplate reportTemplate = ReportTemplate.builder() - .dossierTemplateId("dossierTemplateId") - .templateId("templateId") - .fileName("fileName") - .storageId("storageId") - .uploadDate(OffsetDateTime.now()) - .build(); - byte[] wordReport = wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, reportTemplate, fileModel, dossier); + + XWPFDocument doc = new XWPFDocument(wordTemplateResource.getInputStream()); + wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, doc, fileModel, dossier, true); + byte[] wordReport = wordReportGenerationService.toByteArray(doc); try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/efsa_template1.docx")) { fileOutputStream.write(wordReport); } - ReportTemplate reportTemplate2 = ReportTemplate.builder() - .dossierTemplateId("dossierTemplateId") - .templateId("templateId") - .fileName("fileNameReportTemplate2") - .storageId("storageId") - .uploadDate(OffsetDateTime.now()) - .build(); - byte[] wordReport2 = wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries2, dossierTemplateId, reportTemplate2, fileModel2, dossier); + doc = new XWPFDocument(wordTemplateResource.getInputStream()); + wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries2, dossierTemplateId, doc, fileModel2, dossier, true); + byte[] wordReport2 = wordReportGenerationService.toByteArray(doc); try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/efsa_template2.docx")) { fileOutputStream.write(wordReport2); } @@ -392,15 +378,10 @@ public class RedactionReportIntegrationTest { .build()); ClassPathResource templateResource = new ClassPathResource("templates/6464 appendix_b EFSA dRAR justification.docx"); - when(reportStorageService.getReportTemplate(storageId)).thenReturn(IOUtils.toByteArray(templateResource.getInputStream())); - ReportTemplate reportTemplate = ReportTemplate.builder() - .dossierTemplateId("dossierTemplateId") - .templateId("templateId") - .fileName("filename") - .storageId("storageId") - .uploadDate(OffsetDateTime.now()) - .build(); - byte[] report = wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, reportTemplate, fileModel, project); + + XWPFDocument doc = new XWPFDocument(templateResource.getInputStream()); + wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, doc, fileModel, project, true); + byte[] report = wordReportGenerationService.toByteArray(doc); try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/efsa_template13.docx")) { fileOutputStream.write(report); @@ -453,7 +434,10 @@ public class RedactionReportIntegrationTest { .storageId("storageId") .uploadDate(OffsetDateTime.now()) .build(); - byte[] report = wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, reportTemplate, fileStatus, project); + + XWPFDocument doc = new XWPFDocument(templateResource.getInputStream()); + wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, doc, fileStatus, project, true); + byte[] report = wordReportGenerationService.toByteArray(doc); try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/iuclid_report_2.docx")) { fileOutputStream.write(report); @@ -530,13 +514,16 @@ public class RedactionReportIntegrationTest { String dossierTemplateId = "dossierTemplateId"; ClassPathResource redactionLogResource = new ClassPathResource("files/redactionLog2817.json"); + ClassPathResource redactionLogResource2 = new ClassPathResource("files/redactionLog.json"); RedactionLog redactionLog = objectMapper.readValue(redactionLogResource.getInputStream(), RedactionLog.class); + RedactionLog redactionLog2 = objectMapper.readValue(redactionLogResource2.getInputStream(), RedactionLog.class); ClassPathResource legalBasisMappingResource = new ClassPathResource("files/legalBasisMappingNew.json"); List legalBasisMapping = objectMapper.readValue(legalBasisMappingResource.getInputStream(), new TypeReference<>() { }); List reportEntries = redactionLogConverterService.convertAndSort(redactionLog, legalBasisMapping); + List reportEntries2 = redactionLogConverterService.convertAndSort(redactionLog2, legalBasisMapping); when(dossierAttributesConfigClient.getDossierAttributes(dossierTemplateId)).thenReturn(new ArrayList<>()); when(dossierAttributesClient.getDossierAttributes("dossierId")).thenReturn(new ArrayList<>()); @@ -544,6 +531,7 @@ public class RedactionReportIntegrationTest { FileModel fileStatus = FileModel.builder().filename("VV123456").build(); + FileModel fileStatus2 = FileModel.builder().filename("second file").build(); Dossier project = Dossier.builder().id("dossierId").dossierName("projectName").build(); @@ -554,16 +542,12 @@ public class RedactionReportIntegrationTest { .storageId(storageId) .build()); - ClassPathResource templateResource = new ClassPathResource("templates/Seeds - New Justification Form.docx"); + ClassPathResource templateResource = new ClassPathResource("templates/Seeds-NewJustificationForm.docx"); when(reportStorageService.getReportTemplate(storageId)).thenReturn(IOUtils.toByteArray(templateResource.getInputStream())); - ReportTemplate reportTemplate = ReportTemplate.builder() - .dossierTemplateId("dossierTemplateId") - .templateId("templateId") - .fileName("fileName") - .storageId("storageId") - .uploadDate(OffsetDateTime.now()) - .build(); - byte[] report = wordReportGenerationService.generateReport(ReportType.WORD_SINGLE_FILE, reportEntries, dossierTemplateId, reportTemplate, fileStatus, project); + XWPFDocument doc = new XWPFDocument(templateResource.getInputStream()); + doc = wordReportGenerationService.generateReport(ReportType.WORD_TEMPLATE_MULTI_FILE, reportEntries, dossierTemplateId, doc, fileStatus, project, false); + doc = wordReportGenerationService.generateReport(ReportType.WORD_TEMPLATE_MULTI_FILE, reportEntries2, dossierTemplateId, doc, fileStatus2, project, true); + byte[] report = wordReportGenerationService.toByteArray(doc); try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/seedsReport.docx")) { fileOutputStream.write(report); diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/templates/Seeds-NewJustificationForm.docx b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/templates/Seeds-NewJustificationForm.docx new file mode 100644 index 0000000000000000000000000000000000000000..80c4eb2f3c450816f85a4a0c59af222355d9bbb8 GIT binary patch literal 62329 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 literal 0 HcmV?d00001