RED-6686 Extract Tenant and user-management code into a separate service.
This commit is contained in:
parent
8c296b5a53
commit
2a26c5ac9d
@ -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>
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
|
||||
@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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'
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user