TSK-869: Throw error for non-unique input-file

This commit is contained in:
BVier 2019-08-07 12:11:44 +02:00 committed by Holger Hagen
parent 72a9a98b16
commit 1d41e99f9d
5 changed files with 84 additions and 1 deletions

View File

@ -6,6 +6,7 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileOutputStream;
@ -366,7 +367,7 @@ public class ClassificationDefinitionControllerIntTest {
ResponseEntity<String> response = importRequest(clList);
assertEquals(HttpStatus.OK, response.getStatusCode());
Thread.sleep(10);
LOGGER.debug("Wait for 10 s to give the system a chance to update");
LOGGER.debug("Wait 10 ms to give the system a chance to update");
ClassificationSummaryResource childWithNewParent = this.getClassificationWithKeyAndDomain("L110105",
"DOMAIN_A");
@ -378,6 +379,23 @@ public class ClassificationDefinitionControllerIntTest {
assertEquals(child2.parentKey, childWithoutParent.parentKey);
}
@Test
public void testFailOnImportDuplicates() throws IOException {
ClassificationSummaryResource classification = this.getClassificationWithKeyAndDomain("L110105", "DOMAIN_A");
String classificationString = objMapper.writeValueAsString(classification);
List<String> clList = new ArrayList<>();
clList.add(classificationString);
clList.add(classificationString);
try {
importRequest(clList);
fail("Expected http-Status 409");
} catch (HttpClientErrorException e) {
assertEquals(HttpStatus.CONFLICT, e.getStatusCode());
}
}
private ClassificationResource createClassification(String id, String key, String domain, String parentId,
String parentKey) {
ClassificationResource classificationResource = new ClassificationResource();

View File

@ -5,6 +5,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileWriter;
@ -35,6 +36,7 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.DeserializationFeature;
@ -116,6 +118,25 @@ public class WorkbasketDefinitionControllerIntTest {
assertEquals(HttpStatus.OK, responseImport.getStatusCode());
}
@Test
public void testFailOnImportDuplicates() throws IOException {
ResponseEntity<List<WorkbasketDefinitionResource>> response = template.exchange(
server + port + "/v1/workbasket-definitions?domain=DOMAIN_A",
HttpMethod.GET, request, new ParameterizedTypeReference<List<WorkbasketDefinitionResource>>() {
});
List<String> list = new ArrayList<>();
list.add(objMapper.writeValueAsString(response.getBody().get(0)));
list.add(objMapper.writeValueAsString(response.getBody().get(0)));
try {
importRequest(list);
fail("Expected http-Status 409");
} catch (HttpClientErrorException e) {
assertEquals(HttpStatus.CONFLICT, e.getStatusCode());
}
}
@Test
public void testNoErrorWhenImportWithSameIdButDifferentKeyAndDomain()
throws IOException {

View File

@ -11,6 +11,7 @@ import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@ -95,6 +96,7 @@ public class ClassificationDefinitionController {
LOGGER.debug("Entry to importClassifications()");
Map<String, String> systemIds = getSystemIds();
List<ClassificationResource> classificationsResources = extractClassificationResourcesFromFile(file);
checkForDuplicates(classificationsResources);
Map<Classification, String> childrenInFile = mapChildrenToParentKeys(classificationsResources, systemIds);
insertOrUpdateClassificationsWithoutParent(classificationsResources, systemIds);
@ -123,6 +125,22 @@ public class ClassificationDefinitionController {
return classificationsDefinitions;
}
private void checkForDuplicates(List<ClassificationResource> classificationList) {
List<String> identifiers = new ArrayList<>();
Set<String> duplicates = new HashSet<>();
for (ClassificationResource classification : classificationList) {
String identifier = classification.key + "|" + classification.domain;
if (identifiers.contains(identifier)) {
duplicates.add(identifier);
} else {
identifiers.add(identifier);
}
}
if (!duplicates.isEmpty()) {
throw new DuplicateKeyException("The 'key|domain'-identifier is not unique for the value(s): " + duplicates.toString());
}
}
private Map<Classification, String> mapChildrenToParentKeys(List<ClassificationResource> classificationResources,
Map<String, String> systemIds) {
LOGGER.debug("Entry to mapChildrenToParentKeys()");

View File

@ -4,6 +4,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
@ -86,6 +87,11 @@ public class TaskanaRestExceptionHandler extends ResponseEntityExceptionHandler
return buildResponse(ex, req, HttpStatus.CONFLICT);
}
@ExceptionHandler(DuplicateKeyException.class)
protected ResponseEntity<Object> handleDuplicateKey(DuplicateKeyException ex, WebRequest req) {
return buildResponse(ex, req, HttpStatus.CONFLICT);
}
@ExceptionHandler(ConcurrencyException.class)
protected ResponseEntity<Object> handleConcurrencyException(ConcurrencyException ex, WebRequest req) {
return buildResponse(ex, req, HttpStatus.LOCKED);

View File

@ -3,12 +3,15 @@ package pro.taskana.rest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@ -122,6 +125,7 @@ public class WorkbasketDefinitionController {
.list()
.stream()
.collect(Collectors.toMap(this::logicalId, WorkbasketSummary::getId));
checkForDuplicates(definitions);
// key: old system ID
// value: system ID
@ -179,6 +183,22 @@ public class WorkbasketDefinitionController {
return workbasketDefinitionAssembler.toModel(wbRes);
}
private void checkForDuplicates(List<WorkbasketDefinitionResource> definitions) {
List<String> identifiers = new ArrayList<>();
Set<String> duplicates = new HashSet<>();
for (WorkbasketDefinitionResource definition : definitions) {
String identifier = logicalId(workbasketDefinitionAssembler.toModel(definition.getWorkbasket()));
if (identifiers.contains(identifier)) {
duplicates.add(identifier);
} else {
identifiers.add(identifier);
}
}
if (!duplicates.isEmpty()) {
throw new DuplicateKeyException("The 'key|domain'-identifier is not unique for the value(s): " + duplicates.toString());
}
}
private String logicalId(WorkbasketSummary workbasket) {
return logicalId(workbasket.getKey(), workbasket.getDomain());
}