diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/ColoredText.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/ColoredText.java new file mode 100644 index 0000000..d740345 --- /dev/null +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/ColoredText.java @@ -0,0 +1,13 @@ +package com.iqser.red.service.redaction.report.v1.server.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +@AllArgsConstructor +public class ColoredText { + private String text; + private String color; +} diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/ReportRedactionEntry.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/ReportRedactionEntry.java index 4a19ff4..706c291 100644 --- a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/ReportRedactionEntry.java +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/model/ReportRedactionEntry.java @@ -15,4 +15,5 @@ public class ReportRedactionEntry { private String justificationParagraph; private String justificationReason; private String excerpt; + private String value; } diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/IuclidFunctionService.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/IuclidFunctionService.java new file mode 100644 index 0000000..d64b132 --- /dev/null +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/IuclidFunctionService.java @@ -0,0 +1,59 @@ +package com.iqser.red.service.redaction.report.v1.server.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Service; + +import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEntry; + +@Service +public class IuclidFunctionService { + + public String computeIuclidFunction(List reportRedactionEntries, String filename) { + + Map> entriesPerJustification = new HashMap<>(); + reportRedactionEntries.forEach(reportRedactionEntry -> { + entriesPerJustification.computeIfAbsent(reportRedactionEntry.getJustification(), (x) -> new ArrayList<>()) + .add(reportRedactionEntry); + }); + + StringBuilder s = new StringBuilder(); + s.append(removeExtension(filename)); + s.append("\n\n\n"); + entriesPerJustification.keySet().forEach(key -> { + s.append("<[]>"); + s.append(key.replaceAll("\n", "\n<[]>")); + s.append("\n\n"); + s.append("relates to: "); + Iterator iterator = entriesPerJustification.get(key).iterator(); + while (iterator.hasNext()) { + ReportRedactionEntry entry = iterator.next(); + s.append("p").append(entry.getPage()); + s.append(" ").append(entry.getValue() != null ? entry.getValue() : "non-readable content"); + if (iterator.hasNext()) { + s.append(", "); + } + } + s.append("\n\n\n"); + + }); + + return s.toString(); + } + + + private String removeExtension(String fileName) { + + var index = fileName.lastIndexOf("."); + if (index > 0) { + return fileName.substring(0, index); + } else { + return fileName; + } + } + +} diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/PlaceholderService.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/PlaceholderService.java index 93dee16..8d7efbd 100644 --- a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/PlaceholderService.java +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/PlaceholderService.java @@ -1,12 +1,13 @@ package com.iqser.red.service.redaction.report.v1.server.service; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - import java.time.format.DateTimeFormatter; import java.util.List; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + @Slf4j @Service @RequiredArgsConstructor @@ -32,10 +33,12 @@ public class PlaceholderService { public static final String DOSSIER_NAME_PLACEHOLDER = "{{dossier.name}}"; + public static final String IUCLID_FUNCTION_PLACEHOLDER = "{{function.iuclidreport}}"; + public List getGeneralPlaceholders() { - return List.of(FILE_NAME_PLACEHOLDER, PAGE_PLACEHOLDER, PARAGRAPH_PLACEHOLDER, JUSTIFICATION_PLACEHOLDER, JUSTIFICATION_PARAGRAPH_PLACEHOLDER, JUSTIFICATION_REASON_PLACEHOLDER, EXCERPT_PLACEHOLDER, FORMAT_DATE_ISO_PLACEHOLDER, FORMAT_DATE_GER_PLACEHOLDER, FORMAT_DATE_ENG_PLACEHOLDER, FORMAT_TIME_ISO_PLACEHOLDER, DOSSIER_NAME_PLACEHOLDER); + return List.of(FILE_NAME_PLACEHOLDER, PAGE_PLACEHOLDER, PARAGRAPH_PLACEHOLDER, JUSTIFICATION_PLACEHOLDER, JUSTIFICATION_PARAGRAPH_PLACEHOLDER, JUSTIFICATION_REASON_PLACEHOLDER, EXCERPT_PLACEHOLDER, FORMAT_DATE_ISO_PLACEHOLDER, FORMAT_DATE_GER_PLACEHOLDER, FORMAT_DATE_ENG_PLACEHOLDER, FORMAT_TIME_ISO_PLACEHOLDER, DOSSIER_NAME_PLACEHOLDER, IUCLID_FUNCTION_PLACEHOLDER); } } diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/RedactionLogConverterService.java b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/RedactionLogConverterService.java index 0847e95..4fa87ec 100644 --- a/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/RedactionLogConverterService.java +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/main/java/com/iqser/red/service/redaction/report/v1/server/service/RedactionLogConverterService.java @@ -63,7 +63,7 @@ public class RedactionLogConverterService { .filter(lbm -> lbm.getReason().equalsIgnoreCase(entry.getLegalBasis())) .findAny() .map(LegalBasis::getDescription) - .orElse(""), checkTextForNull(entry.getTextBefore()) + entry.getValue() + checkTextForNull(entry.getTextAfter()))); + .orElse(""), checkTextForNull(entry.getTextBefore()) + entry.getValue() + checkTextForNull(entry.getTextAfter()), entry.getValue())); } } } 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 61fd656..ad87f42 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 @@ -10,10 +10,13 @@ import com.iqser.red.service.redaction.report.v1.api.model.ReportType; import com.iqser.red.service.redaction.report.v1.server.client.DossierAttributesClient; import com.iqser.red.service.redaction.report.v1.server.client.DossierAttributesConfigClient; import com.iqser.red.service.redaction.report.v1.server.client.FileAttributesConfigClient; +import com.iqser.red.service.redaction.report.v1.server.model.ColoredText; import com.iqser.red.service.redaction.report.v1.server.model.ImagePlaceholder; import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEntry; import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService; import lombok.RequiredArgsConstructor; + +import org.apache.commons.lang3.StringUtils; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.util.Units; import org.apache.poi.xwpf.usermodel.*; @@ -36,6 +39,7 @@ public class WordReportGenerationService { private final ReportStorageService reportStorageService; private final DossierAttributesClient dossierAttributesClient; private final DossierAttributesConfigClient dossierAttributesConfigClient; + private final IuclidFunctionService iuclidFunctionService; public byte[] generateReport(ReportType reportType, List reportEntries, @@ -93,7 +97,7 @@ public class WordReportGenerationService { } addTableRows(doc, reportEntries, fileStatus.getFilename()); for (String placeholder : placeholders) { - String placeholderValue = getPlaceholderValue(placeholder, dossier, fileStatus, fileAttributePlaceholders, dossierAttributesPlaceholder); + String placeholderValue = getPlaceholderValue(placeholder, dossier, fileStatus, fileAttributePlaceholders, dossierAttributesPlaceholder, reportEntries); if (placeholderValue != null) { replaceTextPlaceholders(doc, placeholder, placeholderValue); } @@ -123,7 +127,7 @@ public class WordReportGenerationService { private List getDefaultPlaceholders() { List defPlaceholders = new ArrayList<>(); - defPlaceholders.addAll(Arrays.asList(FILE_NAME_PLACEHOLDER, FORMAT_DATE_ISO_PLACEHOLDER, FORMAT_DATE_GER_PLACEHOLDER, FORMAT_DATE_ENG_PLACEHOLDER, FORMAT_TIME_ISO_PLACEHOLDER, DOSSIER_NAME_PLACEHOLDER)); + defPlaceholders.addAll(Arrays.asList(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)); return defPlaceholders; } @@ -142,7 +146,8 @@ public class WordReportGenerationService { private String getPlaceholderValue(String placeholder, Dossier project, FileModel fileStatus, Map fileAttributePlaceholders, - Map dossierAttributesPlaceholders) { + Map dossierAttributesPlaceholders, + List reportRedactionEntries) { if (placeholder.equals(FORMAT_DATE_ISO_PLACEHOLDER)) { return OffsetDateTime.now().format(FORMAT_DATE_ISO); @@ -162,6 +167,9 @@ public class WordReportGenerationService { if (placeholder.equals(FILE_NAME_PLACEHOLDER)) { return fileStatus.getFilename(); } + if (placeholder.equals(IUCLID_FUNCTION_PLACEHOLDER)) { + return iuclidFunctionService.computeIuclidFunction(reportRedactionEntries, fileStatus.getFilename()); + } if (fileAttributePlaceholders.containsKey(placeholder)) { String id = fileAttributePlaceholders.get(placeholder); @@ -221,11 +229,24 @@ public class WordReportGenerationService { if (paragraphText.contains(search)) { String safeToUseInReplaceAllString = Pattern.quote(search); paragraphText = paragraphText.replaceAll(safeToUseInReplaceAllString, replace); - XWPFRun run = p.getRuns().get(0); - run.setText(paragraphText, 0); int size = p.getRuns().size(); - for (int i = 1; i < size; i++) { - p.removeRun(1); + for (int i = 0; i <= size; i++) { + p.removeRun(0); + } + if (paragraphText.contains("\n")) { + String[] stringsOnNewLines = paragraphText.split("\n"); + for (int i = 0; i < stringsOnNewLines.length; i++) { + p.insertNewRun(i); + XWPFRun newRun = p.getRuns().get(i); + String textForLine = stringsOnNewLines[i]; + ColoredText coloredText = getColor(textForLine); + newRun.setText(coloredText.getText()); + if (coloredText.getColor() != null) { + newRun.setTextHighlightColor(coloredText.getColor()); + } + newRun.addCarriageReturn(); + + } } } } @@ -316,6 +337,15 @@ public class WordReportGenerationService { run.setText(value); } + private ColoredText getColor(String textForLine) { + + if (textForLine.contains("<[]>"); + String text = StringUtils.substringAfter(textForLine, ">]>"); + return new ColoredText(text, color); + } + return new ColoredText(textForLine, null); + } private byte[] toByteArray(XWPFDocument doc) throws IOException { 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 60d6ec8..1797807 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 @@ -54,6 +54,8 @@ import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageSer import com.iqser.red.service.redaction.v1.model.RedactionLog; import com.iqser.red.storage.commons.service.StorageService; +import lombok.SneakyThrows; + @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT) public class RedactionReportIntegrationTest { @@ -405,6 +407,60 @@ public class RedactionReportIntegrationTest { } } + @Test + @SneakyThrows + public void testIuclidReport() { + String dossierTemplateId = "dossierTemplateId"; + + ClassPathResource redactionLogResource = new ClassPathResource("files/redactionLog.json"); + + RedactionLog redactionLog = objectMapper.readValue(redactionLogResource.getInputStream(), RedactionLog.class); + + ClassPathResource legalBasisMappingResource = new ClassPathResource("files/legalBasisMapping.json"); + + List legalBasisMapping = objectMapper.readValue(legalBasisMappingResource.getInputStream(), new TypeReference<>() { + }); + + List reportEntries = redactionLogConverterService.convertAndSort(redactionLog, legalBasisMapping); + + + when(dossierAttributesConfigClient.getDossierAttributes(dossierTemplateId)).thenReturn(new ArrayList<>()); + + + when(dossierAttributesClient.getDossierAttributes("dossierId")).thenReturn(new ArrayList<>()); + + + when(fileAttributesConfigClient.getFileAttributeConfigs(dossierTemplateId)).thenReturn(new ArrayList<>()); + + + FileModel fileStatus = FileModel.builder().filename("filename").build(); + + Dossier project = Dossier.builder().id("dossierId").dossierName("projectName").build(); + + String templateId = "templateId"; + String storageId = "storageId"; + when(reportTemplateClient.getReportTemplate(dossierTemplateId, templateId)).thenReturn(ReportTemplate.builder() + .dossierTemplateId(dossierTemplateId) + .storageId(storageId) + .build()); + + ClassPathResource templateResource = new ClassPathResource("templates/IUCLID_Template.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); + + try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/iuclid_report.docx")) { + fileOutputStream.write(report); + } + } + + private static String getTemporaryDirectory() { String tmpdir = System.getProperty("java.io.tmpdir"); if (StringUtils.isNotBlank(tmpdir)) { diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/redactionLog.json b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/redactionLog.json index aaef186..1aa54ed 100644 --- a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/redactionLog.json +++ b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/files/redactionLog.json @@ -726,7 +726,7 @@ "value": "Syngenta Crop Protection AG", "reason": "Address found", "matchedRule": 2, - "legalBasis": "Article 39(e)(1) and Article 39(e)(2) of Regulation (EC) No 178/2002", + "legalBasis": "Article 63(2)(a) of Regulation (EC) No 1107/2009 (making reference to Article 39 of Regulation EC No 178/2002)", "redacted": true, "section": "1 Statement of subject matter and purpose for which this report\nhas been prepared and background information on the application", "color": [ diff --git a/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/templates/IUCLID_Template.docx b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/templates/IUCLID_Template.docx new file mode 100644 index 0000000..3ed1fbc Binary files /dev/null and b/redaction-report-service-v1/redaction-report-service-server-v1/src/test/resources/templates/IUCLID_Template.docx differ