Pull request #93: RED-2560

Merge in RED/redaction-report-service from RED-2560-port to master

* commit '8dc9cadbe173b96713affd33824df8295b20b7a0':
  RED-2560 Syngenta RFC: IUCLID Justification Form
This commit is contained in:
Ali Oezyetimoglu 2021-11-04 13:32:54 +01:00
commit 004b737f3a
9 changed files with 176 additions and 14 deletions

View File

@ -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;
}

View File

@ -15,4 +15,5 @@ public class ReportRedactionEntry {
private String justificationParagraph;
private String justificationReason;
private String excerpt;
private String value;
}

View File

@ -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<ReportRedactionEntry> reportRedactionEntries, String filename) {
Map<String, List<ReportRedactionEntry>> 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("<[<color:yellow>]>");
s.append(key.replaceAll("\n", "\n<[<color:yellow>]>"));
s.append("\n\n");
s.append("relates to: ");
Iterator<ReportRedactionEntry> 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;
}
}
}

View File

@ -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<String> 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);
}
}

View File

@ -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()));
}
}
}

View File

@ -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<ReportRedactionEntry> 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<String> getDefaultPlaceholders() {
List<String> 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<String, String> fileAttributePlaceholders,
Map<String, String> dossierAttributesPlaceholders) {
Map<String, String> dossierAttributesPlaceholders,
List<ReportRedactionEntry> 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("<[<color:")) {
String color = StringUtils.substringBetween(textForLine, "<[<color:", ">]>");
String text = StringUtils.substringAfter(textForLine, ">]>");
return new ColoredText(text, color);
}
return new ColoredText(textForLine, null);
}
private byte[] toByteArray(XWPFDocument doc) throws IOException {

View File

@ -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<LegalBasis> legalBasisMapping = objectMapper.readValue(legalBasisMappingResource.getInputStream(), new TypeReference<>() {
});
List<ReportRedactionEntry> 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)) {

View File

@ -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": [