RED-6686 Extract Tenant and user-management code into a separate service.

This commit is contained in:
Timo Bejan 2023-06-26 21:47:12 +02:00
parent 8c296b5a53
commit 2a26c5ac9d
29 changed files with 991 additions and 1347 deletions

View File

@ -12,7 +12,16 @@
<artifactId>redaction-report-service-server-v1</artifactId>
<properties>
<tennat-commons.version>0.6.0</tennat-commons.version>
</properties>
<dependencies>
<dependency>
<groupId>com.knecon.fforesight</groupId>
<artifactId>tenant-commons</artifactId>
<version>${tennat-commons.version}</version>
</dependency>
<dependency>
<groupId>com.iqser.red.service</groupId>
<artifactId>redaction-report-service-api-v1</artifactId>

View File

@ -2,6 +2,7 @@ package com.iqser.red.service.redaction.report.v1.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@ -12,18 +13,17 @@ import org.springframework.scheduling.annotation.EnableAsync;
import com.iqser.red.service.redaction.report.v1.server.client.DossierClient;
import com.iqser.red.service.redaction.report.v1.server.configuration.MessagingConfiguration;
import com.iqser.red.service.redaction.report.v1.server.multitenancy.AsyncConfig;
import com.iqser.red.service.redaction.report.v1.server.multitenancy.MultiTenancyMessagingConfiguration;
import com.iqser.red.service.redaction.report.v1.server.multitenancy.MultiTenancyWebConfiguration;
import com.iqser.red.service.redaction.report.v1.server.settings.ReportTemplateSettings;
import com.iqser.red.storage.commons.StorageAutoConfiguration;
import com.knecon.fforesight.tenantcommons.MultiTenancyAutoConfiguration;
import io.micrometer.core.aop.TimedAspect;
import io.micrometer.core.instrument.MeterRegistry;
@EnableAsync
@ImportAutoConfiguration({MultiTenancyAutoConfiguration.class})
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class})
@Import({MultiTenancyWebConfiguration.class, AsyncConfig.class, MessagingConfiguration.class, MultiTenancyMessagingConfiguration.class, StorageAutoConfiguration.class})
@Import({MessagingConfiguration.class, StorageAutoConfiguration.class})
@EnableFeignClients(basePackageClasses = {DossierClient.class})
@EnableConfigurationProperties(ReportTemplateSettings.class)
public class Application {

View File

@ -1,10 +0,0 @@
package com.iqser.red.service.redaction.report.v1.server.client;
import org.springframework.cloud.openfeign.FeignClient;
import com.iqser.red.service.persistence.service.v1.api.internal.resources.TenantsResource;
@FeignClient(name = "TenantsResource", url = "${persistence-service.url}")
public interface TenantsClient extends TenantsResource {
}

View File

@ -1,15 +1,17 @@
package com.iqser.red.service.redaction.report.v1.server.controller;
import com.amazonaws.services.kms.model.NotFoundException;
import com.iqser.red.commons.spring.ErrorMessage;
import lombok.extern.slf4j.Slf4j;
import java.time.OffsetDateTime;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.time.OffsetDateTime;
import com.amazonaws.services.kms.model.NotFoundException;
import com.iqser.red.commons.spring.ErrorMessage;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestControllerAdvice
@ -17,6 +19,7 @@ public class ControllerAdvice {
/* error handling */
@ResponseBody
@ResponseStatus(value = HttpStatus.NOT_FOUND)
@ExceptionHandler(value = NotFoundException.class)
@ -25,4 +28,5 @@ public class ControllerAdvice {
log.error(e.getMessage(), e);
return new ErrorMessage(OffsetDateTime.now(), e.getMessage());
}
}

View File

@ -1,7 +1,6 @@
package com.iqser.red.service.redaction.report.v1.server.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -32,11 +31,11 @@ public class RSSController implements RSSResource {
var detailed = rSSService.getRSS(dossierId, fileId);
List<RSSFileResponse> fileResponses = new ArrayList<>();
for (DetailedRSSFileResponse detailedRSSFileResponse : detailed.getFiles()){
for (DetailedRSSFileResponse detailedRSSFileResponse : detailed.getFiles()) {
String fileName = detailedRSSFileResponse.getFilename();
Map<String, String> result = new LinkedHashMap<>();
for(Map.Entry<String, SCMComponent> detailedRss : detailedRSSFileResponse.getResult().entrySet()){
if(detailedRss.getValue().getValue() != null){
for (Map.Entry<String, SCMComponent> detailedRss : detailedRSSFileResponse.getResult().entrySet()) {
if (detailedRss.getValue().getValue() != null) {
result.put(detailedRss.getKey(), detailedRss.getValue().getValue());
} else {
result.put(detailedRss.getKey(), detailedRss.getValue().getOriginalValue());
@ -50,7 +49,7 @@ public class RSSController implements RSSResource {
}
public DetailedRSSResponse getDetailedRSS(@PathVariable(DOSSIER_ID) String dossierId, @RequestParam(value = "fileId", required = false) String fileId){
public DetailedRSSResponse getDetailedRSS(@PathVariable(DOSSIER_ID) String dossierId, @RequestParam(value = "fileId", required = false) String fileId) {
return rSSService.getRSS(dossierId, fileId);
}

View File

@ -1,27 +0,0 @@
package com.iqser.red.service.redaction.report.v1.server.multitenancy;
import java.util.concurrent.Executor;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
public class AsyncConfig extends AsyncConfigurerSupport {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(7);
executor.setMaxPoolSize(42);
executor.setQueueCapacity(11);
executor.setThreadNamePrefix("TenantAwareTaskExecutor-");
executor.setTaskDecorator(new TenantAwareTaskDecorator());
executor.initialize();
return executor;
}
}

View File

@ -1,105 +0,0 @@
package com.iqser.red.service.redaction.report.v1.server.multitenancy;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import jakarta.annotation.PostConstruct;
import lombok.SneakyThrows;
@Service
public class EncryptionDecryptionService {
@Value("${redaction-report-service.crypto.key:redaction}")
private String key;
private SecretKey secretKey;
private byte[] iv;
@SneakyThrows
@PostConstruct
protected void postConstruct() {
SecureRandom secureRandom = new SecureRandom();
iv = new byte[12];
secureRandom.nextBytes(iv);
secretKey = generateSecretKey(key, iv);
}
@SneakyThrows
public String encrypt(String strToEncrypt) {
return Base64.getEncoder().encodeToString(encrypt(strToEncrypt.getBytes()));
}
@SneakyThrows
public String decrypt(String strToDecrypt) {
byte[] bytes = Base64.getDecoder().decode(strToDecrypt);
return new String(decrypt(bytes), StandardCharsets.UTF_8);
}
@SneakyThrows
public byte[] encrypt(byte[] data) {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] encryptedData = cipher.doFinal(data);
ByteBuffer byteBuffer = ByteBuffer.allocate(4 + iv.length + encryptedData.length);
byteBuffer.putInt(iv.length);
byteBuffer.put(iv);
byteBuffer.put(encryptedData);
return byteBuffer.array();
}
@SneakyThrows
public byte[] decrypt(byte[] encryptedData) {
ByteBuffer byteBuffer = ByteBuffer.wrap(encryptedData);
int noonceSize = byteBuffer.getInt();
if (noonceSize < 12 || noonceSize >= 16) {
throw new IllegalArgumentException("Nonce size is incorrect. Make sure that the incoming data is an AES encrypted file.");
}
byte[] iv = new byte[noonceSize];
byteBuffer.get(iv);
SecretKey secretKey = generateSecretKey(key, iv);
byte[] cipherBytes = new byte[byteBuffer.remaining()];
byteBuffer.get(cipherBytes);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, secretKey, parameterSpec);
return cipher.doFinal(cipherBytes);
}
@SneakyThrows
public SecretKey generateSecretKey(String password, byte[] iv) {
KeySpec spec = new PBEKeySpec(password.toCharArray(), iv, 65536, 128); // AES-128
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] key = secretKeyFactory.generateSecret(spec).getEncoded();
return new SecretKeySpec(key, "AES");
}
}

View File

@ -1,17 +0,0 @@
package com.iqser.red.service.redaction.report.v1.server.multitenancy;
import org.springframework.stereotype.Component;
import feign.RequestInterceptor;
import feign.RequestTemplate;
@Component
public class ForwardTenantInterceptor implements RequestInterceptor {
public static final String TENANT_HEADER_NAME = "X-TENANT-ID";
@Override
public void apply(RequestTemplate template) {
template.header(TENANT_HEADER_NAME, TenantContext.getTenantId());
}
}

View File

@ -1,48 +0,0 @@
package com.iqser.red.service.redaction.report.v1.server.multitenancy;
import static com.iqser.red.service.redaction.report.v1.server.multitenancy.ForwardTenantInterceptor.TENANT_HEADER_NAME;
import org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MultiTenancyMessagingConfiguration {
@Bean
public static BeanPostProcessor multitenancyBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof RabbitTemplate) {
((RabbitTemplate) bean).setBeforePublishPostProcessors(m -> {
m.getMessageProperties().setHeader(TENANT_HEADER_NAME, TenantContext.getTenantId());
return m;
});
} else if (bean instanceof AbstractRabbitListenerContainerFactory) {
((AbstractRabbitListenerContainerFactory<?>) bean).setAfterReceivePostProcessors(m -> {
String tenant = m.getMessageProperties().getHeader(TENANT_HEADER_NAME);
if (tenant != null) {
TenantContext.setTenantId(tenant);
} else {
throw new RuntimeException("No Tenant is set queue message");
}
return m;
});
}
return bean;
}
};
}
}

View File

@ -1,28 +0,0 @@
package com.iqser.red.service.redaction.report.v1.server.multitenancy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import com.iqser.red.commons.spring.DefaultWebMvcConfiguration;
@Configuration
public class MultiTenancyWebConfiguration extends DefaultWebMvcConfiguration {
private final TenantInterceptor tenantInterceptor;
@Autowired
public MultiTenancyWebConfiguration(TenantInterceptor tenantInterceptor) {
this.tenantInterceptor = tenantInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addWebRequestInterceptor(tenantInterceptor);
}
}

View File

@ -1,45 +0,0 @@
package com.iqser.red.service.redaction.report.v1.server.multitenancy;
import org.springframework.stereotype.Service;
import com.iqser.red.service.redaction.report.v1.server.client.TenantsClient;
import com.iqser.red.storage.commons.model.AzureStorageConnection;
import com.iqser.red.storage.commons.model.S3StorageConnection;
import com.iqser.red.storage.commons.service.StorageConnectionProvider;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class StorageConnectionProviderImpl implements StorageConnectionProvider {
private final TenantsClient tenantsClient;
private final EncryptionDecryptionService encryptionDecryptionService;
@Override
public AzureStorageConnection getAzureStorageConnection(String tenantId) {
var tenant = tenantsClient.getTenant(tenantId);
return AzureStorageConnection.builder()
.connectionString(encryptionDecryptionService.decrypt(tenant.getAzureStorageConnection().getConnectionString()))
.containerName(tenant.getAzureStorageConnection().getContainerName())
.build();
}
@Override
public S3StorageConnection getS3StorageConnection(String tenantId) {
var tenant = tenantsClient.getTenant(tenantId);
return S3StorageConnection.builder()
.key(tenant.getS3StorageConnection().getKey())
.secret(encryptionDecryptionService.decrypt(tenant.getS3StorageConnection().getSecret()))
.signerType(tenant.getS3StorageConnection().getSignerType())
.bucketName(tenant.getS3StorageConnection().getBucketName())
.region(tenant.getS3StorageConnection().getRegion())
.endpoint(tenant.getS3StorageConnection().getEndpoint())
.build();
}
}

View File

@ -1,23 +0,0 @@
package com.iqser.red.service.redaction.report.v1.server.multitenancy;
import org.springframework.core.task.TaskDecorator;
import org.springframework.lang.NonNull;
public class TenantAwareTaskDecorator implements TaskDecorator {
@Override
@NonNull
public Runnable decorate(@NonNull Runnable runnable) {
String tenantId = TenantContext.getTenantId();
return () -> {
try {
TenantContext.setTenantId(tenantId);
runnable.run();
} finally {
TenantContext.setTenantId(null);
}
};
}
}

View File

@ -1,29 +0,0 @@
package com.iqser.red.service.redaction.report.v1.server.multitenancy;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public final class TenantContext {
private static InheritableThreadLocal<String> currentTenant = new InheritableThreadLocal<>();
public static void setTenantId(String tenantId) {
log.debug("Setting tenantId to " + tenantId);
currentTenant.set(tenantId);
}
public static String getTenantId() {
return currentTenant.get();
}
public static void clear() {
currentTenant.remove();
}
}

View File

@ -1,35 +0,0 @@
package com.iqser.red.service.redaction.report.v1.server.multitenancy;
import org.springframework.stereotype.Component;
import org.springframework.ui.ModelMap;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.WebRequestInterceptor;
@Component
public class TenantInterceptor implements WebRequestInterceptor {
public static final String TENANT_HEADER_NAME = "X-TENANT-ID";
@Override
public void preHandle(WebRequest request) {
if (request.getHeader(TENANT_HEADER_NAME) != null) {
TenantContext.setTenantId(request.getHeader(TENANT_HEADER_NAME));
}
}
@Override
public void postHandle(WebRequest request, ModelMap model) {
TenantContext.clear();
}
@Override
public void afterCompletion(WebRequest request, Exception ex) {
}
}

View File

@ -78,10 +78,7 @@ import lombok.extern.slf4j.Slf4j;
@RequiredArgsConstructor
public class ExcelReportGenerationService {
private final RSSPoc2Service rSSPoc2Service;
private static final Set<String> prefixRedactionPlaceholders = Set.of(DOSSIER_ATTRIBUTE_PLACEHOLDER_BASE, FILE_ATTRIBUTE_PLACEHOLDER_BASE);
private static final Set<String> redactionPlaceholders = Set.of(FILE_NAME_PLACEHOLDER,
PAGE_PLACEHOLDER,
PARAGRAPH_PLACEHOLDER,
@ -97,6 +94,7 @@ public class ExcelReportGenerationService {
REDACTION_ENTITY_DISPLAY_NAME_PLACEHOLDER,
SCM_FUNCTION_PLACEHOLDER,
SKIPPED_PLACEHOLDER);
private final RSSPoc2Service rSSPoc2Service;
@Timed("redactmanager_generateExcelReport")
@ -218,6 +216,60 @@ public class ExcelReportGenerationService {
}
private void addRedactionEntryRows(Sheet sheet, List<ReportRedactionEntry> reportEntries, String filename, ExcelModel excelModel, PlaceholderModel placeholderModel) {
long start = System.currentTimeMillis();
AtomicInteger rowIndex = new AtomicInteger(excelModel.getRedactionPlaceholderRow());
Map<Integer, Function<PlaceholderInput, String>> placeholderCellPos = excelModel.getPlaceholderCellPos();
reportEntries.forEach(entry -> {
sheet.createRow(rowIndex.get());
excelModel.getWrittenRows().add(rowIndex.get());
for (Map.Entry<Integer, Function<PlaceholderInput, String>> entry1 : placeholderCellPos.entrySet()) {
Cell cell = sheet.getRow(rowIndex.get()).createCell(entry1.getKey());
cell.setCellValue(entry1.getValue().apply(new PlaceholderInput(filename, entry, placeholderModel, null)));
}
rowIndex.getAndIncrement();
});
excelModel.setRedactionPlaceholderRow(rowIndex.getAndIncrement());
log.debug("Adding rows took: {}", System.currentTimeMillis() - start);
}
private void addSCMEntryRows(Sheet sheet, FileModel fileModel, ExcelModel excelModel) {
var scm = rSSPoc2Service.getRSS(fileModel.getDossierId(), fileModel.getId());
var scmResultMap = scm.getFiles().get(0).getResult();
AtomicInteger rowIndex = new AtomicInteger(excelModel.getRedactionPlaceholderRow());
var oecd = rSSPoc2Service.getOecdNumber(fileModel);
for (Map.Entry<String, SCMComponent> entry : scmResultMap.entrySet()) {
sheet.createRow(rowIndex.get());
excelModel.getWrittenRows().add(rowIndex.get());
Cell keyCell = sheet.getRow(rowIndex.get()).createCell(0);
keyCell.setCellValue(oecd + "-" + entry.getKey().replaceAll("_", " "));
Cell valueCell = sheet.getRow(rowIndex.get()).createCell(1);
valueCell.setCellValue(entry.getValue().getValue() != null ? entry.getValue().getValue() : entry.getValue().getOriginalValue());
rowIndex.getAndIncrement();
}
sheet.createRow(rowIndex.get());
excelModel.getWrittenRows().add(rowIndex.get());
excelModel.setRedactionPlaceholderRow(rowIndex.getAndIncrement());
}
private void replacePlaceholders(Cell cell, PlaceholderModel placeholderModel, String dossierName, String filename) {
for (String placeholder : placeholderModel.getPlaceholders()) {
@ -229,6 +281,112 @@ public class ExcelReportGenerationService {
}
private void replacePlaceholdersForImagePlaceholder(SXSSFWorkbook workbook, Sheet sheet, Cell cell, PlaceholderModel placeholderModel) throws IOException {
for (ImagePlaceholder imagePlaceholder : placeholderModel.getImagePlaceholders()) {
if (cell.getStringCellValue().contains(imagePlaceholder.getPlaceholder())) {
try (ByteArrayInputStream is = new ByteArrayInputStream(imagePlaceholder.getImage())) {
double factor = calculateScale(is,
PixelUtil.widthUnits2Pixel((short) sheet.getColumnWidth(cell.getColumnIndex())),
PixelUtil.heightUnits2Pixel(cell.getRow().getHeight()));
is.reset();
int pictureIdx = workbook.addPicture(is.readAllBytes(), SXSSFWorkbook.PICTURE_TYPE_JPEG);
is.reset();
//Returns an object that handles instantiating concrete classes
CreationHelper helper = workbook.getCreationHelper();
//Create an anchor that is attached to the worksheet
ClientAnchor anchor = helper.createClientAnchor();
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
anchor.setCol1(cell.getColumnIndex());
anchor.setRow1(cell.getRowIndex());
//Creates the top-level drawing patriarch.
Drawing<?> drawing = sheet.createDrawingPatriarch();
Picture picture = drawing.createPicture(anchor, pictureIdx);
picture.resize(factor);
cell.setCellValue("");
}
}
}
}
private String getPlaceholderValue(String placeholder, String dossierName, String filename, PlaceholderModel placeholderModel) {
if (placeholder.equals(FORMAT_DATE_ISO_PLACEHOLDER)) {
return OffsetDateTime.now().format(FORMAT_DATE_ISO);
}
if (placeholder.equals(FORMAT_DATE_GER_PLACEHOLDER)) {
return OffsetDateTime.now().format(FORMAT_DATE_GER);
}
if (placeholder.equals(FORMAT_DATE_ENG_PLACEHOLDER)) {
return OffsetDateTime.now().format(FORMAT_DATE_ENG);
}
if (placeholder.equals(FORMAT_TIME_ISO_PLACEHOLDER)) {
return OffsetDateTime.now().format(FORMAT_TIME_ISO);
}
if (placeholder.equals(DOSSIER_NAME_PLACEHOLDER)) {
return dossierName;
}
if (placeholder.equals(FILE_NAME_PLACEHOLDER)) {
return filename;
}
if (placeholderModel.getFileAttributeValueByPlaceholder().containsKey(placeholder)) {
return placeholderModel.getFileAttributeValueByPlaceholder().get(placeholder);
}
if (placeholderModel.getDossierAttributesValueByPlaceholder().containsKey(placeholder)) {
return placeholderModel.getDossierAttributesValueByPlaceholder().get(placeholder);
}
if (placeholderModel.getRssComponentPlaceholder() != null && placeholderModel.getRssComponentPlaceholder().containsKey(placeholder)) {
return placeholderModel.getRssComponentPlaceholder().get(placeholder);
}
return null;
}
private void replacePlaceholdersForCell(Cell cell, String search, String replace) {
if (cell.getStringCellValue().contains(search)) {
String safeToUseInReplaceAllString = Pattern.quote(search);
String escapedReplace = Matcher.quoteReplacement(replace);
String str = cell.getStringCellValue().replaceAll(safeToUseInReplaceAllString, escapedReplace);
cell.setCellValue(str);
}
}
private double calculateScale(ByteArrayInputStream imageByteArrayInputStream, float cellWidth, float cellHeight) throws IOException {
BufferedImage img = ImageIO.read(imageByteArrayInputStream);
double imageWidth = img.getWidth();
double imageHeight = img.getHeight();
double widthFactor = cellWidth / imageWidth;
double heightFactor = cellHeight / imageHeight;
if (imageWidth < cellWidth && imageHeight < cellHeight) {
return 1;
} else if (cellWidth > cellHeight) {
return heightFactor;
} else {
return widthFactor;
}
}
@Timed("redactmanager_calculateExcelModel")
public ExcelModel calculateExcelModel(Sheet sheet) {
@ -306,60 +464,6 @@ public class ExcelReportGenerationService {
}
private void addSCMEntryRows(Sheet sheet, FileModel fileModel, ExcelModel excelModel) {
var scm = rSSPoc2Service.getRSS(fileModel.getDossierId(), fileModel.getId());
var scmResultMap = scm.getFiles().get(0).getResult();
AtomicInteger rowIndex = new AtomicInteger(excelModel.getRedactionPlaceholderRow());
var oecd = rSSPoc2Service.getOecdNumber(fileModel);
for (Map.Entry<String, SCMComponent> entry : scmResultMap.entrySet()) {
sheet.createRow(rowIndex.get());
excelModel.getWrittenRows().add(rowIndex.get());
Cell keyCell = sheet.getRow(rowIndex.get()).createCell(0);
keyCell.setCellValue(oecd + "-" + entry.getKey().replaceAll("_", " "));
Cell valueCell = sheet.getRow(rowIndex.get()).createCell(1);
valueCell.setCellValue(entry.getValue().getValue() != null ? entry.getValue().getValue() : entry.getValue().getOriginalValue());
rowIndex.getAndIncrement();
}
sheet.createRow(rowIndex.get());
excelModel.getWrittenRows().add(rowIndex.get());
excelModel.setRedactionPlaceholderRow(rowIndex.getAndIncrement());
}
private void addRedactionEntryRows(Sheet sheet, List<ReportRedactionEntry> reportEntries, String filename, ExcelModel excelModel, PlaceholderModel placeholderModel) {
long start = System.currentTimeMillis();
AtomicInteger rowIndex = new AtomicInteger(excelModel.getRedactionPlaceholderRow());
Map<Integer, Function<PlaceholderInput, String>> placeholderCellPos = excelModel.getPlaceholderCellPos();
reportEntries.forEach(entry -> {
sheet.createRow(rowIndex.get());
excelModel.getWrittenRows().add(rowIndex.get());
for (Map.Entry<Integer, Function<PlaceholderInput, String>> entry1 : placeholderCellPos.entrySet()) {
Cell cell = sheet.getRow(rowIndex.get()).createCell(entry1.getKey());
cell.setCellValue(entry1.getValue().apply(new PlaceholderInput(filename, entry, placeholderModel, null)));
}
rowIndex.getAndIncrement();
});
excelModel.setRedactionPlaceholderRow(rowIndex.getAndIncrement());
log.debug("Adding rows took: {}", System.currentTimeMillis() - start);
}
private boolean isRedactionPlaceholder(String text) {
return prefixRedactionPlaceholders.stream().anyMatch(text::startsWith) || redactionPlaceholders.stream().anyMatch(text::contains);
@ -383,10 +487,9 @@ public class ExcelReportGenerationService {
case JUSTIFICATION_PARAGRAPH_PLACEHOLDER, JUSTIFICATION_LEGAL_BASIS_PLACEHOLDER -> input -> input.getEntry().getJustificationParagraph();
case JUSTIFICATION_REASON_PLACEHOLDER, JUSTIFICATION_TEXT_PLACEHOLDER -> input -> input.getEntry().getJustificationReason();
case EXCERPT_PLACEHOLDER -> input -> input.getEntry().getExcerpt();
case REDACTION_VALUE_PLACEHOLDER -> input -> input.getEntry().getValue() != null ? input.getEntry()
.getValue()
.replaceAll("\n", " ")
.replaceAll(" {2,}", " ") : input.getEntry().getEntityDisplayName();
case REDACTION_VALUE_PLACEHOLDER ->
input -> input.getEntry().getValue() != null ? input.getEntry().getValue().replaceAll("\n", " ").replaceAll(" {2,}", " ") : input.getEntry()
.getEntityDisplayName();
case REDACTION_ENTITY_DISPLAY_NAME_PLACEHOLDER -> input -> input.getEntry().getEntityDisplayName();
case SKIPPED_PLACEHOLDER -> input -> input.getEntry().isSkipped() ? "true" : "false";
default -> input -> "";
@ -395,112 +498,6 @@ public class ExcelReportGenerationService {
}
private void replacePlaceholdersForCell(Cell cell, String search, String replace) {
if (cell.getStringCellValue().contains(search)) {
String safeToUseInReplaceAllString = Pattern.quote(search);
String escapedReplace = Matcher.quoteReplacement(replace);
String str = cell.getStringCellValue().replaceAll(safeToUseInReplaceAllString, escapedReplace);
cell.setCellValue(str);
}
}
private void replacePlaceholdersForImagePlaceholder(SXSSFWorkbook workbook, Sheet sheet, Cell cell, PlaceholderModel placeholderModel) throws IOException {
for (ImagePlaceholder imagePlaceholder : placeholderModel.getImagePlaceholders()) {
if (cell.getStringCellValue().contains(imagePlaceholder.getPlaceholder())) {
try (ByteArrayInputStream is = new ByteArrayInputStream(imagePlaceholder.getImage())) {
double factor = calculateScale(is,
PixelUtil.widthUnits2Pixel((short) sheet.getColumnWidth(cell.getColumnIndex())),
PixelUtil.heightUnits2Pixel(cell.getRow().getHeight()));
is.reset();
int pictureIdx = workbook.addPicture(is.readAllBytes(), SXSSFWorkbook.PICTURE_TYPE_JPEG);
is.reset();
//Returns an object that handles instantiating concrete classes
CreationHelper helper = workbook.getCreationHelper();
//Create an anchor that is attached to the worksheet
ClientAnchor anchor = helper.createClientAnchor();
anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
anchor.setCol1(cell.getColumnIndex());
anchor.setRow1(cell.getRowIndex());
//Creates the top-level drawing patriarch.
Drawing<?> drawing = sheet.createDrawingPatriarch();
Picture picture = drawing.createPicture(anchor, pictureIdx);
picture.resize(factor);
cell.setCellValue("");
}
}
}
}
private double calculateScale(ByteArrayInputStream imageByteArrayInputStream, float cellWidth, float cellHeight) throws IOException {
BufferedImage img = ImageIO.read(imageByteArrayInputStream);
double imageWidth = img.getWidth();
double imageHeight = img.getHeight();
double widthFactor = cellWidth / imageWidth;
double heightFactor = cellHeight / imageHeight;
if (imageWidth < cellWidth && imageHeight < cellHeight) {
return 1;
} else if (cellWidth > cellHeight) {
return heightFactor;
} else {
return widthFactor;
}
}
private String getPlaceholderValue(String placeholder, String dossierName, String filename, PlaceholderModel placeholderModel) {
if (placeholder.equals(FORMAT_DATE_ISO_PLACEHOLDER)) {
return OffsetDateTime.now().format(FORMAT_DATE_ISO);
}
if (placeholder.equals(FORMAT_DATE_GER_PLACEHOLDER)) {
return OffsetDateTime.now().format(FORMAT_DATE_GER);
}
if (placeholder.equals(FORMAT_DATE_ENG_PLACEHOLDER)) {
return OffsetDateTime.now().format(FORMAT_DATE_ENG);
}
if (placeholder.equals(FORMAT_TIME_ISO_PLACEHOLDER)) {
return OffsetDateTime.now().format(FORMAT_TIME_ISO);
}
if (placeholder.equals(DOSSIER_NAME_PLACEHOLDER)) {
return dossierName;
}
if (placeholder.equals(FILE_NAME_PLACEHOLDER)) {
return filename;
}
if (placeholderModel.getFileAttributeValueByPlaceholder().containsKey(placeholder)) {
return placeholderModel.getFileAttributeValueByPlaceholder().get(placeholder);
}
if (placeholderModel.getDossierAttributesValueByPlaceholder().containsKey(placeholder)) {
return placeholderModel.getDossierAttributesValueByPlaceholder().get(placeholder);
}
if (placeholderModel.getRssComponentPlaceholder() != null && placeholderModel.getRssComponentPlaceholder().containsKey(placeholder)) {
return placeholderModel.getRssComponentPlaceholder().get(placeholder);
}
return null;
}
@SneakyThrows
public byte[] toByteArray(SXSSFWorkbook workbook) {

View File

@ -90,6 +90,30 @@ public class GeneratePlaceholderService {
}
private Map<String, String> getFileAttributePlaceholders(String dossierTemplateId) {
Map<String, String> fileAttributePlaceholders = new HashMap<>();
var fileAttributesConfig = fileAttributesClient.getFileAttributeConfigs(dossierTemplateId);
fileAttributesConfig.forEach(fileAttributeConfig -> fileAttributePlaceholders.put(fileAttributeConfig.getPlaceholder(), fileAttributeConfig.getId()));
return fileAttributePlaceholders;
}
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));
}
public void resolveFileAttributeValues(FileModel fileModel, PlaceholderModel placeholderModel) {
Map<String, String> fileAttributeValueByPlaceholder = new HashMap<>();
@ -115,28 +139,4 @@ public class GeneratePlaceholderService {
placeholderModel.getPlaceholders().addAll(rssPlaceholders.keySet());
}
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));
}
private Map<String, String> getFileAttributePlaceholders(String dossierTemplateId) {
Map<String, String> fileAttributePlaceholders = new HashMap<>();
var fileAttributesConfig = fileAttributesClient.getFileAttributeConfigs(dossierTemplateId);
fileAttributesConfig.forEach(fileAttributeConfig -> fileAttributePlaceholders.put(fileAttributeConfig.getPlaceholder(), fileAttributeConfig.getId()));
return fileAttributePlaceholders;
}
}

View File

@ -71,7 +71,6 @@ public class PlaceholderService {
public static final String SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER = "{{function.seeds.redactionGroupedByJustification.pages}}";
public static final String SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER = "{{function.seeds.justification}}";
public static final Set<String> GENERAL_PLACEHOLDERS = Set.of(FILE_NAME_PLACEHOLDER,
PAGE_PLACEHOLDER,
PARAGRAPH_PLACEHOLDER,
@ -105,22 +104,15 @@ public class PlaceholderService {
}
public List<ReportTemplate> getReportTemplatesByPlaceholder(String dossierTemplateId, String placeholder) {
private Set<String> getAllPlaceholders(String dossierTemplateId) {
List<ReportTemplate> reportTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplateId);
if (reportTemplates == null || reportTemplates.isEmpty()) {
throw new NotFoundException("For dossierTemplateId '" + dossierTemplateId + "' no report templates exist.");
}
List<ReportTemplate> result = new ArrayList<>();
Set<String> allPlaceholders = new HashSet<>(GENERAL_PLACEHOLDERS);
for (ReportTemplate reportTemplate : reportTemplates) {
Set<String> placeholders = findGivenPlaceholdersOfTemplate(reportTemplate, new HashSet<>(Collections.singleton(placeholder)));
if (!placeholders.isEmpty()) {
result.add(reportTemplate);
}
}
dossierAttributesConfigClient.getDossierAttributes(dossierTemplateId).forEach(dossierAttributeConfig -> allPlaceholders.add(dossierAttributeConfig.getPlaceholder()));
return result;
fileAttributesClient.getFileAttributeConfigs(dossierTemplateId).forEach(fileAttributeConfig -> allPlaceholders.add(fileAttributeConfig.getPlaceholder()));
return allPlaceholders;
}
@ -216,18 +208,6 @@ public class PlaceholderService {
}
private Set<String> getAllPlaceholders(String dossierTemplateId) {
Set<String> allPlaceholders = new HashSet<>(GENERAL_PLACEHOLDERS);
dossierAttributesConfigClient.getDossierAttributes(dossierTemplateId).forEach(dossierAttributeConfig -> allPlaceholders.add(dossierAttributeConfig.getPlaceholder()));
fileAttributesClient.getFileAttributeConfigs(dossierTemplateId).forEach(fileAttributeConfig -> allPlaceholders.add(fileAttributeConfig.getPlaceholder()));
return allPlaceholders;
}
private void contains(Set<String> allPlaceholders, Set<String> resultPlaceholders, String placeholder) {
for (String searchPlaceholder : allPlaceholders) {
@ -238,4 +218,23 @@ public class PlaceholderService {
allPlaceholders.removeAll(resultPlaceholders);
}
public List<ReportTemplate> getReportTemplatesByPlaceholder(String dossierTemplateId, String placeholder) {
List<ReportTemplate> reportTemplates = reportTemplateClient.getAvailableReportTemplates(dossierTemplateId);
if (reportTemplates == null || reportTemplates.isEmpty()) {
throw new NotFoundException("For dossierTemplateId '" + dossierTemplateId + "' no report templates exist.");
}
List<ReportTemplate> result = new ArrayList<>();
for (ReportTemplate reportTemplate : reportTemplates) {
Set<String> placeholders = findGivenPlaceholdersOfTemplate(reportTemplate, new HashSet<>(Collections.singleton(placeholder)));
if (!placeholders.isEmpty()) {
result.add(reportTemplate);
}
}
return result;
}
}

View File

@ -90,8 +90,8 @@ public class RSSPoc2Service {
private final Map<Pair, String> guidelineMapping = new HashMap<>();
private final FileAttributesConfigClient fileAttributesClient;
private List<SimpleDateFormat> formats = new ArrayList<>();
private DateFormat resultDateFormat = new SimpleDateFormat("dd/MM/yyyy");
private final List<SimpleDateFormat> formats = new ArrayList<>();
private final DateFormat resultDateFormat = new SimpleDateFormat("dd/MM/yyyy");
@PostConstruct
@ -336,22 +336,386 @@ public class RSSPoc2Service {
}
@SneakyThrows
private void setOverrideValues(String dossierId, String fileId, Map<String, SCMComponent> result) {
public String getOecdNumber(FileModel file) {
if (!reportStorageService.objectExists(dossierId, fileId, FileType.COMPONENTS)) {
return;
var fileAttributesConfig = fileAttributesClient.getFileAttributeConfigs(file.getDossierTemplateId());
var oecdFileAttributeConf = fileAttributesConfig.stream().filter(f -> f.getLabel().equals("OECD Number")).map(f -> f.getId()).findFirst();
if (oecdFileAttributeConf.isPresent()) {
return file.getFileAttributes().get(oecdFileAttributeConf.get());
}
return null;
}
private void sortRedactionLog(RedactionLog redactionLog) {
redactionLog.getRedactionLogEntry().sort((entry1, entry2) -> {
if (entry1.getPositions().get(0).getPage() == entry2.getPositions().get(0).getPage()) {
if (entry1.getPositions().get(0).getTopLeft().getY() == entry2.getPositions().get(0).getTopLeft().getY()) {
return entry1.getPositions().get(0).getTopLeft().getX() <= entry2.getPositions().get(0).getTopLeft().getX() ? -1 : 1;
} else {
return entry1.getPositions().get(0).getTopLeft().getY() <= entry2.getPositions().get(0).getTopLeft().getY() ? 1 : -1;
}
}
return entry1.getPositions().get(0).getPage() < entry2.getPositions().get(0).getPage() ? -1 : 1;
});
}
private SCMComponent getFirstEntryOrElse(RedactionLog redactionLog, String type, String elseValue) {
String transformation = String.format("First found value of type '%s' or else '%s'", type, elseValue);
var firstEntryOptional = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).findFirst();
if (firstEntryOptional.isPresent()) {
var firstEntry = firstEntryOptional.get();
return SCMComponent.builder().originalValue(firstEntry.getValue()).scmAnnotations(List.of(toScmAnnotations(firstEntry))).transformation(transformation).build();
}
var overrideBytes = reportStorageService.getStoredObjectBytes(dossierId, fileId, FileType.COMPONENTS);
ComponentsOverrides componentsOverrides = objectMapper.readValue(overrideBytes, ComponentsOverrides.class);
return SCMComponent.builder().originalValue(elseValue).transformation(transformation).build();
}
for (Map.Entry<String, SCMComponent> entry : result.entrySet()) {
if (componentsOverrides.getComponentOverrides().containsKey(entry.getKey())) {
String overrideValue = componentsOverrides.getComponentOverrides().get(entry.getKey());
entry.getValue().setValue(overrideValue);
private SCMComponent getPerformingLaboratory(RedactionLog redactionLog) {
String transformation = "Value of laboratory_name, combined with laboratory_country if distance is small";
var laboratoryEntry = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("laboratory_name")).findFirst();
if (!laboratoryEntry.isPresent()) {
return SCMComponent.builder().originalValue("").transformation(transformation).build();
}
var laboratoryCountry = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("laboratory_country") && Math.abs(laboratoryEntry.get().getPositions().get(0).getTopLeft().getY() - r.getPositions()
.get(0)
.getTopLeft()
.getY()) < 80)
.collect(Collectors.toList());
RedactionLogEntry countryWithSmallestDistance = null;
for (var entry : laboratoryCountry) {
if (countryWithSmallestDistance == null) {
countryWithSmallestDistance = entry;
} else if (Math.abs(laboratoryEntry.get().getPositions().get(0).getTopLeft().getY() - entry.getPositions().get(0).getTopLeft().getY()) < Math.abs(laboratoryEntry.get()
.getPositions()
.get(0)
.getTopLeft()
.getY() - countryWithSmallestDistance.getPositions().get(0).getTopLeft().getY())) {
countryWithSmallestDistance = entry;
}
}
List<ScmAnnotation> scmAnnotations = new ArrayList<>();
scmAnnotations.add(toScmAnnotations(laboratoryEntry.get()));
StringBuilder sb = new StringBuilder();
if (laboratoryEntry.isPresent()) {
sb.append(laboratoryEntry.get().getValue());
}
if (countryWithSmallestDistance != null) {
sb.append(", ").append(countryWithSmallestDistance.getValue());
scmAnnotations.add(toScmAnnotations(countryWithSmallestDistance));
}
return SCMComponent.builder().originalValue(sb.toString().trim()).scmAnnotations(scmAnnotations).transformation(transformation).build();
}
private SCMComponent getConvertedDates(RedactionLog redactionLog, String type) {
List<RedactionLogEntry> redactionLogEntries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).collect(Collectors.toList());
String value = redactionLogEntries.stream().map(RedactionLogEntry::getValue).map(this::convertDate).collect(Collectors.joining(", "));
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(redactionLogEntries.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(String.format("Convert values of type '%s' to dd/MM/yyyy joined with ', '", type))
.build();
}
private SCMComponent ifPresentAddOrElse(RedactionLog redactionLog, String type, String presentValue, String elseValue) {
String transformation = String.format("If type %s is present than '%s' else '%s'", type, presentValue, elseValue);
var firstEntryOptional = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).findFirst();
if (firstEntryOptional.isPresent()) {
var firstEntry = firstEntryOptional.get();
return SCMComponent.builder().originalValue(presentValue).scmAnnotations(List.of(toScmAnnotations(firstEntry))).transformation(transformation).build();
}
return SCMComponent.builder().originalValue(elseValue).transformation(transformation).build();
}
private SCMComponent getJoinedUniqueValues(RedactionLog redactionLog, String type, String seperator) {
String transformation = String.format("Combine unique values of '%s' with seperator '%s'", type, seperator);
var uniqueEntries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).collect(Collectors.toSet());
String value = uniqueEntries.stream().map(RedactionLogEntry::getValue).collect(Collectors.toSet()).stream().collect(Collectors.joining(seperator)).trim();
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(uniqueEntries.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
private SCMComponent getTestGuideline1(RedactionLog redactionLog) {
String transformation = "If 'oecd_guideline_number' and 'oecd_guideline_year' are present than mapped by provided mapping table else value of 'oecd_guideline' if present or else ''";
var guidelineNumber = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("oecd_guideline_number")).findFirst();
var guidelineYear = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("oecd_guideline_year")).findFirst();
if (guidelineNumber.isPresent() && guidelineYear.isPresent()) {
var guidelinePair = Pair.of(guidelineNumber.get().getValue(), guidelineYear.get().getValue());
if (guidelineMapping.containsKey(guidelinePair)) {
String value = guidelineMapping.get(guidelinePair);
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(List.of(toScmAnnotations(guidelineNumber.get()), toScmAnnotations(guidelineYear.get())))
.transformation(transformation)
.build();
}
}
var guideline = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("oecd_guideline")).findFirst();
if (guideline.isPresent()) {
return SCMComponent.builder()
.originalValue(guideline.get().getValue())
.scmAnnotations(List.of(toScmAnnotations(guideline.get())))
.transformation(transformation)
.build();
}
return SCMComponent.builder().originalValue("").transformation(transformation).build();
}
private SCMComponent getTestGuideline2(RedactionLog redactionLog) {
String transformation = "Combine values of 'epa_guideline' and 'ec_guideline' with seperator ', '";
List<RedactionLogEntry> guidelines = new ArrayList<>();
guidelines.addAll(redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("epa_guideline")).collect(Collectors.toList()));
guidelines.addAll(redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("ec_guideline")).collect(Collectors.toList()));
String value = guidelines.stream().map(RedactionLogEntry::getValue).collect(Collectors.joining(", "));
if (!value.isEmpty()) {
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(guidelines.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
return SCMComponent.builder().originalValue("").transformation(transformation).build();
}
private boolean oecdIn(String oecd, Set<String> oecdsToApply) {
return oecd != null && oecdsToApply.contains(oecd);
}
private List<SCMComponent> getAsSentences(RedactionLog redactionLog, String type) {
String transformation = String.format("Values of type '%s' as sentences", type);
List<SCMComponent> sentences = new ArrayList<>();
var typeStringsEntries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).collect(Collectors.toList());
if (typeStringsEntries.isEmpty()) {
return sentences;
}
for (RedactionLogEntry typeStringEntry : typeStringsEntries) {
BreakIterator iterator = BreakIterator.getSentenceInstance(Locale.US);
iterator.setText(typeStringEntry.getValue());
int start = iterator.first();
for (int end = iterator.next(); end != BreakIterator.DONE; start = end, end = iterator.next()) {
sentences.add(SCMComponent.builder()
.originalValue(typeStringEntry.getValue().substring(start, end).replaceAll("\\n", "").trim())
.scmAnnotations(List.of(toScmAnnotations(typeStringEntry)))
.transformation(transformation)
.build());
}
}
return sentences;
}
private SCMComponent getLongestBlockOrElse(RedactionLog redactionLog, String type, String elseValue) {
String transformation = String.format("Longest value of type '%s' if present or else '%s'", type, elseValue);
var entries = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals(type))
.sorted(Comparator.comparing(s -> s.getValue().length()))
.collect(Collectors.toList());
if (!entries.isEmpty()) {
var firstEntry = entries.get(entries.size() - 1);
return SCMComponent.builder().originalValue(firstEntry.getValue()).scmAnnotations(List.of(toScmAnnotations(firstEntry))).transformation(transformation).build();
}
return SCMComponent.builder().originalValue(elseValue).transformation(transformation).build();
}
private SCMComponent getAsOneBlock(RedactionLog redactionLog, String type) {
String transformation = String.format("Combine value of '%s' to one block", type);
var entries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).collect(Collectors.toList());
String value = entries.stream().map(RedactionLogEntry::getValue).collect(Collectors.joining(" "));
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(entries.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
private SCMComponent getJoinedValues(RedactionLog redactionLog, String type, String seperator) {
String transformation = String.format("Combine values of '%s' with seperator '%s'", type, seperator);
var entries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).collect(Collectors.toList());
String value = entries.stream().map(RedactionLogEntry::getValue).collect(Collectors.joining(seperator)).trim();
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(entries.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
private SCMComponent getSex(RedactionLog redactionLog) {
String transformation = "Combine unique values of 'sex', map plural values to singular";
var entries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("sex")).collect(Collectors.toSet());
var value = entries.stream().map(RedactionLogEntry::getValue).map(String::toLowerCase).map(s -> {
if (s.equals("females")) {
return "female";
} else if (s.equals("males")) {
return "male";
}
return s;
}).collect(Collectors.toSet()).stream().collect(Collectors.joining(", ")).trim();
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(entries.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
private SCMComponent getNumberOfAnimals(RedactionLog redactionLog) {
String transformation = "Return value of 'number_of_animals' if present else return sum of unique 'animal_number' or else '' ";
var numberOfAnimals = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("number_of_animals")).findFirst();
if (numberOfAnimals.isPresent()) {
return SCMComponent.builder()
.originalValue(numberOfAnimals.get().getValue())
.scmAnnotations(List.of(toScmAnnotations(numberOfAnimals.get())))
.transformation(transformation)
.build();
}
var uniqueAnimalNumbers = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("animal_number")).collect(Collectors.toSet());
if (uniqueAnimalNumbers.isEmpty()) {
return SCMComponent.builder().originalValue("").transformation(transformation).build();
}
int size = uniqueAnimalNumbers.stream().map(a -> a.getValue()).collect(Collectors.toSet()).size();
return SCMComponent.builder()
.originalValue(String.valueOf(size))
.scmAnnotations(uniqueAnimalNumbers.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
private List<SCMComponent> getDoseMortality(RedactionLog redactionLog) {
String transformation = "Combine values of 'dose_mortality' and 'dose_mortality_dose' of same row with ', ' ";
var doseMortalityEntries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("dose_mortality")).collect(Collectors.toList());
var doseMortalityDoseEntries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("dose_mortality_dose")).collect(Collectors.toList());
List<SCMComponent> result = new ArrayList<>();
for (var mortality : doseMortalityEntries) {
RedactionLogEntry doseWithSmallestDistance = null;
for (var dose : doseMortalityDoseEntries) {
if (Math.round(mortality.getPositions().get(0).getTopLeft().getY()) == Math.round(dose.getPositions().get(0).getTopLeft().getY())) {
doseWithSmallestDistance = dose;
break;
}
if (doseWithSmallestDistance == null) {
doseWithSmallestDistance = dose;
} else if (Math.abs(Math.round(mortality.getPositions().get(0).getTopLeft().getY()) - Math.round(dose.getPositions()
.get(0)
.getTopLeft()
.getY())) < Math.abs(Math.round(mortality.getPositions().get(0).getTopLeft().getY()) - Math.round(doseWithSmallestDistance.getPositions()
.get(0)
.getTopLeft()
.getY()))) {
doseWithSmallestDistance = dose;
}
}
if (doseWithSmallestDistance != null) {
result.add(SCMComponent.builder()
.originalValue(doseWithSmallestDistance.getValue() + ", " + mortality.getValue())
.scmAnnotations(List.of(toScmAnnotations(doseWithSmallestDistance), toScmAnnotations(mortality)))
.transformation(transformation)
.build());
} else if (mortality != null) {
result.add(SCMComponent.builder().originalValue(mortality.getValue()).scmAnnotations(List.of(toScmAnnotations(mortality))).transformation(transformation).build());
}
}
return result;
}
@ -470,318 +834,22 @@ public class RSSPoc2Service {
}
private Map<String, SCMComponent> getKeyContains(Map<String, SCMComponent> components, String compontentName) {
@SneakyThrows
private void setOverrideValues(String dossierId, String fileId, Map<String, SCMComponent> result) {
Map<String, SCMComponent> resultMap = new LinkedHashMap<>();
if (!reportStorageService.objectExists(dossierId, fileId, FileType.COMPONENTS)) {
return;
}
for (Map.Entry<String, SCMComponent> entry : components.entrySet()) {
if (entry.getKey().contains(compontentName)) {
resultMap.put(entry.getKey(), entry.getValue());
var overrideBytes = reportStorageService.getStoredObjectBytes(dossierId, fileId, FileType.COMPONENTS);
ComponentsOverrides componentsOverrides = objectMapper.readValue(overrideBytes, ComponentsOverrides.class);
for (Map.Entry<String, SCMComponent> entry : result.entrySet()) {
if (componentsOverrides.getComponentOverrides().containsKey(entry.getKey())) {
String overrideValue = componentsOverrides.getComponentOverrides().get(entry.getKey());
entry.getValue().setValue(overrideValue);
}
}
return resultMap;
}
private SCMComponent getSex(RedactionLog redactionLog) {
String transformation = "Combine unique values of 'sex', map plural values to singular";
var entries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("sex")).collect(Collectors.toSet());
var value = entries.stream().map(RedactionLogEntry::getValue).map(String::toLowerCase).map(s -> {
if (s.equals("females")) {
return "female";
} else if (s.equals("males")) {
return "male";
}
return s;
}).collect(Collectors.toSet()).stream().collect(Collectors.joining(", ")).trim();
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(entries.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
private List<SCMComponent> getDoseMortality(RedactionLog redactionLog) {
String transformation = "Combine values of 'dose_mortality' and 'dose_mortality_dose' of same row with ', ' ";
var doseMortalityEntries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("dose_mortality")).collect(Collectors.toList());
var doseMortalityDoseEntries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("dose_mortality_dose")).collect(Collectors.toList());
List<SCMComponent> result = new ArrayList<>();
for (var mortality : doseMortalityEntries) {
RedactionLogEntry doseWithSmallestDistance = null;
for (var dose : doseMortalityDoseEntries) {
if (Math.round(mortality.getPositions().get(0).getTopLeft().getY()) == Math.round(dose.getPositions().get(0).getTopLeft().getY())) {
doseWithSmallestDistance = dose;
break;
}
if (doseWithSmallestDistance == null) {
doseWithSmallestDistance = dose;
} else if (Math.abs(Math.round(mortality.getPositions().get(0).getTopLeft().getY()) - Math.round(dose.getPositions()
.get(0)
.getTopLeft()
.getY())) < Math.abs(Math.round(mortality.getPositions().get(0).getTopLeft().getY()) - Math.round(doseWithSmallestDistance.getPositions()
.get(0)
.getTopLeft()
.getY()))) {
doseWithSmallestDistance = dose;
}
}
if (doseWithSmallestDistance != null) {
result.add(SCMComponent.builder()
.originalValue(doseWithSmallestDistance.getValue() + ", " + mortality.getValue())
.scmAnnotations(List.of(toScmAnnotations(doseWithSmallestDistance), toScmAnnotations(mortality)))
.transformation(transformation)
.build());
} else if (mortality != null) {
result.add(SCMComponent.builder().originalValue(mortality.getValue()).scmAnnotations(List.of(toScmAnnotations(mortality))).transformation(transformation).build());
}
}
return result;
}
private SCMComponent getJoinedValues(RedactionLog redactionLog, String type, String seperator) {
String transformation = String.format("Combine values of '%s' with seperator '%s'", type, seperator);
var entries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).collect(Collectors.toList());
String value = entries.stream().map(RedactionLogEntry::getValue).collect(Collectors.joining(seperator)).trim();
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(entries.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
private SCMComponent getJoinedUniqueValues(RedactionLog redactionLog, String type, String seperator) {
String transformation = String.format("Combine unique values of '%s' with seperator '%s'", type, seperator);
var uniqueEntries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).collect(Collectors.toSet());
String value = uniqueEntries.stream().map(RedactionLogEntry::getValue).collect(Collectors.toSet()).stream().collect(Collectors.joining(seperator)).trim();
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(uniqueEntries.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
private SCMComponent getLongestBlockOrElse(RedactionLog redactionLog, String type, String elseValue) {
String transformation = String.format("Longest value of type '%s' if present or else '%s'", type, elseValue);
var entries = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals(type))
.sorted(Comparator.comparing(s -> s.getValue().length()))
.collect(Collectors.toList());
if (!entries.isEmpty()) {
var firstEntry = entries.get(entries.size() - 1);
return SCMComponent.builder().originalValue(firstEntry.getValue()).scmAnnotations(List.of(toScmAnnotations(firstEntry))).transformation(transformation).build();
}
return SCMComponent.builder().originalValue(elseValue).transformation(transformation).build();
}
private SCMComponent getAsOneBlock(RedactionLog redactionLog, String type) {
String transformation = String.format("Combine value of '%s' to one block", type);
var entries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).collect(Collectors.toList());
String value = entries.stream().map(RedactionLogEntry::getValue).collect(Collectors.joining(" "));
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(entries.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
private boolean oecdIn(String oecd, Set<String> oecdsToApply) {
if (oecd != null && oecdsToApply.contains(oecd)) {
return true;
}
return false;
}
public String getOecdNumber(FileModel file) {
var fileAttributesConfig = fileAttributesClient.getFileAttributeConfigs(file.getDossierTemplateId());
var oecdFileAttributeConf = fileAttributesConfig.stream().filter(f -> f.getLabel().equals("OECD Number")).map(f -> f.getId()).findFirst();
if (oecdFileAttributeConf.isPresent()) {
return file.getFileAttributes().get(oecdFileAttributeConf.get());
}
return null;
}
private SCMComponent getNumberOfAnimals(RedactionLog redactionLog) {
String transformation = "Return value of 'number_of_animals' if present else return sum of unique 'animal_number' or else '' ";
var numberOfAnimals = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("number_of_animals")).findFirst();
if (numberOfAnimals.isPresent()) {
return SCMComponent.builder()
.originalValue(numberOfAnimals.get().getValue())
.scmAnnotations(List.of(toScmAnnotations(numberOfAnimals.get())))
.transformation(transformation)
.build();
}
var uniqueAnimalNumbers = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("animal_number")).collect(Collectors.toSet());
if (uniqueAnimalNumbers.isEmpty()) {
return SCMComponent.builder().originalValue("").transformation(transformation).build();
}
int size = uniqueAnimalNumbers.stream().map(a -> a.getValue()).collect(Collectors.toSet()).size();
return SCMComponent.builder()
.originalValue(String.valueOf(size))
.scmAnnotations(uniqueAnimalNumbers.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
private List<SCMComponent> getAsSentences(RedactionLog redactionLog, String type) {
String transformation = String.format("Values of type '%s' as sentences", type);
List<SCMComponent> sentences = new ArrayList<>();
var typeStringsEntries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).collect(Collectors.toList());
if (typeStringsEntries.isEmpty()) {
return sentences;
}
for (RedactionLogEntry typeStringEntry : typeStringsEntries) {
BreakIterator iterator = BreakIterator.getSentenceInstance(Locale.US);
iterator.setText(typeStringEntry.getValue());
int start = iterator.first();
for (int end = iterator.next(); end != BreakIterator.DONE; start = end, end = iterator.next()) {
sentences.add(SCMComponent.builder()
.originalValue(typeStringEntry.getValue().substring(start, end).replaceAll("\\n", "").trim())
.scmAnnotations(List.of(toScmAnnotations(typeStringEntry)))
.transformation(transformation)
.build());
}
}
return sentences;
}
private SCMComponent getPerformingLaboratory(RedactionLog redactionLog) {
String transformation = "Value of laboratory_name, combined with laboratory_country if distance is small";
var laboratoryEntry = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("laboratory_name")).findFirst();
if (!laboratoryEntry.isPresent()) {
return SCMComponent.builder().originalValue("").transformation(transformation).build();
}
var laboratoryCountry = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("laboratory_country") && Math.abs(laboratoryEntry.get().getPositions().get(0).getTopLeft().getY() - r.getPositions()
.get(0)
.getTopLeft()
.getY()) < 80)
.collect(Collectors.toList());
RedactionLogEntry countryWithSmallestDistance = null;
for (var entry : laboratoryCountry) {
if (countryWithSmallestDistance == null) {
countryWithSmallestDistance = entry;
} else if (Math.abs(laboratoryEntry.get().getPositions().get(0).getTopLeft().getY() - entry.getPositions().get(0).getTopLeft().getY()) < Math.abs(laboratoryEntry.get()
.getPositions()
.get(0)
.getTopLeft()
.getY() - countryWithSmallestDistance.getPositions().get(0).getTopLeft().getY())) {
countryWithSmallestDistance = entry;
}
}
List<ScmAnnotation> scmAnnotations = new ArrayList<>();
scmAnnotations.add(toScmAnnotations(laboratoryEntry.get()));
StringBuilder sb = new StringBuilder();
if (laboratoryEntry.isPresent()) {
sb.append(laboratoryEntry.get().getValue());
}
if (countryWithSmallestDistance != null) {
sb.append(", ").append(countryWithSmallestDistance.getValue());
scmAnnotations.add(toScmAnnotations(countryWithSmallestDistance));
}
return SCMComponent.builder().originalValue(sb.toString().trim()).scmAnnotations(scmAnnotations).transformation(transformation).build();
}
private SCMComponent ifPresentAddOrElse(RedactionLog redactionLog, String type, String presentValue, String elseValue) {
String transformation = String.format("If type %s is present than '%s' else '%s'", type, presentValue, elseValue);
var firstEntryOptional = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).findFirst();
if (firstEntryOptional.isPresent()) {
var firstEntry = firstEntryOptional.get();
return SCMComponent.builder().originalValue(presentValue).scmAnnotations(List.of(toScmAnnotations(firstEntry))).transformation(transformation).build();
}
return SCMComponent.builder().originalValue(elseValue).transformation(transformation).build();
}
private SCMComponent getFirstEntryOrElse(RedactionLog redactionLog, String type, String elseValue) {
String transformation = String.format("First found value of type '%s' or else '%s'", type, elseValue);
var firstEntryOptional = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).findFirst();
if (firstEntryOptional.isPresent()) {
var firstEntry = firstEntryOptional.get();
return SCMComponent.builder().originalValue(firstEntry.getValue()).scmAnnotations(List.of(toScmAnnotations(firstEntry))).transformation(transformation).build();
}
return SCMComponent.builder().originalValue(elseValue).transformation(transformation).build();
}
@ -792,20 +860,6 @@ public class RSSPoc2Service {
}
private SCMComponent getConvertedDates(RedactionLog redactionLog, String type) {
List<RedactionLogEntry> redactionLogEntries = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals(type)).collect(Collectors.toList());
String value = redactionLogEntries.stream().map(RedactionLogEntry::getValue).map(this::convertDate).collect(Collectors.joining(", "));
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(redactionLogEntries.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(String.format("Convert values of type '%s' to dd/MM/yyyy joined with ', '", type))
.build();
}
@SuppressWarnings("PMD.EmptyCatchBlock")
private String convertDate(String dateAsString) {
@ -828,74 +882,17 @@ public class RSSPoc2Service {
}
private SCMComponent getTestGuideline1(RedactionLog redactionLog) {
private Map<String, SCMComponent> getKeyContains(Map<String, SCMComponent> components, String compontentName) {
String transformation = "If 'oecd_guideline_number' and 'oecd_guideline_year' are present than mapped by provided mapping table else value of 'oecd_guideline' if present or else ''";
Map<String, SCMComponent> resultMap = new LinkedHashMap<>();
var guidelineNumber = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("oecd_guideline_number")).findFirst();
var guidelineYear = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("oecd_guideline_year")).findFirst();
if (guidelineNumber.isPresent() && guidelineYear.isPresent()) {
var guidelinePair = Pair.of(guidelineNumber.get().getValue(), guidelineYear.get().getValue());
if (guidelineMapping.containsKey(guidelinePair)) {
String value = guidelineMapping.get(guidelinePair);
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(List.of(toScmAnnotations(guidelineNumber.get()), toScmAnnotations(guidelineYear.get())))
.transformation(transformation)
.build();
for (Map.Entry<String, SCMComponent> entry : components.entrySet()) {
if (entry.getKey().contains(compontentName)) {
resultMap.put(entry.getKey(), entry.getValue());
}
}
var guideline = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("oecd_guideline")).findFirst();
if (guideline.isPresent()) {
return SCMComponent.builder()
.originalValue(guideline.get().getValue())
.scmAnnotations(List.of(toScmAnnotations(guideline.get())))
.transformation(transformation)
.build();
}
return SCMComponent.builder().originalValue("").transformation(transformation).build();
}
private SCMComponent getTestGuideline2(RedactionLog redactionLog) {
String transformation = "Combine values of 'epa_guideline' and 'ec_guideline' with seperator ', '";
List<RedactionLogEntry> guidelines = new ArrayList<>();
guidelines.addAll(redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("epa_guideline")).collect(Collectors.toList()));
guidelines.addAll(redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("ec_guideline")).collect(Collectors.toList()));
String value = guidelines.stream().map(RedactionLogEntry::getValue).collect(Collectors.joining(", "));
if (!value.isEmpty()) {
return SCMComponent.builder()
.originalValue(value)
.scmAnnotations(guidelines.stream().map(this::toScmAnnotations).collect(Collectors.toList()))
.transformation(transformation)
.build();
}
return SCMComponent.builder().originalValue("").transformation(transformation).build();
}
private void sortRedactionLog(RedactionLog redactionLog) {
redactionLog.getRedactionLogEntry().sort((entry1, entry2) -> {
if (entry1.getPositions().get(0).getPage() == entry2.getPositions().get(0).getPage()) {
if (entry1.getPositions().get(0).getTopLeft().getY() == entry2.getPositions().get(0).getTopLeft().getY()) {
return entry1.getPositions().get(0).getTopLeft().getX() <= entry2.getPositions().get(0).getTopLeft().getX() ? -1 : 1;
} else {
return entry1.getPositions().get(0).getTopLeft().getY() <= entry2.getPositions().get(0).getTopLeft().getY() ? 1 : -1;
}
}
return entry1.getPositions().get(0).getPage() < entry2.getPositions().get(0).getPage() ? -1 : 1;
});
return resultMap;
}
}

View File

@ -164,65 +164,58 @@ public class RSSService {
}
private String getRule5Endpoint(RedactionLog redactionLog) {
private String getRule46Attachments(RedactionLog redactionLog) {
var studyType = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("study_type")).map(RedactionLogEntry::getValue).findFirst();
var attachments = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("attachments")).map(RedactionLogEntry::getValue).findFirst();
if (studyType.isPresent()) {
return studyType.get();
if (attachments.isPresent()) {
return "Yes";
}
var guideline = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("guideline")).map(RedactionLogEntry::getValue).findFirst();
if (guideline.isPresent()) {
return mapGuideline(guideline.get());
}
return "";
return "None";
}
private String getRule7StudyPeriod(RedactionLog redactionLog) {
var startDate = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("experimental_start_date")).map(RedactionLogEntry::getValue).findFirst();
var endDate = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("experimental_end_date")).map(RedactionLogEntry::getValue).findFirst();
private String getRule42BodyWeight(RedactionLog redactionLog) {
var bodyWeights = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("body_weight")).map(RedactionLogEntry::getValue).collect(Collectors.toList());
StringBuilder sb = new StringBuilder();
startDate.ifPresent(sb::append);
endDate.ifPresent(s -> sb.append(" to ").append(s));
return sb.toString();
}
private String get9RationaleForReliabilityIncludingDeficiencies(RedactionLog redactionLog) {
var guideline = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("guideline")).map(RedactionLogEntry::getValue).findFirst();
if (guideline.isPresent()) {
return "Guideline study";
for (var bodyWeight : bodyWeights) {
sb.append(bodyWeight).append(" / ");
}
return "";
return sb.toString();
}
private String getRule14Reference(RedactionLog redactionLog) {
private String getRule41ClinicalSigns(RedactionLog redactionLog) {
var title = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("title")).map(RedactionLogEntry::getValue).collect(Collectors.joining(" "));
var author = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("author")).map(RedactionLogEntry::getValue).findFirst();
var completionDate = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("completion_date")).map(RedactionLogEntry::getValue).findFirst();
StringBuilder sb = new StringBuilder("Study report/");
sb.append(title).append('/');
author.ifPresent(s -> sb.append('/').append(s));
completionDate.ifPresent(s -> sb.append('/').append(s));
var clinicalSigns = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("clinical_signs"))
.map(RedactionLogEntry::getValue)
.collect(Collectors.toList());
StringBuilder sb = new StringBuilder();
for (var clinicalSign : clinicalSigns) {
sb.append(clinicalSign).append(" / ");
}
return sb.toString();
}
private String getRule49Conclusions(RedactionLog redactionLog) {
var conclusions = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("conclusion")).map(RedactionLogEntry::getValue).collect(Collectors.toList());
if (conclusions.isEmpty()) {
return "";
}
return conclusions.get(conclusions.size() - 1);
}
private String getRule15DataAccess(RedactionLog redactionLog) {
var sponsor = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("sponsor")).map(RedactionLogEntry::getValue).findFirst();
@ -239,153 +232,6 @@ public class RSSService {
}
private String getRule17Guideline(RedactionLog redactionLog) {
var guidelines = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("guideline")).map(RedactionLogEntry::getValue).collect(Collectors.toSet());
StringBuilder stringBuilder = new StringBuilder();
int i = 1;
for (String guideline : guidelines) {
stringBuilder.append(i).append(") according to guideline ").append(guideline).append(" (").append(mapGuideline(guideline)).append(") ");
i++;
}
return stringBuilder.toString();
}
private String getRule19GlpCompliance(RedactionLog redactionLog) {
var glpCompliance = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("glp_compliance")).map(RedactionLogEntry::getValue).findFirst();
return glpCompliance.map(s -> "Yes. " + s).orElse("No.");
}
private String getRule20TestType(RedactionLog redactionLog) {
var upAndDownProcedure = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("up_and_down_procedure")).map(RedactionLogEntry::getValue).findFirst();
if (upAndDownProcedure.isPresent()) {
return "Up down Procedure";
}
var guideline8701100 = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("guideline"))
.map(RedactionLogEntry::getValue)
.filter(g -> g.contains("870.1100"))
.findFirst();
if (guideline8701100.isPresent()) {
return "Up down Procedure";
}
return "No";
}
private String getRule21LimitTest(RedactionLog redactionLog) {
var limitTest = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("limit_test")).map(RedactionLogEntry::getValue).findFirst();
var noLimitTest = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("no_limit_test")).map(RedactionLogEntry::getValue).findFirst();
if (limitTest.isPresent() && noLimitTest.isEmpty()) {
return "Yes";
}
return "No";
}
private String getRule22TestMaterialInformation(RedactionLog redactionLog) {
var testSubstance = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("test_substance")).map(RedactionLogEntry::getValue).findFirst();
return testSubstance.map(s -> s + "/CAS number").orElse("");
}
private String getRule24SpecificDetailsOnTestMaterial(RedactionLog redactionLog) {
var materials = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("materials")).map(RedactionLogEntry::getValue).collect(Collectors.toList());
StringBuilder sb = new StringBuilder();
for (var material : materials) {
sb.append(material).append(' ');
}
return sb.toString();
}
private String getRule25Species(RedactionLog redactionLog) {
var species = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("species")).map(RedactionLogEntry::getValue).findFirst();
return species.orElse("");
}
private String getRule26Strain(RedactionLog redactionLog) {
var strain = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("strain")).map(RedactionLogEntry::getValue).findFirst();
return strain.orElse("");
}
private String getRule27Sex(RedactionLog redactionLog) {
var sex = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("sex")).map(RedactionLogEntry::getValue).findFirst();
return sex.orElse("");
}
private String getRule28DetailsOnTestAnimalsTestSystemEnvironmentalConditions(RedactionLog redactionLog) {
return redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("test_animals"))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getTopLeft().getX()))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getTopLeft().getY(), Comparator.reverseOrder()))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getPage()))
.map(RedactionLogEntry::getValue)
.collect(Collectors.joining(" "));
}
private String getRule29RouteOfAdministration(RedactionLog redactionLog) {
var routeOfAdministration = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("route_of_administration"))
.map(RedactionLogEntry::getValue)
.findFirst();
return routeOfAdministration.orElse("");
}
private String getRule30Vehicle(RedactionLog redactionLog) {
var vehicles = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("vehicle")).map(RedactionLogEntry::getValue).collect(Collectors.toList());
if (vehicles.isEmpty()) {
return "Not Applicable";
}
return String.join(" / ", vehicles);
}
private String getRule31DetailsOfOralExposure(RedactionLog redactionLog) {
var oralExposures = redactionLog.getRedactionLogEntry()
@ -402,64 +248,6 @@ public class RSSService {
}
private String getRule32Doses(RedactionLog redactionLog) {
var dosagesPerAnimal = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("dosage_per_animal"))
.map(r -> r.getValue().replaceAll("\\n", "").trim())
.collect(Collectors.toSet());
var dosages = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("dosage"))
.map(r -> r.getValue().replaceAll("\\n", "").trim())
.collect(Collectors.toSet());
Set<String> allDosages = new HashSet<>();
allDosages.addAll(dosagesPerAnimal);
allDosages.addAll(dosages);
StringBuilder sb = new StringBuilder();
for (var dosagePerAnimal : allDosages) {
sb.append(dosagePerAnimal).append(" mg/kg bw").append(" , ");
}
return sb.toString().trim();
}
private String getRule33NoOfAnimalsPerSexPerDose(RedactionLog redactionLog) {
var dosagesPerAnimal = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("dosage_per_animal"))
.map(RedactionLogEntry::getValue)
.collect(Collectors.toList());
var uniqueDosagesPerAnimal = new HashSet<>(dosagesPerAnimal);
var uniqueAnimalNumbers = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("animal_number"))
.map(RedactionLogEntry::getValue)
.collect(Collectors.toSet());
if (uniqueDosagesPerAnimal.size() == 1 && uniqueAnimalNumbers.size() > 1) {
return uniqueAnimalNumbers.size() + " * " + uniqueDosagesPerAnimal.iterator().next() + " mg/kg bw";
}
Map<String, List<String>> dosagesPerAnimalMap = new HashMap<>();
for (var dosage : dosagesPerAnimal) {
dosagesPerAnimalMap.computeIfAbsent(dosage, (x) -> new ArrayList<>()).add(dosage);
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, List<String>> entry : dosagesPerAnimalMap.entrySet()) {
sb.append(entry.getValue().size()).append(" * ").append(entry.getKey()).append(" mg/kg bw, ");
}
return sb.toString().trim();
}
private String getRule35DetailsOnStudyDesign(RedactionLog redactionLog) {
var necropsy = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("necropsy")).map(RedactionLogEntry::getValue).findFirst();
@ -502,43 +290,82 @@ public class RSSService {
}
private String getRule40Mortality(RedactionLog redactionLog) {
private String getRule28DetailsOnTestAnimalsTestSystemEnvironmentalConditions(RedactionLog redactionLog) {
var mortalitys = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("mortality")).map(RedactionLogEntry::getValue).collect(Collectors.toList());
StringBuilder sb = new StringBuilder();
for (var mortality : mortalitys) {
sb.append(mortality).append(' ');
}
return sb.toString();
}
private String getRule41ClinicalSigns(RedactionLog redactionLog) {
var clinicalSigns = redactionLog.getRedactionLogEntry()
return redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("clinical_signs"))
.filter(r -> r.getType().equals("test_animals"))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getTopLeft().getX()))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getTopLeft().getY(), Comparator.reverseOrder()))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getPage()))
.map(RedactionLogEntry::getValue)
.collect(Collectors.toList());
StringBuilder sb = new StringBuilder();
for (var clinicalSign : clinicalSigns) {
sb.append(clinicalSign).append(" / ");
}
return sb.toString();
.collect(Collectors.joining(" "));
}
private String getRule42BodyWeight(RedactionLog redactionLog) {
private String getRule32Doses(RedactionLog redactionLog) {
var dosagesPerAnimal = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("dosage_per_animal"))
.map(r -> r.getValue().replaceAll("\\n", "").trim())
.collect(Collectors.toSet());
var dosages = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("dosage"))
.map(r -> r.getValue().replaceAll("\\n", "").trim())
.collect(Collectors.toSet());
Set<String> allDosages = new HashSet<>();
allDosages.addAll(dosagesPerAnimal);
allDosages.addAll(dosages);
var bodyWeights = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("body_weight")).map(RedactionLogEntry::getValue).collect(Collectors.toList());
StringBuilder sb = new StringBuilder();
for (var bodyWeight : bodyWeights) {
sb.append(bodyWeight).append(" / ");
for (var dosagePerAnimal : allDosages) {
sb.append(dosagePerAnimal).append(" mg/kg bw").append(" , ");
}
return sb.toString();
return sb.toString().trim();
}
private String getRule5Endpoint(RedactionLog redactionLog) {
var studyType = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("study_type")).map(RedactionLogEntry::getValue).findFirst();
if (studyType.isPresent()) {
return studyType.get();
}
var guideline = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("guideline")).map(RedactionLogEntry::getValue).findFirst();
if (guideline.isPresent()) {
return mapGuideline(guideline.get());
}
return "";
}
private String getRule50ExecutiveSummary(RedactionLog redactionLog) {
return redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("executive_summary"))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getTopLeft().getX()))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getTopLeft().getY(), Comparator.reverseOrder()))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getPage()))
.map(RedactionLogEntry::getValue)
.collect(Collectors.joining(" "));
}
private String getRule19GlpCompliance(RedactionLog redactionLog) {
var glpCompliance = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("glp_compliance")).map(RedactionLogEntry::getValue).findFirst();
return glpCompliance.map(s -> "Yes. " + s).orElse("No.");
}
@ -558,18 +385,6 @@ public class RSSService {
}
private String getRule46Attachments(RedactionLog redactionLog) {
var attachments = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("attachments")).map(RedactionLogEntry::getValue).findFirst();
if (attachments.isPresent()) {
return "Yes";
}
return "None";
}
private String getRule47Illustration(RedactionLog redactionLog) {
var illustration = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("formula") || r.getType().equals("image")).findFirst();
@ -580,28 +395,213 @@ public class RSSService {
}
private String getRule49Conclusions(RedactionLog redactionLog) {
private String getRule21LimitTest(RedactionLog redactionLog) {
var conclusions = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("conclusion")).map(RedactionLogEntry::getValue).collect(Collectors.toList());
var limitTest = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("limit_test")).map(RedactionLogEntry::getValue).findFirst();
if (conclusions.isEmpty()) {
return "";
var noLimitTest = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("no_limit_test")).map(RedactionLogEntry::getValue).findFirst();
if (limitTest.isPresent() && noLimitTest.isEmpty()) {
return "Yes";
}
return conclusions.get(conclusions.size() - 1);
return "No";
}
private String getRule50ExecutiveSummary(RedactionLog redactionLog) {
private String getRule40Mortality(RedactionLog redactionLog) {
return redactionLog.getRedactionLogEntry()
var mortalitys = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("mortality")).map(RedactionLogEntry::getValue).collect(Collectors.toList());
StringBuilder sb = new StringBuilder();
for (var mortality : mortalitys) {
sb.append(mortality).append(' ');
}
return sb.toString();
}
private String getRule33NoOfAnimalsPerSexPerDose(RedactionLog redactionLog) {
var dosagesPerAnimal = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("executive_summary"))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getTopLeft().getX()))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getTopLeft().getY(), Comparator.reverseOrder()))
.sorted(Comparator.comparing(e -> e.getPositions().get(0).getPage()))
.filter(r -> r.getType().equals("dosage_per_animal"))
.map(RedactionLogEntry::getValue)
.collect(Collectors.joining(" "));
.collect(Collectors.toList());
var uniqueDosagesPerAnimal = new HashSet<>(dosagesPerAnimal);
var uniqueAnimalNumbers = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("animal_number"))
.map(RedactionLogEntry::getValue)
.collect(Collectors.toSet());
if (uniqueDosagesPerAnimal.size() == 1 && uniqueAnimalNumbers.size() > 1) {
return uniqueAnimalNumbers.size() + " * " + uniqueDosagesPerAnimal.iterator().next() + " mg/kg bw";
}
Map<String, List<String>> dosagesPerAnimalMap = new HashMap<>();
for (var dosage : dosagesPerAnimal) {
dosagesPerAnimalMap.computeIfAbsent(dosage, (x) -> new ArrayList<>()).add(dosage);
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, List<String>> entry : dosagesPerAnimalMap.entrySet()) {
sb.append(entry.getValue().size()).append(" * ").append(entry.getKey()).append(" mg/kg bw, ");
}
return sb.toString().trim();
}
private String get9RationaleForReliabilityIncludingDeficiencies(RedactionLog redactionLog) {
var guideline = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("guideline")).map(RedactionLogEntry::getValue).findFirst();
if (guideline.isPresent()) {
return "Guideline study";
}
return "";
}
private String getRule14Reference(RedactionLog redactionLog) {
var title = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("title")).map(RedactionLogEntry::getValue).collect(Collectors.joining(" "));
var author = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("author")).map(RedactionLogEntry::getValue).findFirst();
var completionDate = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("completion_date")).map(RedactionLogEntry::getValue).findFirst();
StringBuilder sb = new StringBuilder("Study report/");
sb.append(title).append('/');
author.ifPresent(s -> sb.append('/').append(s));
completionDate.ifPresent(s -> sb.append('/').append(s));
return sb.toString();
}
private String getRule29RouteOfAdministration(RedactionLog redactionLog) {
var routeOfAdministration = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("route_of_administration"))
.map(RedactionLogEntry::getValue)
.findFirst();
return routeOfAdministration.orElse("");
}
private String getRule27Sex(RedactionLog redactionLog) {
var sex = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("sex")).map(RedactionLogEntry::getValue).findFirst();
return sex.orElse("");
}
private String getRule25Species(RedactionLog redactionLog) {
var species = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("species")).map(RedactionLogEntry::getValue).findFirst();
return species.orElse("");
}
private String getRule24SpecificDetailsOnTestMaterial(RedactionLog redactionLog) {
var materials = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("materials")).map(RedactionLogEntry::getValue).collect(Collectors.toList());
StringBuilder sb = new StringBuilder();
for (var material : materials) {
sb.append(material).append(' ');
}
return sb.toString();
}
private String getRule26Strain(RedactionLog redactionLog) {
var strain = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("strain")).map(RedactionLogEntry::getValue).findFirst();
return strain.orElse("");
}
private String getRule7StudyPeriod(RedactionLog redactionLog) {
var startDate = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("experimental_start_date")).map(RedactionLogEntry::getValue).findFirst();
var endDate = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("experimental_end_date")).map(RedactionLogEntry::getValue).findFirst();
StringBuilder sb = new StringBuilder();
startDate.ifPresent(sb::append);
endDate.ifPresent(s -> sb.append(" to ").append(s));
return sb.toString();
}
private String getRule17Guideline(RedactionLog redactionLog) {
var guidelines = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("guideline")).map(RedactionLogEntry::getValue).collect(Collectors.toSet());
StringBuilder stringBuilder = new StringBuilder();
int i = 1;
for (String guideline : guidelines) {
stringBuilder.append(i).append(") according to guideline ").append(guideline).append(" (").append(mapGuideline(guideline)).append(") ");
i++;
}
return stringBuilder.toString();
}
private String getRule22TestMaterialInformation(RedactionLog redactionLog) {
var testSubstance = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("test_substance")).map(RedactionLogEntry::getValue).findFirst();
return testSubstance.map(s -> s + "/CAS number").orElse("");
}
private String getRule20TestType(RedactionLog redactionLog) {
var upAndDownProcedure = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("up_and_down_procedure")).map(RedactionLogEntry::getValue).findFirst();
if (upAndDownProcedure.isPresent()) {
return "Up down Procedure";
}
var guideline8701100 = redactionLog.getRedactionLogEntry()
.stream()
.filter(r -> r.getType().equals("guideline"))
.map(RedactionLogEntry::getValue)
.filter(g -> g.contains("870.1100"))
.findFirst();
if (guideline8701100.isPresent()) {
return "Up down Procedure";
}
return "No";
}
private String getRule30Vehicle(RedactionLog redactionLog) {
var vehicles = redactionLog.getRedactionLogEntry().stream().filter(r -> r.getType().equals("vehicle")).map(RedactionLogEntry::getValue).collect(Collectors.toList());
if (vehicles.isEmpty()) {
return "Not Applicable";
}
return String.join(" / ", vehicles);
}

View File

@ -162,30 +162,14 @@ public class RedactionLogConverterService {
}
private String checkTextForNull(String text) {
if (text == null) {
return "";
}
return text;
}
private String humanize(String label) {
String str = label;
str = str.replaceAll("-+?", " ");
str = str.replaceAll("_+?", " ");
str = str.replaceAll(" +", " ");
StringBuilder stringBuilder = new StringBuilder();
Matcher match = Pattern.compile("([a-z])([a-z]*)", Pattern.CASE_INSENSITIVE).matcher(str);
while (match.find()) {
match.appendReplacement(stringBuilder, match.group(1).toUpperCase() + match.group(2));
}
return match.appendTail(stringBuilder).toString();
/*
This method catches types like hint_only or published_information
*/
private boolean isHintType(List<Type> types, String type) {
var matchingTypes = getMatchingTypes(types, type);
Optional<Type> foundType = matchingTypes.stream().findFirst();
return foundType.map(Type::isHint).orElse(false);
}
@ -207,14 +191,13 @@ public class RedactionLogConverterService {
}
/*
This method catches types like hint_only or published_information
*/
private boolean isHintType(List<Type> types, String type) {
private String checkTextForNull(String text) {
if (text == null) {
return "";
}
return text;
var matchingTypes = getMatchingTypes(types, type);
Optional<Type> foundType = matchingTypes.stream().findFirst();
return foundType.map(Type::isHint).orElse(false);
}
@ -223,4 +206,21 @@ public class RedactionLogConverterService {
return types.stream().filter(t -> t.getType().equals(type)).collect(Collectors.toList());
}
private String humanize(String label) {
String str = label;
str = str.replaceAll("-+?", " ");
str = str.replaceAll("_+?", " ");
str = str.replaceAll(" +", " ");
StringBuilder stringBuilder = new StringBuilder();
Matcher match = Pattern.compile("([a-z])([a-z]*)", Pattern.CASE_INSENSITIVE).matcher(str);
while (match.find()) {
match.appendReplacement(stringBuilder, match.group(1).toUpperCase() + match.group(2));
}
return match.appendTail(stringBuilder).toString();
}
}

View File

@ -228,8 +228,10 @@ public class ReportGenerationService {
}
private void generateSingleFileReports(List<ReportTemplate> singleFilesTemplates, List<StoredFileInformation> storedFileInformation,
Dossier dossier, PlaceholderModel placeholderModel,
private void generateSingleFileReports(List<ReportTemplate> singleFilesTemplates,
List<StoredFileInformation> storedFileInformation,
Dossier dossier,
PlaceholderModel placeholderModel,
String downloadId,
FileModel fileStatus,
List<ReportRedactionEntry> reportEntries) {
@ -291,11 +293,6 @@ public class ReportGenerationService {
}
@FieldDefaults(makeFinal = true, level = AccessLevel.PUBLIC)
private static final class ReportTemplates {

View File

@ -10,7 +10,6 @@ import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.redaction.report.v1.api.model.ReportRequestMessage;
import com.iqser.red.service.redaction.report.v1.api.model.ReportResultMessage;
@ -54,16 +53,10 @@ public class ReportMessageReceiver {
private void addToReportResultQueue(String userId, String downloadId, String reportFileInformationStorageId, int priority) {
try {
rabbitTemplate.convertAndSend(REPORT_RESULT_QUEUE,
objectMapper.writeValueAsString(new ReportResultMessage(userId, downloadId, reportFileInformationStorageId)),
message -> {
message.getMessageProperties().setPriority(priority);
return message;
});
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
rabbitTemplate.convertAndSend(REPORT_RESULT_QUEUE, new ReportResultMessage(userId, downloadId, reportFileInformationStorageId), message -> {
message.getMessageProperties().setPriority(priority);
return message;
});
}
}

View File

@ -10,8 +10,8 @@ import org.springframework.stereotype.Service;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
import com.iqser.red.service.redaction.report.v1.api.model.StoredFileInformation;
import com.iqser.red.service.redaction.report.v1.server.multitenancy.TenantContext;
import com.iqser.red.storage.commons.service.StorageService;
import com.knecon.fforesight.tenantcommons.TenantContext;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;

View File

@ -4,20 +4,21 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemp
public final class StorageIdUtils {
private StorageIdUtils() {
throw new IllegalStateException("Utility class");
}
public static String getStorageId(String downloadId, String tmpFilename) {
return downloadId.substring(0, downloadId.length() - 3) + "/" + tmpFilename;
}
public static String getStorageId(String dossierId, String fileId, FileType fileType) {
return dossierId + "/" + fileId + "." + fileType.name() + fileType.getExtension();
}
private StorageIdUtils() {
throw new IllegalStateException("Utility class");
}
}

View File

@ -2,4 +2,5 @@ server:
port: 8084
persistence-service.url: "http://persistence-service-v1:8080"
persistence-service.url: "http://localhost:8085"
tenant-user-management-service.url: "http://localhost:8091/internal"

View File

@ -2,6 +2,8 @@ info:
description: Redaction Report Server v1
persistence-service.url: "http://persistence-service-v1:8080"
tenant-user-management-service.url: "http://tenant-user-management-service:8080/internal"
fforesight.tenants.remote: true
server:
port: 8080
@ -35,4 +37,4 @@ management:
metrics.export.prometheus.enabled: ${monitoring.enabled:false}
storage:
backend: 's3'
backend: 's3'

View File

@ -33,6 +33,7 @@ import com.iqser.red.service.redaction.report.v1.server.service.PlaceholderServi
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
import com.iqser.red.storage.commons.StorageAutoConfiguration;
import com.iqser.red.storage.commons.service.StorageService;
import com.knecon.fforesight.tenantcommons.TenantsClient;
@ExtendWith(SpringExtension.class)
@EnableAutoConfiguration(exclude = {/*StorageAutoConfiguration.class, */RabbitAutoConfiguration.class})
@ -40,6 +41,9 @@ import com.iqser.red.storage.commons.service.StorageService;
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PlaceholderTest {
@MockBean
TenantsClient tenantsClient;
@Autowired
private PlaceholderService placeholderService;

View File

@ -71,6 +71,7 @@ import com.iqser.red.service.redaction.report.v1.server.service.WordReportGenera
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
import com.iqser.red.storage.commons.StorageAutoConfiguration;
import com.iqser.red.storage.commons.service.StorageService;
import com.knecon.fforesight.tenantcommons.TenantsClient;
import lombok.SneakyThrows;
@ -80,6 +81,9 @@ import lombok.SneakyThrows;
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = StorageAutoConfiguration.class)})
public class RedactionReportIntegrationTest {
@MockBean
TenantsClient tenantsClient;
@Autowired
private ObjectMapper objectMapper;

View File

@ -55,12 +55,13 @@ 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.configuration.MessagingConfiguration;
import com.iqser.red.service.redaction.report.v1.server.multitenancy.TenantContext;
import com.iqser.red.service.redaction.report.v1.server.service.ReportGenerationService;
import com.iqser.red.service.redaction.report.v1.server.utils.FileSystemBackedStorageService;
import com.iqser.red.service.redaction.report.v1.server.utils.MetricValidationUtils;
import com.iqser.red.storage.commons.StorageAutoConfiguration;
import com.iqser.red.storage.commons.service.StorageService;
import com.knecon.fforesight.tenantcommons.TenantContext;
import com.knecon.fforesight.tenantcommons.TenantsClient;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import lombok.SneakyThrows;
@ -73,6 +74,9 @@ import lombok.extern.slf4j.Slf4j;
@AutoConfigureObservability
public class RedactionReportV2IntegrationTest {
@MockBean
TenantsClient tenantsClient;
@MockBean
private RabbitTemplate rabbitTemplate;