RED-9771 - Fixes for updating component mappings

This commit is contained in:
Andrei Isvoran 2024-07-31 10:32:36 +02:00
parent 66f1a86c77
commit 0f15e68623
6 changed files with 153 additions and 30 deletions

View File

@ -249,6 +249,36 @@ public class DossierTemplateControllerV2 implements DossierTemplateResource {
dossierTemplatePersistenceService.checkDossierTemplateExistsOrElseThrow404(dossierTemplateId);
String nameToUse = validateFileName(file, name);
if (Strings.isNullOrEmpty(delimiter)) {
throw new BadRequestException("The provided delimiter is not valid! Can't be null or empty.");
} else if (delimiter.length() != 1) {
throw new BadRequestException(format("The provided delimiter %s is not valid! Only a single character is allowed.", delimiter));
}
char cleanDelimiter = delimiter.charAt(0);
Path mappingFile = saveToFile(file);
try {
ComponentMappingMetadata resultMetaData = componentMappingService.update(dossierTemplateId,
componentMappingId,
nameToUse,
encoding,
cleanDelimiter,
mappingFile.toFile(),
file.getOriginalFilename());
return componentMappingMapper.toModel(resultMetaData);
} finally {
Files.deleteIfExists(mappingFile);
}
}
private static String validateFileName(MultipartFile file, String name) {
if (Strings.isNullOrEmpty(file.getOriginalFilename()) || !file.getOriginalFilename().endsWith(".csv")) {
throw new BadRequestException(format("File name \"%s\" does not end with .csv", file.getOriginalFilename()));
}
@ -260,32 +290,7 @@ public class DossierTemplateControllerV2 implements DossierTemplateResource {
if (Strings.isNullOrEmpty(nameToUse)) {
throw new BadRequestException(format("The provided file name \"%s\" is not valid!", nameToUse));
}
if (Strings.isNullOrEmpty(delimiter)) {
throw new BadRequestException("The provided delimiter is not valid! Can't be null or empty.");
} else if (delimiter.length() != 1) {
throw new BadRequestException(format("The provided delimiter %s is not valid! Only a single character is allowed.", delimiter));
}
char cleanDelimiter = delimiter.charAt(0);
if (Strings.isNullOrEmpty(delimiter) || delimiter.length() != 1) {
throw new BadRequestException("The provided delimiter is not valid! Only a single character is allowed.");
}
Path mappingFile = saveToFile(file);
try {
ComponentMappingMetadata resultMetaData = componentMappingService.update(dossierTemplateId,
componentMappingId,
nameToUse,
encoding,
cleanDelimiter,
mappingFile.toFile());
return componentMappingMapper.toModel(resultMetaData);
} finally {
Files.deleteIfExists(mappingFile);
}
return nameToUse;
}

View File

@ -62,11 +62,11 @@ public class ComponentMappingService {
@SneakyThrows
public ComponentMappingMetadata update(String dossierTemplateId, String mappingId, String name, String encoding, char delimiter, File mappingFile) {
public ComponentMappingMetadata update(String dossierTemplateId, String mappingId, String name, String encoding, char delimiter, File mappingFile, String fileName) {
ComponentMappingEntity entity = componentMappingPersistenceService.getEntityById(dossierTemplateId, mappingId);
return updateOrCreate(entity, name, encoding, delimiter, mappingFile);
return updateOrCreate(entity, name, encoding, delimiter, mappingFile, fileName);
}
@ -86,13 +86,13 @@ public class ComponentMappingService {
.fileName(fileName)
.build();
return updateOrCreate(entity, name, encoding, delimiter, mappingFile);
return updateOrCreate(entity, name, encoding, delimiter, mappingFile, fileName);
}
@SneakyThrows
private ComponentMappingMetadata updateOrCreate(ComponentMappingEntity entity, String name, String encoding, char delimiter, File mappingFile) {
private ComponentMappingMetadata updateOrCreate(ComponentMappingEntity entity, String name, String encoding, char delimiter, File mappingFile, String fileName) {
Charset charset = resolveCharset(encoding);
@ -104,6 +104,7 @@ public class ComponentMappingService {
entity.setNumberOfLines(stats.numberOfLines());
entity.setColumnLabels(stats.columnLabels());
entity.setVersion(entity.getVersion() + 1);
entity.setFileName(fileName);
componentMappingPersistenceService.updateOrCreate(entity.getStorageId(), mappingFile, entity);
@ -139,6 +140,10 @@ public class ComponentMappingService {
List<String[]> rows = reader.readAll();
if (rows.isEmpty()) {
throw new BadRequestException("CSV file can not be empty!");
}
columnLabels = rows.remove(0); // remove header row
if (Arrays.stream(columnLabels)

View File

@ -0,0 +1,98 @@
package com.iqser.red.service.peristence.v1.server.integration.tests;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.mock.web.MockMultipartFile;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateExternalClient;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.management.v1.processor.entity.ComponentMappingEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierTemplateEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.ComponentMappingPersistenceService;
import com.iqser.red.service.persistence.service.v2.api.external.model.ComponentMappingMetadataModel;
import feign.FeignException;
import lombok.SneakyThrows;
@EnableJpaAuditing
public class ComponentMappingTest extends AbstractPersistenceServerServiceTest {
@Autowired
private DossierTesterAndProvider dossierTesterAndProvider;
@Autowired
private DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider;
@Autowired
private DossierTemplateExternalClient dossierTemplateExternalClient;
@MockBean
private ComponentMappingPersistenceService componentMappingPersistenceService;
@Test
@SneakyThrows
public void testComponentMappingUpdate() {
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var mockMultipartFile = new MockMultipartFile("file.csv",
"file.csv",
"application/csv",
IOUtils.toByteArray(new ClassPathResource("files/componentmapping/file.csv").getInputStream()));
ComponentMappingMetadataModel componentMappingMetadataModel = dossierTemplateExternalClient.uploadMapping(dossierTemplate.getId(), mockMultipartFile, "file", "UTF-8", ",");
assertEquals(componentMappingMetadataModel.getFileName(), mockMultipartFile.getOriginalFilename());
var updateMockMultipartFile = new MockMultipartFile("update_file.csv",
"update_file.csv",
"application/csv",
IOUtils.toByteArray(new ClassPathResource("files/componentmapping/update_file.csv").getInputStream()));
when(componentMappingPersistenceService.getEntityById(anyString(), anyString())).thenReturn(ComponentMappingEntity.builder()
.id(componentMappingMetadataModel.getId())
.dossierTemplate(new DossierTemplateEntity())
.storageId(buildStorageId(dossierTemplate.getId(), componentMappingMetadataModel.getId(), "file", "update_file.csv"))
.fileName("update_file.csv")
.build());
componentMappingMetadataModel = dossierTemplateExternalClient.updateMapping(dossierTemplate.getId(), componentMappingMetadataModel.getId(), updateMockMultipartFile, "file", "UTF-8", ",");
assertEquals(componentMappingMetadataModel.getFileName(), updateMockMultipartFile.getOriginalFilename());
}
@Test
@SneakyThrows
public void testCreateComponentMappingWithEmptyCsv() {
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var mockMultipartFile = new MockMultipartFile("file.csv",
"empty.csv",
"application/csv",
IOUtils.toByteArray(new ClassPathResource("files/componentmapping/empty.csv").getInputStream()));
var result = assertThrows(FeignException.class, () -> dossierTemplateExternalClient.uploadMapping(dossierTemplate.getId(), mockMultipartFile, "file", "UTF-8", ","));
assertTrue(result.getMessage().contains("CSV file can not be empty!"));
}
public static String buildStorageId(String dossierTemplateId, String id, String name, String fileName) {
return dossierTemplateId + "/" + id + "_" + name + "_" + fileName;
}
}

View File

@ -0,0 +1,10 @@
1,"Eldon Base for stackable storage shelf, platinum",Muhammed MacIntyre,3,-213.25,38.94,35,Nunavut,Storage & Organization,0.8
2,"1.7 Cubic Foot Compact ""Cube"" Office Refrigerators",Barry French,293,457.81,208.16,68.02,Nunavut,Appliances,0.58
3,"Cardinal Slant-D Ring Binder, Heavy Gauge Vinyl",Barry French,293,46.71,8.69,2.99,Nunavut,Binders and Binder Accessories,0.39
4,R380,Clay Rozendal,483,1198.97,195.99,3.99,Nunavut,Telephones and Communication,0.58
5,Holmes HEPA Air Purifier,Carlos Soltero,515,30.94,21.78,5.94,Nunavut,Appliances,0.5
6,G.E. Longer-Life Indoor Recessed Floodlight Bulbs,Carlos Soltero,515,4.43,6.64,4.95,Nunavut,Office Furnishings,0.37
7,"Angle-D Binders with Locking Rings, Label Holders",Carl Jackson,613,-54.04,7.3,7.72,Nunavut,Binders and Binder Accessories,0.38
8,"SAFCO Mobile Desk Side File, Wire Frame",Carl Jackson,613,127.70,42.76,6.22,Nunavut,Storage & Organization,
9,"SAFCO Commercial Wire Shelving, Black",Monica Federle,643,-695.26,138.14,35,Nunavut,Storage & Organization,
10,Xerox 198,Dorothy Badders,678,-226.36,4.98,8.33,Nunavut,Paper,0.38
1 1 Eldon Base for stackable storage shelf, platinum Muhammed MacIntyre 3 -213.25 38.94 35 Nunavut Storage & Organization 0.8
2 2 1.7 Cubic Foot Compact "Cube" Office Refrigerators Barry French 293 457.81 208.16 68.02 Nunavut Appliances 0.58
3 3 Cardinal Slant-D Ring Binder, Heavy Gauge Vinyl Barry French 293 46.71 8.69 2.99 Nunavut Binders and Binder Accessories 0.39
4 4 R380 Clay Rozendal 483 1198.97 195.99 3.99 Nunavut Telephones and Communication 0.58
5 5 Holmes HEPA Air Purifier Carlos Soltero 515 30.94 21.78 5.94 Nunavut Appliances 0.5
6 6 G.E. Longer-Life Indoor Recessed Floodlight Bulbs Carlos Soltero 515 4.43 6.64 4.95 Nunavut Office Furnishings 0.37
7 7 Angle-D Binders with Locking Rings, Label Holders Carl Jackson 613 -54.04 7.3 7.72 Nunavut Binders and Binder Accessories 0.38
8 8 SAFCO Mobile Desk Side File, Wire Frame Carl Jackson 613 127.70 42.76 6.22 Nunavut Storage & Organization
9 9 SAFCO Commercial Wire Shelving, Black Monica Federle 643 -695.26 138.14 35 Nunavut Storage & Organization
10 10 Xerox 198 Dorothy Badders 678 -226.36 4.98 8.33 Nunavut Paper 0.38

View File

@ -0,0 +1,5 @@
1,"Eldon Base for stackable storage shelf, platinum",Muhammed MacIntyre,3,-213.25,38.94,35,Nunavut,Storage & Organization,0.8
2,"1.7 Cubic Foot Compact ""Cube"" Office Refrigerators",Barry French,293,457.81,208.16,68.02,Nunavut,Appliances,0.58
3,"Cardinal Slant-D<> Ring Binder, Heavy Gauge Vinyl",Barry French,293,46.71,8.69,2.99,Nunavut,Binders and Binder Accessories,0.39
4,R380,Clay Rozendal,483,1198.97,195.99,3.99,Nunavut,Telephones and Communication,0.58
5,Holmes HEPA Air Purifier,Carlos Soltero,515,30.94,21.78,5.94,Nunavut,Appliances,0.5
1 1 Eldon Base for stackable storage shelf, platinum Muhammed MacIntyre 3 -213.25 38.94 35 Nunavut Storage & Organization 0.8
2 2 1.7 Cubic Foot Compact "Cube" Office Refrigerators Barry French 293 457.81 208.16 68.02 Nunavut Appliances 0.58
3 3 Cardinal Slant-D� Ring Binder, Heavy Gauge Vinyl Barry French 293 46.71 8.69 2.99 Nunavut Binders and Binder Accessories 0.39
4 4 R380 Clay Rozendal 483 1198.97 195.99 3.99 Nunavut Telephones and Communication 0.58
5 5 Holmes HEPA Air Purifier Carlos Soltero 515 30.94 21.78 5.94 Nunavut Appliances 0.5