Compare commits
26 Commits
master
...
RED-10683-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d294dda999 | ||
|
|
a525fe6887 | ||
|
|
1c6ab159f9 | ||
|
|
a652de293b | ||
|
|
583ced03f5 | ||
|
|
bcdb54d304 | ||
|
|
713fbddbf0 | ||
|
|
c760a5f5ef | ||
|
|
28d6950b55 | ||
|
|
06c8608774 | ||
|
|
4df06b4bad | ||
|
|
c6caeb001c | ||
|
|
98e2f4f239 | ||
|
|
79a643a571 | ||
|
|
539857a6fb | ||
|
|
827ca3de11 | ||
|
|
f8af6cbc79 | ||
|
|
33e1198440 | ||
|
|
8fb5acb0ce | ||
|
|
2d0f4a8d38 | ||
|
|
96278040b2 | ||
|
|
d8f2982152 | ||
|
|
199f79baff | ||
|
|
b9b2c26526 | ||
|
|
12250c57e2 | ||
|
|
eff750e226 |
@ -11,5 +11,5 @@ commit_hash=$(git rev-parse --short=5 HEAD)
|
|||||||
# Combine branch and commit hash
|
# Combine branch and commit hash
|
||||||
buildName="${USER}-${branch}-${commit_hash}"
|
buildName="${USER}-${branch}-${commit_hash}"
|
||||||
|
|
||||||
gradle bootBuildImage --cleanCache --publishImage -PbuildbootDockerHostNetwork=true -Pversion=$buildName
|
gradle bootBuildImage --cleanCache --publishImage -Pversion=$buildName
|
||||||
echo "nexus.knecon.com:5001/red/${dir}-server-v1:$buildName"
|
echo "nexus.knecon.com:5001/red/${dir}-server-v1:$buildName"
|
||||||
@ -5,7 +5,7 @@ plugins {
|
|||||||
|
|
||||||
description = "redaction-report-service-api-v1"
|
description = "redaction-report-service-api-v1"
|
||||||
|
|
||||||
val persistenceServiceVersion = "2.380.0"
|
val persistenceServiceVersion = "2.465.91"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("io.github.openfeign:feign-core:12.2")
|
implementation("io.github.openfeign:feign-core:12.2")
|
||||||
|
|||||||
@ -14,11 +14,7 @@ public interface ReportTemplateResource {
|
|||||||
|
|
||||||
String REPORT_TEMPLATE_PATH = "/report-templates";
|
String REPORT_TEMPLATE_PATH = "/report-templates";
|
||||||
|
|
||||||
String REPORT_TEMPLATE_UPLOAD_PATH = "/upload-template";
|
String EVICT_REPORT_TEMPLATE_CACHE_PATH = "/evict-report-template-cache";
|
||||||
|
|
||||||
String TEMPLATE_ID = "templateId";
|
|
||||||
|
|
||||||
String TEMPLATE_ID_PATH_VARIABLE = "/template-id/{" + TEMPLATE_ID + "}";
|
|
||||||
|
|
||||||
String DOSSIER_TEMPLATE_ID = "dossierTemplateId";
|
String DOSSIER_TEMPLATE_ID = "dossierTemplateId";
|
||||||
|
|
||||||
@ -29,7 +25,7 @@ public interface ReportTemplateResource {
|
|||||||
List<ReportTemplate> getReportTemplatesByPlaceholder(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId, @RequestBody JSONPrimitive<String> placeholder);
|
List<ReportTemplate> getReportTemplatesByPlaceholder(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId, @RequestBody JSONPrimitive<String> placeholder);
|
||||||
|
|
||||||
|
|
||||||
@PostMapping(value = REPORT_TEMPLATE_UPLOAD_PATH + TEMPLATE_ID_PATH_VARIABLE)
|
@PostMapping(value = EVICT_REPORT_TEMPLATE_CACHE_PATH)
|
||||||
void uploadTemplate(@PathVariable(TEMPLATE_ID) String templateId);
|
void evictReportTemplateCache();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,8 @@ val springCommonsVersion = "2.1.0"
|
|||||||
val storageCommonsVersion = "2.45.0"
|
val storageCommonsVersion = "2.45.0"
|
||||||
val poiVersion = "5.2.3"
|
val poiVersion = "5.2.3"
|
||||||
val metricCommonsVersion = "2.1.0"
|
val metricCommonsVersion = "2.1.0"
|
||||||
val persistenceServiceVersion = "2.420.0"
|
val lifecycleCommonsVersion = "0.6.0"
|
||||||
|
val persistenceServiceVersion = "2.465.91"
|
||||||
val springBootStarterVersion = "3.2.3"
|
val springBootStarterVersion = "3.2.3"
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
@ -35,6 +36,7 @@ dependencies {
|
|||||||
implementation("com.iqser.red.service:persistence-service-shared-mongo-v1:${persistenceServiceVersion}")
|
implementation("com.iqser.red.service:persistence-service-shared-mongo-v1:${persistenceServiceVersion}")
|
||||||
|
|
||||||
implementation("com.knecon.fforesight:tenant-commons:${tenantCommonVersion}")
|
implementation("com.knecon.fforesight:tenant-commons:${tenantCommonVersion}")
|
||||||
|
implementation("com.knecon.fforesight:lifecycle-commons:${lifecycleCommonsVersion}")
|
||||||
implementation("com.iqser.red.commons:storage-commons:${storageCommonsVersion}")
|
implementation("com.iqser.red.commons:storage-commons:${storageCommonsVersion}")
|
||||||
implementation("com.iqser.red.commons:spring-commons:${springCommonsVersion}")
|
implementation("com.iqser.red.commons:spring-commons:${springCommonsVersion}")
|
||||||
implementation("com.iqser.red.commons:metric-commons:${metricCommonsVersion}")
|
implementation("com.iqser.red.commons:metric-commons:${metricCommonsVersion}")
|
||||||
@ -48,6 +50,9 @@ dependencies {
|
|||||||
implementation("org.springframework.cloud:spring-cloud-starter-openfeign:4.1.1")
|
implementation("org.springframework.cloud:spring-cloud-starter-openfeign:4.1.1")
|
||||||
implementation("org.apache.commons:commons-lang3:3.12.0")
|
implementation("org.apache.commons:commons-lang3:3.12.0")
|
||||||
|
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-cache:${springBootStarterVersion}")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-data-redis:${springBootStarterVersion}")
|
||||||
|
|
||||||
implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")
|
implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")
|
||||||
|
|
||||||
implementation("net.logstash.logback:logstash-logback-encoder:7.4")
|
implementation("net.logstash.logback:logstash-logback-encoder:7.4")
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfi
|
|||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
@ -21,6 +22,7 @@ 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.configuration.MessagingConfiguration;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.settings.ReportTemplateSettings;
|
import com.iqser.red.service.redaction.report.v1.server.settings.ReportTemplateSettings;
|
||||||
import com.iqser.red.storage.commons.StorageAutoConfiguration;
|
import com.iqser.red.storage.commons.StorageAutoConfiguration;
|
||||||
|
import com.knecon.fforesight.lifecyclecommons.LifecycleAutoconfiguration;
|
||||||
import com.knecon.fforesight.mongo.database.commons.MongoDatabaseCommonsAutoConfiguration;
|
import com.knecon.fforesight.mongo.database.commons.MongoDatabaseCommonsAutoConfiguration;
|
||||||
import com.knecon.fforesight.tenantcommons.MultiTenancyAutoConfiguration;
|
import com.knecon.fforesight.tenantcommons.MultiTenancyAutoConfiguration;
|
||||||
|
|
||||||
@ -30,10 +32,11 @@ import io.micrometer.core.instrument.MeterRegistry;
|
|||||||
@EnableAsync
|
@EnableAsync
|
||||||
@ImportAutoConfiguration({MultiTenancyAutoConfiguration.class, SharedMongoAutoConfiguration.class})
|
@ImportAutoConfiguration({MultiTenancyAutoConfiguration.class, SharedMongoAutoConfiguration.class})
|
||||||
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class, DataSourceAutoConfiguration.class, LiquibaseAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
|
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class, DataSourceAutoConfiguration.class, LiquibaseAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
|
||||||
@Import({MessagingConfiguration.class, StorageAutoConfiguration.class, MongoDatabaseCommonsAutoConfiguration.class})
|
@Import({MessagingConfiguration.class, StorageAutoConfiguration.class, MongoDatabaseCommonsAutoConfiguration.class, LifecycleAutoconfiguration.class})
|
||||||
@EnableFeignClients(basePackageClasses = {DossierClient.class})
|
@EnableFeignClients(basePackageClasses = {DossierClient.class})
|
||||||
@EnableMongoRepositories(basePackages = "com.iqser.red.service.persistence")
|
@EnableMongoRepositories(basePackages = "com.iqser.red.service.persistence")
|
||||||
@EnableConfigurationProperties(ReportTemplateSettings.class)
|
@EnableConfigurationProperties(ReportTemplateSettings.class)
|
||||||
|
@EnableAspectJAutoProxy
|
||||||
public class Application {
|
public class Application {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.iqser.red.service.redaction.report.v1.server.cache;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RedisCachingConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
|
||||||
|
|
||||||
|
return (builder) -> builder.withCacheConfiguration("reportTemplateCache",
|
||||||
|
RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(30)).disableCachingNullValues());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||||
|
|
||||||
|
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||||
|
template.setConnectionFactory(connectionFactory);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package com.iqser.red.service.redaction.report.v1.server.cache;
|
||||||
|
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class ReportTemplateCache {
|
||||||
|
|
||||||
|
private final ReportStorageService reportStorageService;
|
||||||
|
|
||||||
|
@Cacheable(value = "reportTemplateCache")
|
||||||
|
public byte[] getTemplate(String storageId) {
|
||||||
|
|
||||||
|
log.info("Putting report template with storageId {} into cache", storageId);
|
||||||
|
return reportStorageService.getReportTemplate(storageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@CacheEvict(value = "reportTemplateCache", allEntries = true)
|
||||||
|
public void evictReportTemplateCache() {
|
||||||
|
log.info("Evicted cache for report templates");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -10,7 +10,7 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.common.JSON
|
|||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.ReportTemplate;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.ReportTemplate;
|
||||||
import com.iqser.red.service.redaction.report.v1.api.resource.ReportTemplateResource;
|
import com.iqser.red.service.redaction.report.v1.api.resource.ReportTemplateResource;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService;
|
import com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.utils.TemplateCache;
|
import com.iqser.red.service.redaction.report.v1.server.cache.ReportTemplateCache;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -21,6 +21,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
public class ReportTemplateController implements ReportTemplateResource {
|
public class ReportTemplateController implements ReportTemplateResource {
|
||||||
|
|
||||||
private final PlaceholderService placeholderService;
|
private final PlaceholderService placeholderService;
|
||||||
|
private final ReportTemplateCache reportTemplateCache;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -30,15 +31,10 @@ public class ReportTemplateController implements ReportTemplateResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If a template with the same id is uploaded we evict it from the cache.
|
|
||||||
*
|
|
||||||
* @param templateId The id for the uploaded template
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void uploadTemplate(String templateId) {
|
public void evictReportTemplateCache(){
|
||||||
|
|
||||||
TemplateCache.evictCache(templateId);
|
reportTemplateCache.evictReportTemplateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,50 @@
|
|||||||
|
package com.iqser.red.service.redaction.report.v1.server.model;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||||
|
public class ComponentReportModel {
|
||||||
|
|
||||||
|
Integer componentStartColumn;
|
||||||
|
Integer componentValueIndexColumn;
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isComponentReport() {
|
||||||
|
|
||||||
|
return componentStartColumn != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getComponentNameColumn() {
|
||||||
|
|
||||||
|
assert isComponentReport();
|
||||||
|
return componentStartColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getComponentValueIndexColumn() {
|
||||||
|
|
||||||
|
assert writeComponentValueIndices();
|
||||||
|
return componentValueIndexColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getComponentValueColumn() {
|
||||||
|
|
||||||
|
assert isComponentReport();
|
||||||
|
if (writeComponentValueIndices()) {
|
||||||
|
return componentValueIndexColumn + 1;
|
||||||
|
}
|
||||||
|
return componentStartColumn + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean writeComponentValueIndices() {
|
||||||
|
|
||||||
|
return componentValueIndexColumn != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -22,14 +22,19 @@ public class ExcelModel {
|
|||||||
private Map<Integer, Integer> cellWidths = new HashMap<>();
|
private Map<Integer, Integer> cellWidths = new HashMap<>();
|
||||||
private Map<CellIdentifier, Cell> cellsToCopyBeforeRedactionPlaceholderRow = new HashMap<>();
|
private Map<CellIdentifier, Cell> cellsToCopyBeforeRedactionPlaceholderRow = new HashMap<>();
|
||||||
private Map<CellIdentifier, Cell> cellsToCopyAfterRedactionPlaceholderRow = new HashMap<>();
|
private Map<CellIdentifier, Cell> cellsToCopyAfterRedactionPlaceholderRow = new HashMap<>();
|
||||||
|
|
||||||
private List<Integer> writtenRows = new ArrayList<>();
|
private List<Integer> writtenRows = new ArrayList<>();
|
||||||
private boolean rowsBeforeRedactionEntryRowsAdded;
|
private boolean rowsBeforeRedactionEntryRowsAdded;
|
||||||
private boolean rssPlaceholdersPresent;
|
private boolean rssPlaceholdersPresent;
|
||||||
private boolean placeholderInFirstRow;
|
private boolean placeholderInFirstRow;
|
||||||
private boolean firstRowWritten;
|
private boolean firstRowWritten;
|
||||||
private boolean skippedPlaceholderPresent;
|
private boolean skippedPlaceholderPresent;
|
||||||
private boolean fileAttributesPlaceholderPresent;
|
|
||||||
private boolean scmFunctionPlaceholderPresent;
|
private boolean scmFunctionPlaceholderPresent;
|
||||||
|
private ComponentReportModel componentReport;
|
||||||
|
private List<FileAttributeModel> fileAttributeColumns;
|
||||||
|
|
||||||
|
public boolean isFileAttributesPlaceholderPresent() {
|
||||||
|
|
||||||
|
return !fileAttributeColumns.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.iqser.red.service.redaction.report.v1.server.service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CellTextChunkingService {
|
||||||
|
|
||||||
|
public static final int MAX_CELL_TEXT_LENGTH = 32767;
|
||||||
|
|
||||||
|
|
||||||
|
public List<String> process(String value) {
|
||||||
|
|
||||||
|
List<String> chunks = new ArrayList<>();
|
||||||
|
if (value == null) {
|
||||||
|
return chunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
int length = value.length();
|
||||||
|
int startIndex = 0;
|
||||||
|
|
||||||
|
while (startIndex < length) {
|
||||||
|
int endIndex = Math.min(startIndex + MAX_CELL_TEXT_LENGTH, length);
|
||||||
|
String chunk = value.substring(startIndex, endIndex);
|
||||||
|
chunks.add(chunk);
|
||||||
|
startIndex = endIndex;
|
||||||
|
}
|
||||||
|
return chunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,18 +1,16 @@
|
|||||||
package com.iqser.red.service.redaction.report.v1.server.service;
|
package com.iqser.red.service.redaction.report.v1.server.service;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.*;
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLog;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLog;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileAttributeConfig;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLogEntryValue;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.*;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.client.ComponentClient;
|
import com.iqser.red.service.redaction.report.v1.server.client.*;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.client.FileAttributesConfigClient;
|
import com.iqser.red.service.redaction.report.v1.server.model.*;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.model.ExcelModel;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -25,6 +23,7 @@ public class ComponentRowsReportService {
|
|||||||
|
|
||||||
ComponentClient componentResource;
|
ComponentClient componentResource;
|
||||||
FileAttributesConfigClient fileAttributesClient;
|
FileAttributesConfigClient fileAttributesClient;
|
||||||
|
CellTextChunkingService cellTextChunkingService;
|
||||||
|
|
||||||
@SuppressWarnings("checkstyle:all")
|
@SuppressWarnings("checkstyle:all")
|
||||||
static int COMPONENT_NAME_COL = 0;
|
static int COMPONENT_NAME_COL = 0;
|
||||||
@ -39,30 +38,57 @@ public class ComponentRowsReportService {
|
|||||||
|
|
||||||
String oecd = getOecdNumber(fileModel);
|
String oecd = getOecdNumber(fileModel);
|
||||||
|
|
||||||
componentLog.getComponentLogEntries().forEach(componentLogEntry -> {
|
componentLog.getComponentLogEntries()
|
||||||
|
.forEach(componentLogEntry -> {
|
||||||
|
|
||||||
if (componentLogEntry.getComponentValues().isEmpty()) {
|
if (componentLogEntry.getComponentValues().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int componentRowIdx = rowIndex.getAndIncrement();
|
|
||||||
Row componentRow = sheet.createRow(componentRowIdx);
|
|
||||||
excelModel.getWrittenRows().add(componentRowIdx);
|
|
||||||
|
|
||||||
Cell componentNameCell = componentRow.createCell(COMPONENT_NAME_COL);
|
String componentName = oecd + "-" + componentLogEntry.getName().replaceAll("_", " ");
|
||||||
componentNameCell.setCellValue(oecd + "-" + componentLogEntry.getName().replaceAll("_", " "));
|
|
||||||
|
|
||||||
for (int valueIdx = 0; valueIdx < componentLogEntry.getComponentValues().size(); valueIdx++) {
|
// Collect chunks for all values
|
||||||
String value = componentLogEntry.getComponentValues().get(valueIdx).getValue();
|
List<List<String>> valueChunksList = new ArrayList<>();
|
||||||
componentRow.createCell(COMPONENT_VALUE_STARTING_COL + valueIdx).setCellValue(value);
|
int maxChunks = 0;
|
||||||
}
|
|
||||||
|
|
||||||
});
|
for (ComponentLogEntryValue valueEntry : componentLogEntry.getComponentValues()) {
|
||||||
|
String value = valueEntry.getValue();
|
||||||
|
List<String> chunks = cellTextChunkingService.process(value);
|
||||||
|
valueChunksList.add(chunks);
|
||||||
|
if (chunks.size() > maxChunks) {
|
||||||
|
maxChunks = chunks.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create rows for each chunk index
|
||||||
|
for (int chunkIdx = 0; chunkIdx < maxChunks; chunkIdx++) {
|
||||||
|
int componentRowIdx = rowIndex.getAndIncrement();
|
||||||
|
Row componentRow = sheet.createRow(componentRowIdx);
|
||||||
|
excelModel.getWrittenRows().add(componentRowIdx);
|
||||||
|
|
||||||
|
// Component Name Cell
|
||||||
|
Cell componentNameCell = componentRow.createCell(COMPONENT_NAME_COL);
|
||||||
|
componentNameCell.setCellValue(componentName);
|
||||||
|
|
||||||
|
// Cells for each value
|
||||||
|
for (int valueIdx = 0; valueIdx < valueChunksList.size(); valueIdx++) {
|
||||||
|
List<String> chunks = valueChunksList.get(valueIdx);
|
||||||
|
String chunk = chunkIdx < chunks.size() ? chunks.get(chunkIdx) : "";
|
||||||
|
|
||||||
|
Cell valueCell = componentRow.createCell(COMPONENT_VALUE_STARTING_COL + valueIdx);
|
||||||
|
valueCell.setCellValue(chunk);
|
||||||
|
CellStyle cellStyle = sheet.getWorkbook().createCellStyle();
|
||||||
|
cellStyle.setWrapText(true);
|
||||||
|
valueCell.setCellStyle(cellStyle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
sheet.createRow(rowIndex.get());
|
sheet.createRow(rowIndex.get());
|
||||||
excelModel.getWrittenRows().add(rowIndex.get());
|
excelModel.getWrittenRows().add(rowIndex.get());
|
||||||
|
|
||||||
excelModel.setRedactionPlaceholderRow(rowIndex.getAndIncrement());
|
excelModel.setRedactionPlaceholderRow(rowIndex.getAndIncrement());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -73,7 +99,8 @@ public class ComponentRowsReportService {
|
|||||||
.filter(f -> f.getLabel().equals("OECD Number"))
|
.filter(f -> f.getLabel().equals("OECD Number"))
|
||||||
.map(FileAttributeConfig::getId)
|
.map(FileAttributeConfig::getId)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.map(oecd -> file.getFileAttributes().get(oecd))
|
.map(oecd -> file.getFileAttributes()
|
||||||
|
.get(oecd))
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,8 +70,8 @@ public class EntityLogConverterService {
|
|||||||
private Map<String, String> fillMapOfTypeAndEntityDisplayName(String dossierId) {
|
private Map<String, String> fillMapOfTypeAndEntityDisplayName(String dossierId) {
|
||||||
|
|
||||||
List<Type> typeList = new ArrayList<>();
|
List<Type> typeList = new ArrayList<>();
|
||||||
typeList.addAll(dictionaryClient.getAllTypesForDossier(dossierId, false));
|
typeList.addAll(dictionaryClient.getAllTypesForDossier(dossierId, true));
|
||||||
typeList.addAll(dictionaryClient.getAllTypesForDossierTemplate(dossierClient.getDossierById(dossierId, true, false).getDossierTemplateId(), false));
|
typeList.addAll(dictionaryClient.getAllTypesForDossierTemplate(dossierClient.getDossierById(dossierId, true, false).getDossierTemplateId(), true));
|
||||||
|
|
||||||
Map<String, String> mapOfEntityDisplayName = new HashMap<>();
|
Map<String, String> mapOfEntityDisplayName = new HashMap<>();
|
||||||
|
|
||||||
@ -103,6 +103,10 @@ public class EntityLogConverterService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entry.getState() == EntryState.PENDING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (entry.isExcluded()) {
|
if (entry.isExcluded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -170,7 +174,8 @@ public class EntityLogConverterService {
|
|||||||
.orElse(""),
|
.orElse(""),
|
||||||
checkTextForNull(entry.getTextBefore()) + entry.getValue() + checkTextForNull(entry.getTextAfter()),
|
checkTextForNull(entry.getTextBefore()) + entry.getValue() + checkTextForNull(entry.getTextAfter()),
|
||||||
entry.getValue(),
|
entry.getValue(),
|
||||||
mapOfEntityDisplayName.get(entry.getType()),
|
mapOfEntityDisplayName.get(entry.getType())
|
||||||
|
== null ? entry.getType() : mapOfEntityDisplayName.get(entry.getType()),
|
||||||
entry.getState() == EntryState.SKIPPED || entry.getState() == EntryState.IGNORED));
|
entry.getState() == EntryState.SKIPPED || entry.getState() == EntryState.IGNORED));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,268 @@
|
|||||||
|
package com.iqser.red.service.redaction.report.v1.server.service;
|
||||||
|
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.COMPONENT_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.COMPONENT_PLACEHOLDER_BASE;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.DOSSIER_ATTRIBUTE_PLACEHOLDER_BASE;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.EXCERPT_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FILE_ATTRIBUTES_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FILE_ATTRIBUTE_PLACEHOLDER_BASE;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FILE_NAME_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.INDEX_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_LEGAL_BASIS_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_PARAGRAPH_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_REASON_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_TEXT_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.PAGE_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.PARAGRAPH_INDEX_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.PARAGRAPH_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.REDACTION_ENTITY_DISPLAY_NAME_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.REDACTION_VALUE_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SCM_FUNCTION_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER;
|
||||||
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SKIPPED_PLACEHOLDER;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.apache.poi.ss.usermodel.CellStyle;
|
||||||
|
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||||
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileAttributeConfig;
|
||||||
|
import com.iqser.red.service.redaction.report.v1.server.client.FileAttributesConfigClient;
|
||||||
|
import com.iqser.red.service.redaction.report.v1.server.model.CellIdentifier;
|
||||||
|
import com.iqser.red.service.redaction.report.v1.server.model.ComponentReportModel;
|
||||||
|
import com.iqser.red.service.redaction.report.v1.server.model.ExcelModel;
|
||||||
|
import com.iqser.red.service.redaction.report.v1.server.model.FileAttributeModel;
|
||||||
|
import com.iqser.red.service.redaction.report.v1.server.model.PlaceholderInput;
|
||||||
|
|
||||||
|
import io.micrometer.core.annotation.Timed;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.experimental.FieldDefaults;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
|
||||||
|
public class ExcelModelFactory {
|
||||||
|
|
||||||
|
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,
|
||||||
|
PARAGRAPH_INDEX_PLACEHOLDER,
|
||||||
|
JUSTIFICATION_PLACEHOLDER,
|
||||||
|
EXCERPT_PLACEHOLDER,
|
||||||
|
JUSTIFICATION_PARAGRAPH_PLACEHOLDER,
|
||||||
|
JUSTIFICATION_REASON_PLACEHOLDER,
|
||||||
|
REDACTION_VALUE_PLACEHOLDER,
|
||||||
|
JUSTIFICATION_LEGAL_BASIS_PLACEHOLDER,
|
||||||
|
JUSTIFICATION_TEXT_PLACEHOLDER,
|
||||||
|
SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER,
|
||||||
|
SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER,
|
||||||
|
REDACTION_ENTITY_DISPLAY_NAME_PLACEHOLDER,
|
||||||
|
SCM_FUNCTION_PLACEHOLDER,
|
||||||
|
SKIPPED_PLACEHOLDER,
|
||||||
|
FILE_ATTRIBUTES_PLACEHOLDER,
|
||||||
|
INDEX_PLACEHOLDER,
|
||||||
|
COMPONENT_PLACEHOLDER);
|
||||||
|
|
||||||
|
FileAttributesConfigClient fileAttributesConfigClient;
|
||||||
|
|
||||||
|
|
||||||
|
@Timed("redactmanager_calculateExcelModel")
|
||||||
|
@SuppressWarnings("checkstyle:all")
|
||||||
|
public ExcelModel calculateExcelModel(Sheet sheet, String dossierTemplateId) {
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
Map<Integer, Function<PlaceholderInput, String>> placeholderCellPos = new HashMap<>();
|
||||||
|
Map<Integer, Integer> columnWidths = new HashMap<>();
|
||||||
|
Map<CellIdentifier, Cell> cellsToCopyBeforePlaceholderRow = new HashMap<>();
|
||||||
|
Map<CellIdentifier, Cell> cellsToCopyAfterPlaceholderRow = new HashMap<>();
|
||||||
|
Map<CellIdentifier, Cell> cellsToCopyInPlaceholderRow = new HashMap<>();
|
||||||
|
Integer componentColumn = null;
|
||||||
|
Integer componentValueIndexColumn = null;
|
||||||
|
List<FileAttributeModel> fileAttributeCols = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean hasRssPlaceHolders = false;
|
||||||
|
boolean hasSkippedPlaceholder = false;
|
||||||
|
int placeholderRow = -1;
|
||||||
|
boolean placeholderInFirstRow = false;
|
||||||
|
boolean hasScmFunctionPlaceholder = false;
|
||||||
|
|
||||||
|
for (int row = 0; row < sheet.getLastRowNum() + 1; row++) {
|
||||||
|
Row actualRow = sheet.getRow(row);
|
||||||
|
|
||||||
|
if (actualRow == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastCellIndex = actualRow.getLastCellNum();
|
||||||
|
for (int col = 0; col < lastCellIndex; col++) {
|
||||||
|
|
||||||
|
Cell cell = actualRow.getCell(col);
|
||||||
|
|
||||||
|
if (cell == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isFileAttributesPlaceholder = false;
|
||||||
|
int columnWidth = sheet.getColumnWidth(col);
|
||||||
|
columnWidths.put(col, columnWidth);
|
||||||
|
String cellStringValue = cell.getStringCellValue();
|
||||||
|
|
||||||
|
if (row == 0 && cellStringValue.contains("{{")) {
|
||||||
|
placeholderInFirstRow = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellStringValue.contains(COMPONENT_PLACEHOLDER_BASE)) {
|
||||||
|
hasRssPlaceHolders = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellStringValue.contains(COMPONENT_PLACEHOLDER)) {
|
||||||
|
componentColumn = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellStringValue.contains(INDEX_PLACEHOLDER)) {
|
||||||
|
componentValueIndexColumn = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellStringValue.contains(SCM_FUNCTION_PLACEHOLDER)) {
|
||||||
|
hasScmFunctionPlaceholder = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cellStringValue.contains(FILE_ATTRIBUTES_PLACEHOLDER)) {
|
||||||
|
|
||||||
|
// For each file attribute we have to replace the column header with the corresponding file attribute.
|
||||||
|
List<FileAttributeConfig> fileAttributeConfigs = fileAttributesConfigClient.getFileAttributeConfigs(dossierTemplateId);
|
||||||
|
|
||||||
|
var iterator = fileAttributeConfigs.iterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
|
||||||
|
cell = getOrCreateCell(actualRow, col);
|
||||||
|
FileAttributeConfig fileAttributeConfig = iterator.next();
|
||||||
|
cell.setCellValue(fileAttributeConfig.getLabel());
|
||||||
|
cellsToCopyBeforePlaceholderRow.put(new CellIdentifier(row, col), cell);
|
||||||
|
fileAttributeCols.add(FileAttributeModel.builder().id(fileAttributeConfig.getId()).cell(cell).build());
|
||||||
|
// If there is more than one file attribute we have to insert a new column, so we shift all columns to the right by 1
|
||||||
|
// and increase the current and last cell index.
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
lastCellIndex += 1;
|
||||||
|
col += 1;
|
||||||
|
sheet.shiftColumns(col, lastCellIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isFileAttributesPlaceholder = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFileAttributesPlaceholder) {
|
||||||
|
if (isRedactionPlaceholder(cellStringValue)) {
|
||||||
|
if (cellStringValue.equals(SKIPPED_PLACEHOLDER)) {
|
||||||
|
hasSkippedPlaceholder = true;
|
||||||
|
}
|
||||||
|
placeholderCellPos.put(col, getFunctionForPlaceHolder(cellStringValue));
|
||||||
|
placeholderRow = row;
|
||||||
|
cellsToCopyInPlaceholderRow.put(new CellIdentifier(row, col), cell);
|
||||||
|
} else {
|
||||||
|
if (placeholderRow == -1) {
|
||||||
|
cellsToCopyBeforePlaceholderRow.put(new CellIdentifier(row, col), cell);
|
||||||
|
} else {
|
||||||
|
cellsToCopyAfterPlaceholderRow.put(new CellIdentifier(row, col), cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasRssPlaceHolders) {
|
||||||
|
cellsToCopyBeforePlaceholderRow.putAll(cellsToCopyInPlaceholderRow);
|
||||||
|
cellsToCopyBeforePlaceholderRow.putAll(cellsToCopyAfterPlaceholderRow);
|
||||||
|
cellsToCopyAfterPlaceholderRow = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Calculate Placeholder Cells took: {}", System.currentTimeMillis() - start);
|
||||||
|
ComponentReportModel componentReport = new ComponentReportModel(componentColumn, componentValueIndexColumn);
|
||||||
|
return new ExcelModel(placeholderCellPos,
|
||||||
|
placeholderRow,
|
||||||
|
columnWidths,
|
||||||
|
cellsToCopyBeforePlaceholderRow,
|
||||||
|
cellsToCopyAfterPlaceholderRow,
|
||||||
|
new ArrayList<>(),
|
||||||
|
false,
|
||||||
|
hasRssPlaceHolders,
|
||||||
|
placeholderInFirstRow,
|
||||||
|
false,
|
||||||
|
hasSkippedPlaceholder,
|
||||||
|
hasScmFunctionPlaceholder,
|
||||||
|
componentReport,
|
||||||
|
fileAttributeCols);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Cell getOrCreateCell(Row actualRow, int i) {
|
||||||
|
|
||||||
|
Cell cell;
|
||||||
|
cell = actualRow.getCell(i);
|
||||||
|
|
||||||
|
// If there is more than one file attribute, starting from the 2nd one we won't find a cell in the given index so we have to create it.
|
||||||
|
if (cell == null) {
|
||||||
|
cell = actualRow.createCell(i);
|
||||||
|
CellStyle cellStyle = actualRow.getCell(i - 1).getCellStyle();
|
||||||
|
cellStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||||
|
cell.setCellStyle(cellStyle);
|
||||||
|
}
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean isRedactionPlaceholder(String text) {
|
||||||
|
|
||||||
|
return prefixRedactionPlaceholders.stream()
|
||||||
|
.anyMatch(text::startsWith) || redactionPlaceholders.stream()
|
||||||
|
.anyMatch(text::contains);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Function<PlaceholderInput, String> getFunctionForPlaceHolder(String placeholder) {
|
||||||
|
|
||||||
|
if (placeholder.startsWith(FILE_ATTRIBUTE_PLACEHOLDER_BASE)) {
|
||||||
|
return placeholderInput -> placeholderInput.getPlaceholderModel().getFileAttributeValueByPlaceholder().get(placeholder);
|
||||||
|
}
|
||||||
|
if (placeholder.startsWith(DOSSIER_ATTRIBUTE_PLACEHOLDER_BASE)) {
|
||||||
|
return placeholderInput -> placeholderInput.getPlaceholderModel().getDossierAttributesValueByPlaceholder().get(placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return switch (placeholder) {
|
||||||
|
case FILE_NAME_PLACEHOLDER -> PlaceholderInput::getFilename;
|
||||||
|
case PAGE_PLACEHOLDER -> input -> String.valueOf(input.getEntry().getPage());
|
||||||
|
case PARAGRAPH_PLACEHOLDER -> input -> input.getEntry().getSection();
|
||||||
|
case PARAGRAPH_INDEX_PLACEHOLDER -> input -> String.valueOf(input.getEntry().getParagraphIdx());
|
||||||
|
case JUSTIFICATION_PLACEHOLDER -> input -> input.getEntry().getJustification();
|
||||||
|
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_ENTITY_DISPLAY_NAME_PLACEHOLDER -> input -> input.getEntry().getEntityDisplayName();
|
||||||
|
case SKIPPED_PLACEHOLDER -> input -> input.getEntry().isSkipped() ? "true" : "false";
|
||||||
|
default -> input -> "";
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,11 +1,6 @@
|
|||||||
package com.iqser.red.service.redaction.report.v1.server.service;
|
package com.iqser.red.service.redaction.report.v1.server.service;
|
||||||
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.COMPONENT_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.DOSSIER_ATTRIBUTE_PLACEHOLDER_BASE;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.DOSSIER_NAME_PLACEHOLDER;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.DOSSIER_NAME_PLACEHOLDER;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.EXCERPT_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FILE_ATTRIBUTES_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FILE_ATTRIBUTE_PLACEHOLDER_BASE;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FILE_NAME_PLACEHOLDER;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FILE_NAME_PLACEHOLDER;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ENG;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ENG;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ENG_PLACEHOLDER;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ENG_PLACEHOLDER;
|
||||||
@ -15,29 +10,10 @@ import static com.iqser.red.service.redaction.report.v1.server.service.Placehold
|
|||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ISO_PLACEHOLDER;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ISO_PLACEHOLDER;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_TIME_ISO;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_TIME_ISO;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_TIME_ISO_PLACEHOLDER;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_TIME_ISO_PLACEHOLDER;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.INDEX_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_LEGAL_BASIS_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_PARAGRAPH_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_REASON_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.JUSTIFICATION_TEXT_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.PAGE_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.PARAGRAPH_INDEX_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.PARAGRAPH_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.REDACTION_ENTITY_DISPLAY_NAME_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.REDACTION_VALUE_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.RSS_PLACEHOLDER_BASE;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SCM_FUNCTION_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER;
|
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SKIPPED_PLACEHOLDER;
|
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -54,17 +30,14 @@ import org.apache.poi.ss.usermodel.Cell;
|
|||||||
import org.apache.poi.ss.usermodel.CellStyle;
|
import org.apache.poi.ss.usermodel.CellStyle;
|
||||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||||
|
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||||
import org.apache.poi.ss.usermodel.Drawing;
|
import org.apache.poi.ss.usermodel.Drawing;
|
||||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
|
||||||
import org.apache.poi.ss.usermodel.Picture;
|
import org.apache.poi.ss.usermodel.Picture;
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileAttributeConfig;
|
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.client.FileAttributesConfigClient;
|
|
||||||
import com.iqser.red.service.redaction.report.v1.server.model.CellIdentifier;
|
import com.iqser.red.service.redaction.report.v1.server.model.CellIdentifier;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.model.ExcelModel;
|
import com.iqser.red.service.redaction.report.v1.server.model.ExcelModel;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.model.ImagePlaceholder;
|
import com.iqser.red.service.redaction.report.v1.server.model.ImagePlaceholder;
|
||||||
@ -84,31 +57,10 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ExcelReportGenerationService {
|
public class ExcelReportGenerationService {
|
||||||
|
|
||||||
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,
|
|
||||||
PARAGRAPH_INDEX_PLACEHOLDER,
|
|
||||||
JUSTIFICATION_PLACEHOLDER,
|
|
||||||
EXCERPT_PLACEHOLDER,
|
|
||||||
JUSTIFICATION_PARAGRAPH_PLACEHOLDER,
|
|
||||||
JUSTIFICATION_REASON_PLACEHOLDER,
|
|
||||||
REDACTION_VALUE_PLACEHOLDER,
|
|
||||||
JUSTIFICATION_LEGAL_BASIS_PLACEHOLDER,
|
|
||||||
JUSTIFICATION_TEXT_PLACEHOLDER,
|
|
||||||
SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER,
|
|
||||||
SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER,
|
|
||||||
REDACTION_ENTITY_DISPLAY_NAME_PLACEHOLDER,
|
|
||||||
SCM_FUNCTION_PLACEHOLDER,
|
|
||||||
SKIPPED_PLACEHOLDER,
|
|
||||||
FILE_ATTRIBUTES_PLACEHOLDER,
|
|
||||||
INDEX_PLACEHOLDER,
|
|
||||||
COMPONENT_PLACEHOLDER);
|
|
||||||
|
|
||||||
private final ScmReportService componentReportService;
|
private final ScmReportService componentReportService;
|
||||||
private final FileAttributesConfigClient fileAttributesConfigClient;
|
|
||||||
private final ComponentRowsReportService componentRowsReportService;
|
private final ComponentRowsReportService componentRowsReportService;
|
||||||
private CreationHelper creationHelper;
|
private CreationHelper creationHelper;
|
||||||
|
final DataFormatter formatter = new DataFormatter();
|
||||||
|
|
||||||
|
|
||||||
@Timed("redactmanager_generateExcelReport")
|
@Timed("redactmanager_generateExcelReport")
|
||||||
@ -127,69 +79,72 @@ public class ExcelReportGenerationService {
|
|||||||
.filter(entry -> !entry.isSkipped())
|
.filter(entry -> !entry.isSkipped())
|
||||||
.collect(Collectors.toList()) : allReportEntries;
|
.collect(Collectors.toList()) : allReportEntries;
|
||||||
|
|
||||||
try {
|
for (Sheet sheet : workbook) {
|
||||||
|
|
||||||
for (Sheet sheet : workbook) {
|
if (!excelModel.isRowsBeforeRedactionEntryRowsAdded()) {
|
||||||
|
|
||||||
if (!excelModel.isRowsBeforeRedactionEntryRowsAdded()) {
|
for (Map.Entry<Integer, Integer> columnWidthEntry : excelModel.getCellWidths().entrySet()) {
|
||||||
|
sheet.setColumnWidth(columnWidthEntry.getKey(), columnWidthEntry.getValue());
|
||||||
for (Map.Entry<Integer, Integer> columnWidthEntry : excelModel.getCellWidths().entrySet()) {
|
|
||||||
sheet.setColumnWidth(columnWidthEntry.getKey(), columnWidthEntry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
addRows(workbook,
|
|
||||||
sheet,
|
|
||||||
excelModel.getCellsToCopyBeforeRedactionPlaceholderRow(),
|
|
||||||
excelModel.isRssPlaceholdersPresent() ? excelModel.getWrittenRows().size() : 0,
|
|
||||||
placeholderModel,
|
|
||||||
dossierName,
|
|
||||||
fileModel.getFilename(),
|
|
||||||
excelModel);
|
|
||||||
|
|
||||||
if (!excelModel.isRssPlaceholdersPresent()) {
|
|
||||||
excelModel.setRowsBeforeRedactionEntryRowsAdded(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!excelModel.isRssPlaceholdersPresent() && !excelModel.isFileAttributesPlaceholderPresent() && !excelModel.isScmFunctionPlaceholderPresent()) {
|
addRows(workbook,
|
||||||
addRedactionEntryRows(sheet, reportEntries, fileModel.getFilename(), excelModel, placeholderModel);
|
sheet,
|
||||||
}
|
excelModel.getCellsToCopyBeforeRedactionPlaceholderRow(),
|
||||||
|
excelModel.isRssPlaceholdersPresent() ? excelModel.getWrittenRows().size() : 0,
|
||||||
|
placeholderModel,
|
||||||
|
dossierName,
|
||||||
|
fileModel.getFilename(),
|
||||||
|
excelModel);
|
||||||
|
|
||||||
if (excelModel.isFileAttributesPlaceholderPresent()) {
|
if (!excelModel.isRssPlaceholdersPresent()) {
|
||||||
componentReportService.addScmRows(sheet, fileModel, excelModel);
|
excelModel.setRowsBeforeRedactionEntryRowsAdded(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRedactionReport(excelModel)) {
|
||||||
|
addRedactionEntryRows(sheet, reportEntries, fileModel.getFilename(), excelModel, placeholderModel);
|
||||||
|
} else {
|
||||||
|
if (excelModel.getComponentReport().isComponentReport()) {
|
||||||
|
componentReportService.addComponentRows(sheet, fileModel, excelModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (excelModel.isScmFunctionPlaceholderPresent()) {
|
if (excelModel.isScmFunctionPlaceholderPresent()) {
|
||||||
componentRowsReportService.addComponentRows(sheet, fileModel, excelModel);
|
componentRowsReportService.addComponentRows(sheet, fileModel, excelModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLastFile) {
|
|
||||||
addRows(workbook,
|
|
||||||
sheet,
|
|
||||||
excelModel.getCellsToCopyAfterRedactionPlaceholderRow(),
|
|
||||||
excelModel.getWrittenRows().size(),
|
|
||||||
placeholderModel,
|
|
||||||
dossierName,
|
|
||||||
fileModel.getFilename(),
|
|
||||||
excelModel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("Report Generation took: {} for file with id {}, pageCount: {}, entityLogEntryCount: {}, reportName: {}, className: {}",
|
if (isLastFile) {
|
||||||
System.currentTimeMillis() - start,
|
addRows(workbook,
|
||||||
fileModel.getId(),
|
sheet,
|
||||||
fileModel.getNumberOfPages(),
|
excelModel.getCellsToCopyAfterRedactionPlaceholderRow(),
|
||||||
reportEntries.size(),
|
excelModel.getWrittenRows().size(),
|
||||||
reportTemplateName,
|
placeholderModel,
|
||||||
getClass().getSimpleName());
|
dossierName,
|
||||||
|
fileModel.getFilename(),
|
||||||
} catch (Exception e) {
|
excelModel);
|
||||||
throw new RuntimeException(e);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.info("Report Generation took: {} for file with id {}, pageCount: {}, entityLogEntryCount: {}, reportName: {}, className: {}",
|
||||||
|
System.currentTimeMillis() - start,
|
||||||
|
fileModel.getId(),
|
||||||
|
fileModel.getNumberOfPages(),
|
||||||
|
reportEntries.size(),
|
||||||
|
reportTemplateName,
|
||||||
|
getClass().getSimpleName());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static boolean isRedactionReport(ExcelModel excelModel) {
|
||||||
|
|
||||||
|
return !(excelModel.isRssPlaceholdersPresent()
|
||||||
|
|| excelModel.isFileAttributesPlaceholderPresent()
|
||||||
|
|| excelModel.isScmFunctionPlaceholderPresent()
|
||||||
|
|| excelModel.getComponentReport().isComponentReport());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private void addRows(SXSSFWorkbook workbook,
|
private void addRows(SXSSFWorkbook workbook,
|
||||||
Sheet sheet,
|
Sheet sheet,
|
||||||
Map<CellIdentifier, Cell> copiedCells,
|
Map<CellIdentifier, Cell> copiedCells,
|
||||||
@ -208,6 +163,11 @@ public class ExcelReportGenerationService {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.debug("Copying cell {},{} with content {} from template",
|
||||||
|
cellsToCopyEntry.getKey().getRowIndex(),
|
||||||
|
cellsToCopyEntry.getKey().getColumnIndex(),
|
||||||
|
formatter.formatCellValue(cellsToCopyEntry.getValue()));
|
||||||
|
|
||||||
int indexToAddRow = cellsToCopyEntry.getKey().getRowIndex() + numberOfRowsToShift - skipRows;
|
int indexToAddRow = cellsToCopyEntry.getKey().getRowIndex() + numberOfRowsToShift - skipRows;
|
||||||
|
|
||||||
if (!createdCopyRows.contains(indexToAddRow)) {
|
if (!createdCopyRows.contains(indexToAddRow)) {
|
||||||
@ -241,12 +201,18 @@ public class ExcelReportGenerationService {
|
|||||||
Map<Integer, Function<PlaceholderInput, String>> placeholderCellPos = excelModel.getPlaceholderCellPos();
|
Map<Integer, Function<PlaceholderInput, String>> placeholderCellPos = excelModel.getPlaceholderCellPos();
|
||||||
reportEntries.forEach(entry -> {
|
reportEntries.forEach(entry -> {
|
||||||
|
|
||||||
|
PlaceholderInput placeholderInput = new PlaceholderInput(filename, entry, placeholderModel, null);
|
||||||
sheet.createRow(rowIndex.get());
|
sheet.createRow(rowIndex.get());
|
||||||
excelModel.getWrittenRows().add(rowIndex.get());
|
excelModel.getWrittenRows().add(rowIndex.get());
|
||||||
for (Map.Entry<Integer, Function<PlaceholderInput, String>> entry1 : placeholderCellPos.entrySet()) {
|
for (Map.Entry<Integer, Function<PlaceholderInput, String>> colIdxToCellValueTransform : placeholderCellPos.entrySet()) {
|
||||||
Cell cell = sheet.getRow(rowIndex.get()).createCell(entry1.getKey());
|
Cell cell = sheet.getRow(rowIndex.get()).createCell(colIdxToCellValueTransform.getKey());
|
||||||
cell.setCellValue(entry1.getValue().apply(new PlaceholderInput(filename, entry, placeholderModel, null)) == null ? "" : entry1.getValue()
|
|
||||||
.apply(new PlaceholderInput(filename, entry, placeholderModel, null)));
|
String cellValue = colIdxToCellValueTransform.getValue().apply(placeholderInput);
|
||||||
|
|
||||||
|
if (cellValue == null) {
|
||||||
|
cellValue = "";
|
||||||
|
}
|
||||||
|
cell.setCellValue(cellValue);
|
||||||
}
|
}
|
||||||
rowIndex.getAndIncrement();
|
rowIndex.getAndIncrement();
|
||||||
});
|
});
|
||||||
@ -268,7 +234,8 @@ public class ExcelReportGenerationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void replacePlaceholdersForImagePlaceholder(SXSSFWorkbook workbook, Sheet sheet, Cell cell, PlaceholderModel placeholderModel) throws IOException {
|
@SneakyThrows
|
||||||
|
private void replacePlaceholdersForImagePlaceholder(SXSSFWorkbook workbook, Sheet sheet, Cell cell, PlaceholderModel placeholderModel) {
|
||||||
|
|
||||||
for (ImagePlaceholder imagePlaceholder : placeholderModel.getImagePlaceholders()) {
|
for (ImagePlaceholder imagePlaceholder : placeholderModel.getImagePlaceholders()) {
|
||||||
|
|
||||||
@ -335,18 +302,15 @@ public class ExcelReportGenerationService {
|
|||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
if (placeholderModel.getFileAttributeValueByPlaceholder().containsKey(placeholder)) {
|
if (placeholderModel.getFileAttributeValueByPlaceholder().containsKey(placeholder)) {
|
||||||
return placeholderModel.getFileAttributeValueByPlaceholder()
|
return placeholderModel.getFileAttributeValueByPlaceholder().get(placeholder);
|
||||||
.get(placeholder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (placeholderModel.getDossierAttributesValueByPlaceholder().containsKey(placeholder)) {
|
if (placeholderModel.getDossierAttributesValueByPlaceholder().containsKey(placeholder)) {
|
||||||
return placeholderModel.getDossierAttributesValueByPlaceholder()
|
return placeholderModel.getDossierAttributesValueByPlaceholder().get(placeholder);
|
||||||
.get(placeholder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (placeholderModel.getRssComponentPlaceholder() != null && placeholderModel.getRssComponentPlaceholder().containsKey(placeholder)) {
|
if (placeholderModel.getRssComponentPlaceholder() != null && placeholderModel.getRssComponentPlaceholder().containsKey(placeholder)) {
|
||||||
return placeholderModel.getRssComponentPlaceholder()
|
return placeholderModel.getRssComponentPlaceholder().get(placeholder);
|
||||||
.get(placeholder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -383,167 +347,6 @@ public class ExcelReportGenerationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Timed("redactmanager_calculateExcelModel")
|
|
||||||
@SuppressWarnings("checkstyle:all")
|
|
||||||
public ExcelModel calculateExcelModel(Sheet sheet, String dossierTemplateId) {
|
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
Map<Integer, Function<PlaceholderInput, String>> placeholderCellPos = new HashMap<>();
|
|
||||||
Map<Integer, Integer> columnWidths = new HashMap<>();
|
|
||||||
Map<CellIdentifier, Cell> cellsToCopyBeforePlaceholderRow = new HashMap<>();
|
|
||||||
Map<CellIdentifier, Cell> cellsToCopyAfterPlaceholderRow = new HashMap<>();
|
|
||||||
Map<CellIdentifier, Cell> cellsToCopyInPlaceholderRow = new HashMap<>();
|
|
||||||
|
|
||||||
boolean hasRssPlaceHolders = false;
|
|
||||||
boolean hasSkippedPlaceholder = false;
|
|
||||||
int placeholderRow = -1;
|
|
||||||
boolean placeholderInFirstRow = false;
|
|
||||||
boolean fileAttributesPlaceholder = false;
|
|
||||||
boolean hasScmFunctionPlaceholder = false;
|
|
||||||
|
|
||||||
for (int j = 0; j < sheet.getLastRowNum() + 1; j++) {
|
|
||||||
Row actualRow = sheet.getRow(j);
|
|
||||||
if (actualRow != null) {
|
|
||||||
int lastCellIndex = actualRow.getLastCellNum();
|
|
||||||
for (int i = 0; i < lastCellIndex; i++) {
|
|
||||||
Cell cell = sheet.getRow(j).getCell(i);
|
|
||||||
if (cell != null) {
|
|
||||||
|
|
||||||
boolean skipCopy = false;
|
|
||||||
int columnWidth = sheet.getColumnWidth(i);
|
|
||||||
columnWidths.put(i, columnWidth);
|
|
||||||
String cellStringValue = cell.getStringCellValue();
|
|
||||||
|
|
||||||
if (j == 0 && cellStringValue.contains("{{")) {
|
|
||||||
placeholderInFirstRow = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cellStringValue.contains(RSS_PLACEHOLDER_BASE)) {
|
|
||||||
hasRssPlaceHolders = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cellStringValue.contains(SCM_FUNCTION_PLACEHOLDER)) {
|
|
||||||
hasScmFunctionPlaceholder = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cellStringValue.contains(FILE_ATTRIBUTES_PLACEHOLDER)) {
|
|
||||||
fileAttributesPlaceholder = true;
|
|
||||||
|
|
||||||
// For each file attribute we have to replace the column header with the corresponding file attribute.
|
|
||||||
List<FileAttributeConfig> fileAttributeConfigs = fileAttributesConfigClient.getFileAttributeConfigs(dossierTemplateId);
|
|
||||||
var iterator = fileAttributeConfigs.iterator();
|
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
|
|
||||||
cell = sheet.getRow(j).getCell(i);
|
|
||||||
|
|
||||||
// If there is more than one file attribute, starting from the 2nd one we won't find a cell in the given index so we have to create it.
|
|
||||||
if (cell == null) {
|
|
||||||
cell = sheet.getRow(j).createCell(i);
|
|
||||||
CellStyle cellStyle = sheet.getRow(j).getCell(i - 1).getCellStyle();
|
|
||||||
cellStyle.setAlignment(HorizontalAlignment.CENTER);
|
|
||||||
cell.setCellStyle(cellStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
cell.setCellValue(iterator.next().getLabel());
|
|
||||||
cellsToCopyBeforePlaceholderRow.put(new CellIdentifier(j, i), cell);
|
|
||||||
|
|
||||||
// If there is more than one file attribute we have to insert a new column, so we shift all columns to the right by 1
|
|
||||||
// and increase the current and last cell index.
|
|
||||||
if (iterator.hasNext()) {
|
|
||||||
lastCellIndex += 1;
|
|
||||||
i += 1;
|
|
||||||
sheet.shiftColumns(i, lastCellIndex, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
skipCopy = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!skipCopy) {
|
|
||||||
if (isRedactionPlaceholder(cellStringValue)) {
|
|
||||||
if (cellStringValue.equals(SKIPPED_PLACEHOLDER)) {
|
|
||||||
hasSkippedPlaceholder = true;
|
|
||||||
}
|
|
||||||
placeholderCellPos.put(i, getFunctionForPlaceHolder(cellStringValue));
|
|
||||||
placeholderRow = j;
|
|
||||||
cellsToCopyInPlaceholderRow.put(new CellIdentifier(j, i), cell);
|
|
||||||
} else {
|
|
||||||
if (placeholderRow == -1) {
|
|
||||||
cellsToCopyBeforePlaceholderRow.put(new CellIdentifier(j, i), cell);
|
|
||||||
} else {
|
|
||||||
cellsToCopyAfterPlaceholderRow.put(new CellIdentifier(j, i), cell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasRssPlaceHolders) {
|
|
||||||
cellsToCopyBeforePlaceholderRow.putAll(cellsToCopyInPlaceholderRow);
|
|
||||||
cellsToCopyBeforePlaceholderRow.putAll(cellsToCopyAfterPlaceholderRow);
|
|
||||||
cellsToCopyAfterPlaceholderRow = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("Calculate Placeholder Cells took: {}", System.currentTimeMillis() - start);
|
|
||||||
return new ExcelModel(placeholderCellPos,
|
|
||||||
placeholderRow,
|
|
||||||
columnWidths,
|
|
||||||
cellsToCopyBeforePlaceholderRow,
|
|
||||||
cellsToCopyAfterPlaceholderRow,
|
|
||||||
new ArrayList<>(),
|
|
||||||
false,
|
|
||||||
hasRssPlaceHolders,
|
|
||||||
placeholderInFirstRow,
|
|
||||||
false,
|
|
||||||
hasSkippedPlaceholder,
|
|
||||||
fileAttributesPlaceholder,
|
|
||||||
hasScmFunctionPlaceholder);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean isRedactionPlaceholder(String text) {
|
|
||||||
|
|
||||||
return prefixRedactionPlaceholders.stream()
|
|
||||||
.anyMatch(text::startsWith) || redactionPlaceholders.stream()
|
|
||||||
.anyMatch(text::contains);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Function<PlaceholderInput, String> getFunctionForPlaceHolder(String placeholder) {
|
|
||||||
|
|
||||||
if (placeholder.startsWith(FILE_ATTRIBUTE_PLACEHOLDER_BASE)) {
|
|
||||||
return placeholderInput -> placeholderInput.getPlaceholderModel().getFileAttributeValueByPlaceholder()
|
|
||||||
.get(placeholder);
|
|
||||||
}
|
|
||||||
if (placeholder.startsWith(DOSSIER_ATTRIBUTE_PLACEHOLDER_BASE)) {
|
|
||||||
return placeholderInput -> placeholderInput.getPlaceholderModel().getDossierAttributesValueByPlaceholder()
|
|
||||||
.get(placeholder);
|
|
||||||
}
|
|
||||||
|
|
||||||
return switch (placeholder) {
|
|
||||||
case FILE_NAME_PLACEHOLDER -> PlaceholderInput::getFilename;
|
|
||||||
case PAGE_PLACEHOLDER -> input -> String.valueOf(input.getEntry().getPage());
|
|
||||||
case PARAGRAPH_PLACEHOLDER -> input -> input.getEntry().getSection();
|
|
||||||
case PARAGRAPH_INDEX_PLACEHOLDER -> input -> String.valueOf(input.getEntry().getParagraphIdx());
|
|
||||||
case JUSTIFICATION_PLACEHOLDER -> input -> input.getEntry().getJustification();
|
|
||||||
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_ENTITY_DISPLAY_NAME_PLACEHOLDER -> input -> input.getEntry().getEntityDisplayName();
|
|
||||||
case SKIPPED_PLACEHOLDER -> input -> input.getEntry().isSkipped() ? "true" : "false";
|
|
||||||
default -> input -> "";
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public byte[] toByteArray(SXSSFWorkbook workbook) {
|
public byte[] toByteArray(SXSSFWorkbook workbook) {
|
||||||
|
|
||||||
|
|||||||
@ -15,13 +15,13 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemp
|
|||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;
|
||||||
import com.iqser.red.service.redaction.report.v1.api.model.ReportType;
|
import com.iqser.red.service.redaction.report.v1.api.model.ReportType;
|
||||||
import com.iqser.red.service.redaction.report.v1.api.model.StoredFileInformation;
|
import com.iqser.red.service.redaction.report.v1.api.model.StoredFileInformation;
|
||||||
|
import com.iqser.red.service.redaction.report.v1.server.cache.ReportTemplateCache;
|
||||||
|
import com.iqser.red.service.redaction.report.v1.server.model.ExcelModel;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.model.MultiFileWorkbook;
|
import com.iqser.red.service.redaction.report.v1.server.model.MultiFileWorkbook;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.model.PlaceholderModel;
|
import com.iqser.red.service.redaction.report.v1.server.model.PlaceholderModel;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEntry;
|
import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEntry;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.model.ReportTemplatesModel;
|
import com.iqser.red.service.redaction.report.v1.server.model.ReportTemplatesModel;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
|
||||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageServiceAsyncWrapper;
|
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageServiceAsyncWrapper;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.utils.TemplateCache;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -33,10 +33,11 @@ import lombok.experimental.FieldDefaults;
|
|||||||
@SuppressWarnings("PMD")
|
@SuppressWarnings("PMD")
|
||||||
public class ExcelReportTemplateService {
|
public class ExcelReportTemplateService {
|
||||||
|
|
||||||
ReportStorageService reportStorageService;
|
|
||||||
ExcelReportGenerationService excelTemplateReportGenerationService;
|
ExcelReportGenerationService excelTemplateReportGenerationService;
|
||||||
GeneratePlaceholderService generatePlaceholderService;
|
GeneratePlaceholderService generatePlaceholderService;
|
||||||
ReportStorageServiceAsyncWrapper reportStorageServiceAsyncWrapper;
|
ReportStorageServiceAsyncWrapper reportStorageServiceAsyncWrapper;
|
||||||
|
ReportTemplateCache reportTemplateCache;
|
||||||
|
ExcelModelFactory excelModelFactory;
|
||||||
|
|
||||||
|
|
||||||
public CompletableFuture<StoredFileInformation> createExcelReportFromTemplateAsync(Dossier dossier,
|
public CompletableFuture<StoredFileInformation> createExcelReportFromTemplateAsync(Dossier dossier,
|
||||||
@ -47,14 +48,14 @@ public class ExcelReportTemplateService {
|
|||||||
List<ReportRedactionEntry> reportEntries,
|
List<ReportRedactionEntry> reportEntries,
|
||||||
ReportTemplate reportTemplate) {
|
ReportTemplate reportTemplate) {
|
||||||
|
|
||||||
byte[] excelTemplate = TemplateCache.getTemplate(reportTemplate.getStorageId(), reportStorageService);
|
byte[] excelTemplate = reportTemplateCache.getTemplate(reportTemplate.getStorageId());
|
||||||
try (ByteArrayInputStream is = new ByteArrayInputStream(excelTemplate)) {
|
try (ByteArrayInputStream is = new ByteArrayInputStream(excelTemplate)) {
|
||||||
XSSFWorkbook readWorkbook = new XSSFWorkbook(is);
|
XSSFWorkbook readWorkbook = new XSSFWorkbook(is);
|
||||||
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||||
for (Sheet sheet : readWorkbook) {
|
for (Sheet sheet : readWorkbook) {
|
||||||
writeWorkbook.createSheet(sheet.getSheetName());
|
writeWorkbook.createSheet(sheet.getSheetName());
|
||||||
}
|
}
|
||||||
var excelModel = excelTemplateReportGenerationService.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
var excelModel = excelModelFactory.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
||||||
if (excelModel.isRssPlaceholdersPresent()) {
|
if (excelModel.isRssPlaceholdersPresent()) {
|
||||||
generatePlaceholderService.resolveRssValues(fileStatus, placeholderModel);
|
generatePlaceholderService.resolveRssValues(fileStatus, placeholderModel);
|
||||||
}
|
}
|
||||||
@ -80,18 +81,17 @@ public class ExcelReportTemplateService {
|
|||||||
|
|
||||||
public void prepareExcelReportTemplates(String dossierTemplateId, String templateId, ReportTemplate reportTemplate, ReportTemplatesModel reportTemplatesModel) {
|
public void prepareExcelReportTemplates(String dossierTemplateId, String templateId, ReportTemplate reportTemplate, ReportTemplatesModel reportTemplatesModel) {
|
||||||
|
|
||||||
byte[] excelTemplate = TemplateCache.getTemplate(reportTemplate.getStorageId(), reportStorageService);
|
byte[] excelTemplate = reportTemplateCache.getTemplate(reportTemplate.getStorageId());
|
||||||
try (ByteArrayInputStream is = new ByteArrayInputStream(excelTemplate)) {
|
try (ByteArrayInputStream is = new ByteArrayInputStream(excelTemplate)) {
|
||||||
XSSFWorkbook readWorkbook = new XSSFWorkbook(is);
|
XSSFWorkbook readWorkbook = new XSSFWorkbook(is);
|
||||||
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||||
for (Sheet sheet : readWorkbook) {
|
for (Sheet sheet : readWorkbook) {
|
||||||
writeWorkbook.createSheet(sheet.getSheetName());
|
writeWorkbook.createSheet(sheet.getSheetName());
|
||||||
}
|
}
|
||||||
MultiFileWorkbook multiFileWorkbook = new MultiFileWorkbook(readWorkbook,
|
|
||||||
writeWorkbook,
|
ExcelModel excelModel = excelModelFactory.calculateExcelModel(readWorkbook.getSheetAt(0), dossierTemplateId);
|
||||||
templateId,
|
|
||||||
reportTemplate.getFileName(),
|
MultiFileWorkbook multiFileWorkbook = new MultiFileWorkbook(readWorkbook, writeWorkbook, templateId, reportTemplate.getFileName(), excelModel);
|
||||||
excelTemplateReportGenerationService.calculateExcelModel(readWorkbook.getSheetAt(0), dossierTemplateId));
|
|
||||||
reportTemplatesModel.multiFileWorkbookReportTemplates.add(multiFileWorkbook);
|
reportTemplatesModel.multiFileWorkbookReportTemplates.add(multiFileWorkbook);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Could not generate multifile excel report.");
|
throw new RuntimeException("Could not generate multifile excel report.");
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import static com.iqser.red.service.redaction.report.v1.server.service.Placehold
|
|||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ISO_PLACEHOLDER;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_DATE_ISO_PLACEHOLDER;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_TIME_ISO_PLACEHOLDER;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.FORMAT_TIME_ISO_PLACEHOLDER;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.IUCLID_FUNCTION_PLACEHOLDER;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.IUCLID_FUNCTION_PLACEHOLDER;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.RSS_PLACEHOLDER_BASE;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.COMPONENT_PLACEHOLDER_BASE;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SEEDS_FUNCTION_JUSTIFICATION_PLACEHOLDER;
|
||||||
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER;
|
import static com.iqser.red.service.redaction.report.v1.server.service.PlaceholderService.SEEDS_FUNCTION_REDACTION_GROUPED_BY_JUSTIFICATION_PAGES_PLACEHOLDER;
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ public class GeneratePlaceholderService {
|
|||||||
|
|
||||||
if (!rssResponse.getFiles().isEmpty()) {
|
if (!rssResponse.getFiles().isEmpty()) {
|
||||||
for (Map.Entry<String, SCMComponent> rssEntry : rssResponse.getFiles().get(0).getResult().entrySet()) {
|
for (Map.Entry<String, SCMComponent> rssEntry : rssResponse.getFiles().get(0).getResult().entrySet()) {
|
||||||
rssPlaceholders.put(RSS_PLACEHOLDER_BASE + rssEntry.getKey() + "}}", rssEntry.getValue().getOriginalValue());
|
rssPlaceholders.put(COMPONENT_PLACEHOLDER_BASE + rssEntry.getKey() + "}}", rssEntry.getValue().getOriginalValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,7 +53,7 @@ public class PlaceholderService {
|
|||||||
public static final String SCM_FUNCTION_PLACEHOLDER = "{{function.scm}}";
|
public static final String SCM_FUNCTION_PLACEHOLDER = "{{function.scm}}";
|
||||||
public static final String FILE_ATTRIBUTE_PLACEHOLDER_BASE = "{{file.attribute.";
|
public static final String FILE_ATTRIBUTE_PLACEHOLDER_BASE = "{{file.attribute.";
|
||||||
public static final String DOSSIER_ATTRIBUTE_PLACEHOLDER_BASE = "{{dossier.attribute.";
|
public static final String DOSSIER_ATTRIBUTE_PLACEHOLDER_BASE = "{{dossier.attribute.";
|
||||||
public static final String RSS_PLACEHOLDER_BASE = "{{component.";
|
public static final String COMPONENT_PLACEHOLDER_BASE = "{{component.";
|
||||||
public static final String COMPONENT_PLACEHOLDER = "{{component}}";
|
public static final String COMPONENT_PLACEHOLDER = "{{component}}";
|
||||||
public static final String FILE_ATTRIBUTES_PLACEHOLDER = "{{file.attributes}}";
|
public static final String FILE_ATTRIBUTES_PLACEHOLDER = "{{file.attributes}}";
|
||||||
public static final String INDEX_PLACEHOLDER = "{{index}}";
|
public static final String INDEX_PLACEHOLDER = "{{index}}";
|
||||||
|
|||||||
@ -7,9 +7,6 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import org.apache.poi.ss.usermodel.Sheet;
|
|
||||||
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|
||||||
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -29,12 +26,10 @@ import com.iqser.red.service.redaction.report.v1.server.model.ReportTemplatesMod
|
|||||||
import com.iqser.red.service.redaction.report.v1.server.settings.ReportTemplateSettings;
|
import com.iqser.red.service.redaction.report.v1.server.settings.ReportTemplateSettings;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageServiceAsyncWrapper;
|
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageServiceAsyncWrapper;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.utils.TemplateCache;
|
|
||||||
|
|
||||||
import io.micrometer.core.annotation.Timed;
|
import io.micrometer.core.annotation.Timed;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.experimental.FieldDefaults;
|
import lombok.experimental.FieldDefaults;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@ -57,7 +52,6 @@ public class ReportGenerationService {
|
|||||||
ReportTemplateService reportTemplateService;
|
ReportTemplateService reportTemplateService;
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
@Timed("redactmanager_generateReports")
|
@Timed("redactmanager_generateReports")
|
||||||
public String generateReports(ReportRequestMessage reportMessage) {
|
public String generateReports(ReportRequestMessage reportMessage) {
|
||||||
|
|
||||||
@ -75,9 +69,8 @@ public class ReportGenerationService {
|
|||||||
var isLastFile = fileIdIndex == reportMessage.getFileIds().size() - 1;
|
var isLastFile = fileIdIndex == reportMessage.getFileIds().size() - 1;
|
||||||
|
|
||||||
String dossierId = dossier.getId();
|
String dossierId = dossier.getId();
|
||||||
String fileId = reportMessage.getFileIds()
|
String fileId = reportMessage.getFileIds().get(fileIdIndex);
|
||||||
.get(fileIdIndex);
|
String dossierName = dossier.getName();
|
||||||
String dossierName = dossier.getDossierName();
|
|
||||||
|
|
||||||
var fileStatus = fileStatusClient.getFileStatus(dossierId, fileId);
|
var fileStatus = fileStatusClient.getFileStatus(dossierId, fileId);
|
||||||
generatePlaceholderService.resolveFileAttributeValues(fileStatus, placeholderModel);
|
generatePlaceholderService.resolveFileAttributeValues(fileStatus, placeholderModel);
|
||||||
@ -222,12 +215,12 @@ public class ReportGenerationService {
|
|||||||
|
|
||||||
return CompletableFuture.allOf(singleFilesTemplates.stream()
|
return CompletableFuture.allOf(singleFilesTemplates.stream()
|
||||||
.map(reportTemplate -> reportTemplateService.createReportFromTemplateAsync(dossier,
|
.map(reportTemplate -> reportTemplateService.createReportFromTemplateAsync(dossier,
|
||||||
fileStatus,
|
fileStatus,
|
||||||
placeholderModel,
|
placeholderModel,
|
||||||
reportTemplate.getFileName(),
|
reportTemplate.getFileName(),
|
||||||
downloadId,
|
downloadId,
|
||||||
reportEntries,
|
reportEntries,
|
||||||
reportTemplate).thenAccept(storedFileInformation::add))
|
reportTemplate).thenAccept(storedFileInformation::add))
|
||||||
.toArray(CompletableFuture[]::new));
|
.toArray(CompletableFuture[]::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,148 +38,102 @@ public class ScmReportService {
|
|||||||
|
|
||||||
final ComponentClient componentResource;
|
final ComponentClient componentResource;
|
||||||
final FileAttributesConfigClient fileAttributesClient;
|
final FileAttributesConfigClient fileAttributesClient;
|
||||||
|
final CellTextChunkingService cellTextChunkingService;
|
||||||
final DataFormatter formatter = new DataFormatter();
|
final DataFormatter formatter = new DataFormatter();
|
||||||
Row row;
|
|
||||||
|
|
||||||
public void addScmRows(Sheet sheet, FileModel fileModel, ExcelModel excelModel) {
|
|
||||||
|
|
||||||
var firstRow = sheet.getRow(0);
|
public void addComponentRows(Sheet sheet, FileModel fileModel, ExcelModel excelModel) {
|
||||||
|
|
||||||
int firstRowIndex = 1;
|
|
||||||
while (firstRow == null) {
|
|
||||||
firstRow = sheet.getRow(firstRowIndex);
|
|
||||||
firstRowIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sometimes first row is identified wrong. this makes sure we always identify the correct first row which contains the
|
|
||||||
// header cells as we need them for file attributes (e.g. OECD Number)
|
|
||||||
Cell firstCell = firstRow.getCell(0);
|
|
||||||
if (formatter.formatCellValue(firstCell).equals("File")) {
|
|
||||||
row = firstRow;
|
|
||||||
} else {
|
|
||||||
firstRow = row;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fileColumnIndex = 0;
|
|
||||||
int textColumnIndex = firstRow.getLastCellNum() - 1;
|
|
||||||
int valueIndexColumn = firstRow.getLastCellNum() - 2;
|
|
||||||
int componentColumnIndex = firstRow.getLastCellNum() - 3;
|
|
||||||
|
|
||||||
CellUtil.setAlignment(firstRow.getCell(textColumnIndex), HorizontalAlignment.LEFT);
|
|
||||||
|
|
||||||
ComponentLog componentLog = componentResource.getComponentLog(fileModel.getDossierId(), fileModel.getId(), true);
|
ComponentLog componentLog = componentResource.getComponentLog(fileModel.getDossierId(), fileModel.getId(), true);
|
||||||
|
|
||||||
AtomicInteger rowIndex = new AtomicInteger(excelModel.getRedactionPlaceholderRow());
|
AtomicInteger rowIndexCounter = new AtomicInteger(excelModel.getRedactionPlaceholderRow());
|
||||||
|
|
||||||
Map<String, Integer> componentIndexMap = new HashMap<>();
|
Map<String, Integer> componentIndexMap = new HashMap<>();
|
||||||
|
|
||||||
Row finalFirstRow = firstRow;
|
componentLog.getComponentLogEntries()
|
||||||
|
.forEach(componentLogEntry -> {
|
||||||
|
|
||||||
componentLog.getComponentLogEntries().forEach(componentLogEntry -> {
|
if (componentLogEntry.getComponentValues().isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (componentLogEntry.getComponentValues().isEmpty()) {
|
// Process each ComponentLogEntryValue
|
||||||
return;
|
addOtherCells(sheet, excelModel, rowIndexCounter, componentIndexMap, componentLogEntry, fileModel);
|
||||||
}
|
|
||||||
|
|
||||||
int rowIndexAndIncrement = rowIndex.getAndIncrement();
|
});
|
||||||
Row row = sheet.createRow(rowIndexAndIncrement);
|
|
||||||
excelModel.getWrittenRows().add(rowIndexAndIncrement);
|
|
||||||
|
|
||||||
// Filename cell
|
autosizeColumns(sheet, rowIndexCounter);
|
||||||
Cell fileNameCell = row.createCell(fileColumnIndex);
|
|
||||||
fileNameCell.setCellValue(fileModel.getFilename() == null ? "" : fileModel.getFilename());
|
|
||||||
CellUtil.setVerticalAlignment(fileNameCell, VerticalAlignment.TOP);
|
|
||||||
|
|
||||||
// Component, file attributes and index cell
|
sheet.createRow(rowIndexCounter.get());
|
||||||
addOtherCells(sheet, excelModel, rowIndex, componentIndexMap, componentLogEntry, row, fileModel, finalFirstRow, componentColumnIndex, textColumnIndex, valueIndexColumn);
|
excelModel.getWrittenRows().add(rowIndexCounter.get());
|
||||||
|
excelModel.setRedactionPlaceholderRow(rowIndexCounter.getAndIncrement());
|
||||||
|
}
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
private static void autosizeColumns(Sheet sheet, AtomicInteger rowIndexCounter) {
|
||||||
// Autosize all cells besides the last column because the extracted text should be multiline
|
// Autosize all cells besides the last column because the extracted text should be multiline
|
||||||
if (sheet instanceof SXSSFSheet) {
|
if (sheet instanceof SXSSFSheet) {
|
||||||
((SXSSFSheet) sheet).trackAllColumnsForAutoSizing();
|
((SXSSFSheet) sheet).trackAllColumnsForAutoSizing();
|
||||||
for (int i = 0; i < firstRow.getLastCellNum()-1; i++) {
|
Row row = sheet.getRow(rowIndexCounter.get() - 1);
|
||||||
sheet.autoSizeColumn(i);
|
if (row != null) {
|
||||||
|
for (int i = 0; i < row.getLastCellNum(); i++) {
|
||||||
|
sheet.autoSizeColumn(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sheet.createRow(rowIndex.get());
|
|
||||||
excelModel.getWrittenRows().add(rowIndex.get());
|
|
||||||
excelModel.setRedactionPlaceholderRow(rowIndex.getAndIncrement());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void addOtherCells(Sheet sheet,
|
private void addOtherCells(Sheet sheet,
|
||||||
ExcelModel excelModel,
|
ExcelModel excelModel,
|
||||||
AtomicInteger rowIndex,
|
AtomicInteger rowIndexCounter,
|
||||||
Map<String, Integer> componentIndexMap,
|
Map<String, Integer> componentIndexMap,
|
||||||
ComponentLogEntry componentLogEntry,
|
ComponentLogEntry componentLogEntry,
|
||||||
Row row,
|
FileModel fileModel) {
|
||||||
FileModel fileModel,
|
|
||||||
Row firstRow,
|
|
||||||
int componentColumnIndex,
|
|
||||||
int textColumnIndex,
|
|
||||||
int valueIndexColumn) {
|
|
||||||
|
|
||||||
int rowIndexAndIncrement;
|
|
||||||
|
|
||||||
Cell componentNameCell = row.createCell(componentColumnIndex);
|
|
||||||
String componentValue = componentLogEntry.getName().replaceAll("_", " ");
|
String componentValue = componentLogEntry.getName().replaceAll("_", " ");
|
||||||
componentNameCell.setCellValue(componentValue);
|
|
||||||
|
|
||||||
List<FileAttributeModel> fileAttributeModels = buildFileAttributeModels(fileModel, firstRow);
|
int componentIndex = componentIndexMap.getOrDefault(componentValue, 0);
|
||||||
|
|
||||||
// FileAttributes cells
|
|
||||||
addFileAttribute(row, fileModel, fileAttributeModels);
|
|
||||||
|
|
||||||
var iterator = componentLogEntry.getComponentValues().iterator();
|
List<FileAttributeModel> fileAttributeModels = excelModel.getFileAttributeColumns();
|
||||||
while (iterator.hasNext()) {
|
|
||||||
ComponentLogEntryValue componentLogEntryValue = iterator.next();
|
|
||||||
Cell indexCell = row.createCell(valueIndexColumn);
|
|
||||||
Cell textExtractionCell = row.createCell(textColumnIndex);
|
|
||||||
|
|
||||||
addTextExtraction(componentLogEntryValue, textExtractionCell);
|
for (ComponentLogEntryValue componentLogEntryValue : componentLogEntry.getComponentValues()) {
|
||||||
|
|
||||||
if (componentIndexMap.containsKey(componentValue)) {
|
componentIndex++;
|
||||||
int indexValue = componentIndexMap.get(componentValue);
|
componentIndexMap.put(componentValue, componentIndex);
|
||||||
indexCell.setCellValue(indexValue + 1);
|
|
||||||
|
|
||||||
Cell componentCell = row.createCell(componentColumnIndex);
|
List<String> textChunks = cellTextChunkingService.process(componentLogEntryValue.getValue());
|
||||||
componentCell.setCellValue(componentValue);
|
|
||||||
|
for (String chunk : textChunks) {
|
||||||
|
int currentRowIdx = rowIndexCounter.getAndIncrement();
|
||||||
|
Row row = sheet.createRow(currentRowIdx);
|
||||||
|
excelModel.getWrittenRows().add(currentRowIdx);
|
||||||
|
|
||||||
Cell fileNameCell = row.createCell(0);
|
Cell fileNameCell = row.createCell(0);
|
||||||
fileNameCell.setCellValue(fileModel.getFilename());
|
fileNameCell.setCellValue(fileModel.getFilename() == null ? "" : fileModel.getFilename());
|
||||||
|
CellUtil.setVerticalAlignment(fileNameCell, VerticalAlignment.TOP);
|
||||||
|
|
||||||
|
Cell componentNameCell = row.createCell(excelModel.getComponentReport().getComponentNameColumn());
|
||||||
|
componentNameCell.setCellValue(componentValue);
|
||||||
|
if (excelModel.getComponentReport().writeComponentValueIndices()) {
|
||||||
|
Cell indexCell = row.createCell(excelModel.getComponentReport().getComponentValueIndexColumn());
|
||||||
|
indexCell.setCellValue(componentIndex);
|
||||||
|
CellUtil.setAlignment(indexCell, HorizontalAlignment.CENTER);
|
||||||
|
CellUtil.setVerticalAlignment(indexCell, VerticalAlignment.TOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell textCell = row.createCell(excelModel.getComponentReport().getComponentValueColumn());
|
||||||
|
textCell.setCellValue(chunk);
|
||||||
|
CellStyle cellStyle = sheet.getWorkbook().createCellStyle();
|
||||||
|
cellStyle.setWrapText(true);
|
||||||
|
textCell.setCellStyle(cellStyle);
|
||||||
|
|
||||||
addFileAttribute(row, fileModel, fileAttributeModels);
|
addFileAttribute(row, fileModel, fileAttributeModels);
|
||||||
|
|
||||||
componentIndexMap.put(componentValue, indexValue + 1);
|
|
||||||
} else {
|
|
||||||
componentIndexMap.put(componentValue, 1);
|
|
||||||
indexCell.setCellValue(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
CellUtil.setAlignment(indexCell, HorizontalAlignment.CENTER);
|
|
||||||
CellUtil.setVerticalAlignment(componentNameCell, VerticalAlignment.TOP);
|
|
||||||
CellUtil.setVerticalAlignment(indexCell, VerticalAlignment.TOP);
|
|
||||||
|
|
||||||
if (iterator.hasNext()) {
|
|
||||||
rowIndexAndIncrement = rowIndex.getAndIncrement();
|
|
||||||
row = sheet.createRow(rowIndexAndIncrement);
|
|
||||||
excelModel.getWrittenRows().add(rowIndexAndIncrement);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void addTextExtraction(ComponentLogEntryValue componentLogEntryValue, Cell textExtractionCell) {
|
|
||||||
|
|
||||||
textExtractionCell.setCellValue(componentLogEntryValue.getValue() == null ? "" : componentLogEntryValue.getValue());
|
|
||||||
CellStyle cellStyle = textExtractionCell.getCellStyle();
|
|
||||||
cellStyle.setWrapText(true);
|
|
||||||
textExtractionCell.setCellStyle(cellStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void addFileAttribute(Row row, FileModel fileModel, List<FileAttributeModel> fileAttributeModels) {
|
private void addFileAttribute(Row row, FileModel fileModel, List<FileAttributeModel> fileAttributeModels) {
|
||||||
|
|
||||||
for (FileAttributeModel fileAttributeModel : fileAttributeModels) {
|
for (FileAttributeModel fileAttributeModel : fileAttributeModels) {
|
||||||
@ -202,6 +156,7 @@ public class ScmReportService {
|
|||||||
return fileAttributes;
|
return fileAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<FileAttributeModel> buildFileAttributeModels(FileModel file, Row firstRow) {
|
private List<FileAttributeModel> buildFileAttributeModels(FileModel file, Row firstRow) {
|
||||||
|
|
||||||
List<FileAttributeModel> fileAttributeModels = new ArrayList<>();
|
List<FileAttributeModel> fileAttributeModels = new ArrayList<>();
|
||||||
@ -217,5 +172,4 @@ public class ScmReportService {
|
|||||||
return fileAttributeModels;
|
return fileAttributeModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -280,7 +280,7 @@ public class WordReportGenerationService {
|
|||||||
var search = entry.getKey();
|
var search = entry.getKey();
|
||||||
var replace = entry.getValue();
|
var replace = entry.getValue();
|
||||||
|
|
||||||
if (paragraphText.contains(search)) {
|
if (replace != null && paragraphText.contains(search)) {
|
||||||
isIuclid = search.equals(IUCLID_FUNCTION_PLACEHOLDER);
|
isIuclid = search.equals(IUCLID_FUNCTION_PLACEHOLDER);
|
||||||
String escapedSearch = Pattern.quote(search);
|
String escapedSearch = Pattern.quote(search);
|
||||||
String escapedReplace = Matcher.quoteReplacement(replace);
|
String escapedReplace = Matcher.quoteReplacement(replace);
|
||||||
@ -586,6 +586,10 @@ public class WordReportGenerationService {
|
|||||||
|
|
||||||
private int setText(XWPFTableCell cell, String value) {
|
private int setText(XWPFTableCell cell, String value) {
|
||||||
|
|
||||||
|
// Apache POI automatically adds an initial empty paragraph to a cell resulting in a break line.
|
||||||
|
if (cell.getParagraphs() != null && !cell.getParagraphs().isEmpty()) {
|
||||||
|
cell.removeParagraph(0);
|
||||||
|
}
|
||||||
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
|
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
|
||||||
XWPFParagraph addParagraph = cell.addParagraph();
|
XWPFParagraph addParagraph = cell.addParagraph();
|
||||||
XWPFRun run = addParagraph.createRun();
|
XWPFRun run = addParagraph.createRun();
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEnt
|
|||||||
import com.iqser.red.service.redaction.report.v1.server.model.ReportTemplatesModel;
|
import com.iqser.red.service.redaction.report.v1.server.model.ReportTemplatesModel;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageServiceAsyncWrapper;
|
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageServiceAsyncWrapper;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.utils.TemplateCache;
|
import com.iqser.red.service.redaction.report.v1.server.cache.ReportTemplateCache;
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -34,6 +34,7 @@ public class WordReportTemplateService {
|
|||||||
ReportStorageService reportStorageService;
|
ReportStorageService reportStorageService;
|
||||||
ReportStorageServiceAsyncWrapper reportStorageServiceAsyncWrapper;
|
ReportStorageServiceAsyncWrapper reportStorageServiceAsyncWrapper;
|
||||||
WordReportGenerationService wordReportGenerationService;
|
WordReportGenerationService wordReportGenerationService;
|
||||||
|
ReportTemplateCache reportTemplateCache;
|
||||||
|
|
||||||
public CompletableFuture<StoredFileInformation> createWordReportFromTemplateAsync(Dossier dossier,
|
public CompletableFuture<StoredFileInformation> createWordReportFromTemplateAsync(Dossier dossier,
|
||||||
FileModel fileStatus,
|
FileModel fileStatus,
|
||||||
@ -43,7 +44,7 @@ public class WordReportTemplateService {
|
|||||||
List<ReportRedactionEntry> reportEntries,
|
List<ReportRedactionEntry> reportEntries,
|
||||||
ReportTemplate reportTemplate) {
|
ReportTemplate reportTemplate) {
|
||||||
|
|
||||||
byte[] wordTemplate = TemplateCache.getTemplate(reportTemplate.getStorageId(), reportStorageService);
|
byte[] wordTemplate = reportTemplateCache.getTemplate(reportTemplate.getStorageId());
|
||||||
try (ByteArrayInputStream is = new ByteArrayInputStream(wordTemplate)) {
|
try (ByteArrayInputStream is = new ByteArrayInputStream(wordTemplate)) {
|
||||||
XWPFDocument doc = new XWPFDocument(is);
|
XWPFDocument doc = new XWPFDocument(is);
|
||||||
wordReportGenerationService.generateWordReport(reportEntries, placeholderModel, templateName, doc, fileStatus, dossier, true);
|
wordReportGenerationService.generateWordReport(reportEntries, placeholderModel, templateName, doc, fileStatus, dossier, true);
|
||||||
@ -60,7 +61,7 @@ public class WordReportTemplateService {
|
|||||||
|
|
||||||
public void prepareWordReportTemplates(String templateId, ReportTemplate reportTemplate, ReportTemplatesModel reportTemplatesModel) {
|
public void prepareWordReportTemplates(String templateId, ReportTemplate reportTemplate, ReportTemplatesModel reportTemplatesModel) {
|
||||||
|
|
||||||
byte[] wordTemplate = TemplateCache.getTemplate(reportTemplate.getStorageId(), reportStorageService);
|
byte[] wordTemplate = reportTemplateCache.getTemplate(reportTemplate.getStorageId());
|
||||||
try (ByteArrayInputStream is = new ByteArrayInputStream(wordTemplate)) {
|
try (ByteArrayInputStream is = new ByteArrayInputStream(wordTemplate)) {
|
||||||
XWPFDocument doc = new XWPFDocument(is);
|
XWPFDocument doc = new XWPFDocument(is);
|
||||||
MultiFileDocument multiFileDocument = new MultiFileDocument(wordTemplate, doc, templateId, reportTemplate.getFileName(), 0, 0);
|
MultiFileDocument multiFileDocument = new MultiFileDocument(wordTemplate, doc, templateId, reportTemplate.getFileName(), 0, 0);
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
package com.iqser.red.service.redaction.report.v1.server.storage;
|
package com.iqser.red.service.redaction.report.v1.server.storage;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
|
import org.springframework.core.task.TaskExecutor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -16,10 +15,12 @@ import lombok.RequiredArgsConstructor;
|
|||||||
public class ReportStorageServiceAsyncWrapper {
|
public class ReportStorageServiceAsyncWrapper {
|
||||||
|
|
||||||
private final ReportStorageService reportStorageService;
|
private final ReportStorageService reportStorageService;
|
||||||
private final Executor ioExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
private final TaskExecutor taskExecutor;
|
||||||
|
|
||||||
|
|
||||||
public CompletableFuture<String> storeObjectAsync(String downloadId, byte[] data) {
|
public CompletableFuture<String> storeObjectAsync(String downloadId, byte[] data) {
|
||||||
return CompletableFuture.supplyAsync(() -> reportStorageService.storeObject(downloadId, data), ioExecutor);
|
|
||||||
|
return CompletableFuture.supplyAsync(() -> reportStorageService.storeObject(downloadId, data), taskExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
package com.iqser.red.service.redaction.report.v1.server.utils;
|
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Cache;
|
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
|
||||||
import com.iqser.red.service.redaction.report.v1.server.storage.ReportStorageService;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a caching mechanism for templates to avoid getting a template from storage for each file when we request a download,
|
|
||||||
* since the templates are provided at startup.
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class TemplateCache {
|
|
||||||
|
|
||||||
private static final Cache<String, byte[]> cache = Caffeine.newBuilder().maximumSize(500).build();
|
|
||||||
|
|
||||||
|
|
||||||
public static byte[] getTemplate(String templateId, ReportStorageService reportStorageService) {
|
|
||||||
|
|
||||||
return cache.get(templateId, reportStorageService::getReportTemplate);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void evictCache(String templateId) {
|
|
||||||
|
|
||||||
log.info("Evicting cache for template {}", templateId);
|
|
||||||
cache.invalidate(templateId);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -8,6 +8,9 @@ fforesight.tenants.remote: true
|
|||||||
server:
|
server:
|
||||||
port: 8080
|
port: 8080
|
||||||
|
|
||||||
|
lifecycle:
|
||||||
|
base-package: com.iqser.red.service.redaction.report.v1.server
|
||||||
|
|
||||||
logging.pattern.level: "%5p [${spring.application.name},%X{traceId:-},%X{spanId:-}]"
|
logging.pattern.level: "%5p [${spring.application.name},%X{traceId:-},%X{spanId:-}]"
|
||||||
|
|
||||||
logging.type: ${LOGGING_TYPE:CONSOLE}
|
logging.type: ${LOGGING_TYPE:CONSOLE}
|
||||||
@ -35,6 +38,8 @@ spring:
|
|||||||
max-attempts: 3
|
max-attempts: 3
|
||||||
max-interval: 15000
|
max-interval: 15000
|
||||||
prefetch: 1
|
prefetch: 1
|
||||||
|
cache:
|
||||||
|
type: redis
|
||||||
data:
|
data:
|
||||||
mongodb:
|
mongodb:
|
||||||
auto-index-creation: true
|
auto-index-creation: true
|
||||||
@ -44,7 +49,12 @@ spring:
|
|||||||
port: ${MONGODB_PORT:27017}
|
port: ${MONGODB_PORT:27017}
|
||||||
username: ${MONGODB_USER}
|
username: ${MONGODB_USER}
|
||||||
password: ${MONGODB_PASSWORD}
|
password: ${MONGODB_PASSWORD}
|
||||||
|
redis:
|
||||||
|
database: 0
|
||||||
|
host: ${REDIS_HOST:localhost}
|
||||||
|
port: ${REDIS_PORT:6379}
|
||||||
|
password: ${REDIS_PASSWORD}
|
||||||
|
timeout: 60000
|
||||||
|
|
||||||
management:
|
management:
|
||||||
endpoint:
|
endpoint:
|
||||||
|
|||||||
@ -32,6 +32,10 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
|||||||
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||||
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
|
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
|
||||||
import org.apache.poi.xwpf.usermodel.XWPFRun;
|
import org.apache.poi.xwpf.usermodel.XWPFRun;
|
||||||
|
import org.apache.poi.xwpf.usermodel.XWPFTable;
|
||||||
|
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
|
||||||
|
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
@ -49,6 +53,8 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
|
|||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLog;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLog;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLogEntry;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLogEntryValue;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogLegalBasis;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogLegalBasis;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.Dossier;
|
||||||
@ -67,6 +73,7 @@ import com.iqser.red.service.redaction.report.v1.server.model.ImagePlaceholder;
|
|||||||
import com.iqser.red.service.redaction.report.v1.server.model.PlaceholderModel;
|
import com.iqser.red.service.redaction.report.v1.server.model.PlaceholderModel;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEntry;
|
import com.iqser.red.service.redaction.report.v1.server.model.ReportRedactionEntry;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.service.EntityLogConverterService;
|
import com.iqser.red.service.redaction.report.v1.server.service.EntityLogConverterService;
|
||||||
|
import com.iqser.red.service.redaction.report.v1.server.service.ExcelModelFactory;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.service.ExcelReportGenerationService;
|
import com.iqser.red.service.redaction.report.v1.server.service.ExcelReportGenerationService;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.service.GeneratePlaceholderService;
|
import com.iqser.red.service.redaction.report.v1.server.service.GeneratePlaceholderService;
|
||||||
import com.iqser.red.service.redaction.report.v1.server.service.WordReportGenerationService;
|
import com.iqser.red.service.redaction.report.v1.server.service.WordReportGenerationService;
|
||||||
@ -129,6 +136,9 @@ public class RedactionReportIntegrationTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private GeneratePlaceholderService generatePlaceholderService;
|
private GeneratePlaceholderService generatePlaceholderService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ExcelModelFactory excelModelFactory;
|
||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
private DictionaryClient dictionaryClient;
|
private DictionaryClient dictionaryClient;
|
||||||
|
|
||||||
@ -186,6 +196,19 @@ public class RedactionReportIntegrationTest {
|
|||||||
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Justification Appendix A1_justification.docx")) {
|
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/Justification Appendix A1_justification.docx")) {
|
||||||
fileOutputStream.write(wordReport);
|
fileOutputStream.write(wordReport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (XWPFTable table : doc.getTables()) {
|
||||||
|
for (XWPFTableRow row : table.getRows()) {
|
||||||
|
for (XWPFTableCell cell : row.getTableCells()) {
|
||||||
|
for (XWPFParagraph paragraph : cell.getParagraphs()) {
|
||||||
|
String paragraphText = paragraph.getText();
|
||||||
|
if (!paragraphText.equals("\n")) {
|
||||||
|
Assertions.assertFalse(paragraphText.startsWith("\n"), "Paragraph starts with an empty line.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -404,7 +427,7 @@ public class RedactionReportIntegrationTest {
|
|||||||
var placeholders = buildPlaceHolderModel(new HashMap<>(), new HashMap<>(), List.of());
|
var placeholders = buildPlaceHolderModel(new HashMap<>(), new HashMap<>(), List.of());
|
||||||
|
|
||||||
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
||||||
var excelModel = excelTemplateReportGenerationService.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
var excelModel = excelModelFactory.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
||||||
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||||
writeWorkbook.createSheet("Sheet1");
|
writeWorkbook.createSheet("Sheet1");
|
||||||
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, dossier.getName(), fileModel, excelModel, true);
|
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, dossier.getName(), fileModel, excelModel, true);
|
||||||
@ -435,7 +458,7 @@ public class RedactionReportIntegrationTest {
|
|||||||
var placeholders = buildPlaceHolderModel(new HashMap<>(), new HashMap<>(), List.of());
|
var placeholders = buildPlaceHolderModel(new HashMap<>(), new HashMap<>(), List.of());
|
||||||
|
|
||||||
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
||||||
var excelModel = excelTemplateReportGenerationService.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
var excelModel = excelModelFactory.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
||||||
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||||
writeWorkbook.createSheet("Sheet1");
|
writeWorkbook.createSheet("Sheet1");
|
||||||
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, "dossierName", fileModel, excelModel, false);
|
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, "dossierName", fileModel, excelModel, false);
|
||||||
@ -481,7 +504,7 @@ public class RedactionReportIntegrationTest {
|
|||||||
var placeholders = buildPlaceHolderModel(new HashMap<>(), new HashMap<>(), List.of());
|
var placeholders = buildPlaceHolderModel(new HashMap<>(), new HashMap<>(), List.of());
|
||||||
|
|
||||||
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
||||||
var excelModel = excelTemplateReportGenerationService.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
var excelModel = excelModelFactory.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
||||||
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||||
writeWorkbook.createSheet("Sheet1");
|
writeWorkbook.createSheet("Sheet1");
|
||||||
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, dossier.getName(), fileModel, excelModel, true);
|
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, dossier.getName(), fileModel, excelModel, true);
|
||||||
@ -515,7 +538,7 @@ public class RedactionReportIntegrationTest {
|
|||||||
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()))));
|
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}", IOUtils.toByteArray(imageResource.getInputStream()))));
|
||||||
|
|
||||||
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
||||||
var excelModel = excelTemplateReportGenerationService.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
var excelModel = excelModelFactory.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
||||||
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||||
writeWorkbook.createSheet("Sheet1");
|
writeWorkbook.createSheet("Sheet1");
|
||||||
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, "dossierName", fileModel, excelModel, true);
|
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, "dossierName", fileModel, excelModel, true);
|
||||||
@ -527,6 +550,40 @@ public class RedactionReportIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SneakyThrows
|
||||||
|
public void testExcelReportWithPendingEntries() {
|
||||||
|
|
||||||
|
Dossier dossier = prepareDossier();
|
||||||
|
EntityLog entityLog = objectMapper.readValue(new ClassPathResource("files/entityLogWithPendingEntries.json").getInputStream(), EntityLog.class);
|
||||||
|
List<EntityLogLegalBasis> legalBasisMapping = objectMapper.readValue(new ClassPathResource("files/legalBasisMapping.json").getInputStream(), new TypeReference<>() {
|
||||||
|
});
|
||||||
|
Map<String, String> mapOfEntityDisplayName = createEntityDisplayNames(entityLog);
|
||||||
|
List<ReportRedactionEntry> reportEntries = entityLogConverterService.convertAndSort(DOSSIER_ID, FILE_ID,entityLog, legalBasisMapping, mapOfEntityDisplayName);
|
||||||
|
var imageResource = new ClassPathResource("files/exampleImage.jpg");
|
||||||
|
|
||||||
|
FileModel fileModel = FileModel.builder().filename("filename").build();
|
||||||
|
|
||||||
|
ClassPathResource templateResource = new ClassPathResource("templates/Excel Report_PlaceholderTest.xlsx");
|
||||||
|
|
||||||
|
var placeholders = buildPlaceHolderModel(Map.of("{{dossier_attribute.test1}}", "replaced_dossier_test1"),
|
||||||
|
Map.of("{{file_attribute.test1}}", "replaced_file_test1", "{{file_attribute.test2}}", "replaced_file_test2"),
|
||||||
|
List.of(new ImagePlaceholder("{{dossier.attribute.Signature}}",
|
||||||
|
IOUtils.toByteArray(imageResource.getInputStream()))));
|
||||||
|
|
||||||
|
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
||||||
|
var excelModel = excelModelFactory.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
||||||
|
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||||
|
writeWorkbook.createSheet("Sheet1");
|
||||||
|
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, "dossierName", fileModel, excelModel, true);
|
||||||
|
|
||||||
|
byte[] excelTemplateReport3 = excelTemplateReportGenerationService.toByteArray(writeWorkbook);
|
||||||
|
try (FileOutputStream fileOutputStream = new FileOutputStream( getTemporaryDirectory() + "/Report_Without_Pending_Entries.xlsx")) {
|
||||||
|
fileOutputStream.write(excelTemplateReport3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void testScmReport() {
|
public void testScmReport() {
|
||||||
@ -556,7 +613,7 @@ public class RedactionReportIntegrationTest {
|
|||||||
var placeholders = buildPlaceHolderModel(new HashMap<>(), Map.of("{{file.attribute.placeholder}}", "OECD Number"), List.of());
|
var placeholders = buildPlaceHolderModel(new HashMap<>(), Map.of("{{file.attribute.placeholder}}", "OECD Number"), List.of());
|
||||||
|
|
||||||
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
||||||
var excelModel = excelTemplateReportGenerationService.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
var excelModel = excelModelFactory.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
||||||
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||||
writeWorkbook.createSheet("Sheet1");
|
writeWorkbook.createSheet("Sheet1");
|
||||||
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, dossier.getName(), fileModel, excelModel, true);
|
excelTemplateReportGenerationService.generateExcelReport(reportEntries, placeholders, "test", writeWorkbook, dossier.getName(), fileModel, excelModel, true);
|
||||||
@ -569,6 +626,63 @@ public class RedactionReportIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SneakyThrows
|
||||||
|
public void testComponentLogEntryExceedingMaxValue() {
|
||||||
|
|
||||||
|
Dossier dossier = prepareDossier();
|
||||||
|
|
||||||
|
FileModel fileModel = FileModel.builder()
|
||||||
|
.filename("filename")
|
||||||
|
.dossierId(dossier.getId())
|
||||||
|
.dossierTemplateId(dossier.getDossierTemplateId())
|
||||||
|
.fileAttributes(Map.of("TestAttribute", "Lorem Ipsum"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ComponentLogEntry componentLogEntry = createLargeComponentLogEntry();
|
||||||
|
ComponentLog componentLog = new ComponentLog();
|
||||||
|
componentLog.setComponentLogEntries(List.of(componentLogEntry));
|
||||||
|
|
||||||
|
when(componentClient.getComponentLog(dossier.getId(), fileModel.getId(), true)).thenReturn(componentLog);
|
||||||
|
|
||||||
|
List<FileAttributeConfig> fileAttributeConfigs = objectMapper.readValue(new ClassPathResource("files/scm/fileAttributes.json").getInputStream(), new TypeReference<>() {
|
||||||
|
});
|
||||||
|
when(fileAttributesConfigClient.getFileAttributeConfigs(dossier.getDossierTemplateId())).thenReturn(fileAttributeConfigs);
|
||||||
|
|
||||||
|
ClassPathResource templateResource = new ClassPathResource("templates/scm_report.xlsx");
|
||||||
|
XSSFWorkbook readWorkbook = new XSSFWorkbook(templateResource.getInputStream());
|
||||||
|
var excelModel = excelModelFactory.calculateExcelModel(readWorkbook.getSheetAt(0), dossier.getDossierTemplateId());
|
||||||
|
SXSSFWorkbook writeWorkbook = new SXSSFWorkbook();
|
||||||
|
writeWorkbook.createSheet("Sheet1");
|
||||||
|
|
||||||
|
var placeholders = buildPlaceHolderModel(new HashMap<>(), new HashMap<>(), List.of());
|
||||||
|
|
||||||
|
excelTemplateReportGenerationService.generateExcelReport(new ArrayList<>(), placeholders, "test", writeWorkbook, dossier.getName(), fileModel, excelModel, true);
|
||||||
|
|
||||||
|
|
||||||
|
byte[] excelTemplateReport3 = excelTemplateReportGenerationService.toByteArray(writeWorkbook);
|
||||||
|
try (FileOutputStream fileOutputStream = new FileOutputStream(getTemporaryDirectory() + "/scm_report.xlsx")) {
|
||||||
|
fileOutputStream.write(excelTemplateReport3);
|
||||||
|
}
|
||||||
|
System.out.println(getTemporaryDirectory() + "/scm_report.xlsx");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static ComponentLogEntry createLargeComponentLogEntry() {
|
||||||
|
|
||||||
|
int length = 35000; // Exceed the max cell length of 32,767
|
||||||
|
String longValue = "A".repeat(length);
|
||||||
|
|
||||||
|
ComponentLogEntryValue componentLogEntryValue = new ComponentLogEntryValue();
|
||||||
|
componentLogEntryValue.setValue(longValue);
|
||||||
|
|
||||||
|
ComponentLogEntry componentLogEntry = new ComponentLogEntry();
|
||||||
|
componentLogEntry.setName("TestComponent");
|
||||||
|
componentLogEntry.setComponentValues(List.of(componentLogEntryValue));
|
||||||
|
return componentLogEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Map<String, String> createEntityDisplayNames(EntityLog entityLog) {
|
private Map<String, String> createEntityDisplayNames(EntityLog entityLog) {
|
||||||
|
|
||||||
Type t1 = new Type();
|
Type t1 = new Type();
|
||||||
|
|||||||
@ -19,7 +19,7 @@ public final class OsUtils {
|
|||||||
if (isWindows() && StringUtils.isNotBlank(tmpdir)) {
|
if (isWindows() && StringUtils.isNotBlank(tmpdir)) {
|
||||||
return tmpdir;
|
return tmpdir;
|
||||||
}
|
}
|
||||||
return "/tmp";
|
return "/tmp/";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,8 @@ management:
|
|||||||
spring:
|
spring:
|
||||||
main:
|
main:
|
||||||
allow-circular-references: true
|
allow-circular-references: true
|
||||||
|
cache:
|
||||||
|
type: SIMPLE
|
||||||
data:
|
data:
|
||||||
mongodb:
|
mongodb:
|
||||||
auto-index-creation: true
|
auto-index-creation: true
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,17 @@
|
|||||||
|
<configuration>
|
||||||
|
|
||||||
|
<springProperty scope="configuration" name="logType" source="logging.type"/>
|
||||||
|
<springProperty scope="context" name="application.name" source="spring.application.name"/>
|
||||||
|
<springProperty scope="context" name="version" source="project.version"/>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
|
||||||
|
|
||||||
|
<appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="${logType}"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
Loading…
x
Reference in New Issue
Block a user