TSK-83: delete Classification (with tests)

This commit is contained in:
BVier 2018-01-17 13:55:23 +01:00 committed by Marcel Lengl
parent ef7326311a
commit 2d45297acd
8 changed files with 155 additions and 66 deletions

View File

@ -3,6 +3,7 @@ package pro.taskana;
import java.util.List;
import pro.taskana.exceptions.ClassificationAlreadyExistException;
import pro.taskana.exceptions.ClassificationInUseException;
import pro.taskana.exceptions.ClassificationNotFoundException;
/**
@ -44,6 +45,21 @@ public interface ClassificationService {
*/
Classification getClassification(String key, String domain) throws ClassificationNotFoundException;
/**
* Delete a classification with all child classifications.
*
* @param classificationKey
* the key of the classification you want to delete.
* @param domain
* the domains for which you want to delete the classification.
* if "", the function tries to delete the "master domain" classification and any other classification with this key.
* @throws ClassificationInUseException
* if there are Task existing, which refer to this classification.
* @throws ClassificationNotFoundException
* if for an domain no classification specification is found.
*/
void deleteClassification(String classificationKey, String domain) throws ClassificationInUseException, ClassificationNotFoundException;
/**
* Persists a new classification after adding default values. <br >
* The classification will be added to root-domain, too - if not already existing.

View File

@ -0,0 +1,13 @@
package pro.taskana.exceptions;
/**
* Thrown if a specific task is not in the database.
*/
public class ClassificationInUseException extends TaskanaException {
public ClassificationInUseException(String msg) {
super(msg);
}
private static final long serialVersionUID = 1L;
}

View File

@ -14,6 +14,7 @@ import pro.taskana.ClassificationService;
import pro.taskana.ClassificationSummary;
import pro.taskana.TaskanaEngine;
import pro.taskana.exceptions.ClassificationAlreadyExistException;
import pro.taskana.exceptions.ClassificationInUseException;
import pro.taskana.exceptions.ClassificationNotFoundException;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.exceptions.SystemException;
@ -291,4 +292,38 @@ public class ClassificationServiceImpl implements ClassificationService {
}
return isExisting;
}
@Override
public void deleteClassification(String classificationKey, String domain) throws ClassificationInUseException, ClassificationNotFoundException {
try {
taskanaEngineImpl.openConnection();
if (this.classificationMapper.findByKeyAndDomain(classificationKey, domain) == null) {
throw new ClassificationNotFoundException("The classification " + classificationKey + "wasn't found in the domain " + domain);
}
if (domain.equals("")) {
//master mode - delete all associated classifications in every domain.
List<String> domains = this.classificationMapper.getDomainsForClassification(classificationKey);
domains.remove("");
for (String classificationDomain : domains) {
deleteClassification(classificationKey, classificationDomain);
}
}
TaskServiceImpl taskService = (TaskServiceImpl) taskanaEngineImpl.getTaskService();
int countTasks = taskService.countTasksByClassificationAndDomain(classificationKey, domain);
if (countTasks > 0) {
throw new ClassificationInUseException("There are " + countTasks + " Tasks which belong to this classification or a child classification. Please complete them and try again.");
}
List<String> childKeys = this.classificationMapper.getChildrenOfClassification(classificationKey, domain);
for (String key : childKeys) {
this.deleteClassification(key, domain);
}
this.classificationMapper.deleteClassificationInDomain(classificationKey, domain);
} finally {
taskanaEngineImpl.returnConnection();
}
}
}

View File

@ -835,9 +835,9 @@ public class TaskServiceImpl implements TaskService {
}
}
private void initAttachment(AttachmentImpl attachment, Task newTask) {
if (attachment.getId() == null) {
attachment.setId(IdGenerator.generateWithPrefix(ID_PREFIX_ATTACHMENT));
public int countTasksByClassificationAndDomain(String classificationKey, String domain) {
return taskMapper.countTasksByClassificationAndDomain(classificationKey, domain);
}
}
if (attachment.getCreated() == null) {
attachment.setCreated(Instant.now());

View File

@ -2,6 +2,7 @@ package pro.taskana.model.mappings;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
@ -51,6 +52,11 @@ public interface ClassificationMapper {
value = "UPDATE CLASSIFICATION SET KEY = #{classification.key}, PARENT_CLASSIFICATION_KEY = #{classification.parentClassificationKey}, CATEGORY = #{classification.category}, TYPE = #{classification.type}, NAME = #{classification.name}, DESCRIPTION = #{classification.description}, PRIORITY = #{classification.priority}, SERVICE_LEVEL = #{classification.serviceLevel}, DOMAIN = #{classification.domain}, VALID_IN_DOMAIN = #{classification.isValidInDomain}, APPLICATION_ENTRY_POINT = #{classification.applicationEntryPoint}, CUSTOM_1 = #{classification.custom1}, CUSTOM_2 = #{classification.custom2}, CUSTOM_3 = #{classification.custom3}, CUSTOM_4 = #{classification.custom4}, CUSTOM_5 = #{classification.custom5}, CUSTOM_6 = #{classification.custom6}, CUSTOM_7 = #{classification.custom7}, CUSTOM_8 = #{classification.custom8} WHERE ID = #{classification.id}")
void update(@Param("classification") ClassificationImpl classification);
@Delete("DELETE FROM CLASSIFICATION "
+ "WHERE KEY = #{classificationKey}"
+ "AND DOMAIN = #{domain}")
void deleteClassificationInDomain(@Param("classificationKey") String classificationKey, @Param("domain") String domain);
@Select("<script>"
+ "SELECT ID, KEY, CATEGORY, TYPE, DOMAIN, NAME "
+ "FROM CLASSIFICATION "
@ -67,32 +73,16 @@ public interface ClassificationMapper {
List<ClassificationSummaryImpl> getAllClassificationsWithKey(@Param("key") String key,
@Param("domain") String domain);
@Select("SELECT C.ID, C.KEY, C.PARENT_CLASSIFICATION_KEY, C.CATEGORY, C.TYPE, C.DOMAIN, C.VALID_IN_DOMAIN, C.CREATED, C.NAME, C.DESCRIPTION, C.PRIORITY, C.SERVICE_LEVEL, C.APPLICATION_ENTRY_POINT, "
+ "C.CUSTOM_1, C.CUSTOM_2, C.CUSTOM_3, C.CUSTOM_4, C.CUSTOM_5, C.CUSTOM_6, C.CUSTOM_7, C.CUSTOM_8 "
+ "FROM CLASSIFICATION AS C LEFT JOIN WORKBASKET AS W ON C.DOMAIN = W.DOMAIN "
+ "WHERE c.KEY = #{classificationKey}"
+ "AND W.KEY = #{workbasketKey}")
@Results({@Result(property = "id", column = "ID"),
@Result(property = "key", column = "KEY"),
@Result(property = "parentClassificationKey", column = "PARENT_CLASSIFICATION_KEY"),
@Result(property = "category", column = "CATEGORY"),
@Result(property = "type", column = "TYPE"),
@Result(property = "domain", column = "DOMAIN"),
@Result(property = "isValidInDomain", column = "VALID_IN_DOMAIN"),
@Result(property = "created", column = "CREATED"),
@Result(property = "name", column = "NAME"),
@Result(property = "description", column = "DESCRIPTION"),
@Result(property = "priority", column = "PRIORITY"),
@Result(property = "serviceLevel", column = "SERVICE_LEVEL"),
@Result(property = "applicationEntryPoint", column = "APPLICATION_ENTRY_POINT"),
@Result(property = "custom1", column = "CUSTOM_1"),
@Result(property = "custom2", column = "CUSTOM_2"),
@Result(property = "custom3", column = "CUSTOM_3"),
@Result(property = "custom4", column = "CUSTOM_4"),
@Result(property = "custom5", column = "CUSTOM_5"),
@Result(property = "custom6", column = "CUSTOM_6"),
@Result(property = "custom7", column = "CUSTOM_7"),
@Result(property = "custom8", column = "CUSTOM_8")})
ClassificationImpl findByTask(@Param("classificationKey") String classificationKey,
@Param("workbasketKey") String workbasketKey);
@Select("<script>"
+ "SELECT DOMAIN "
+ "FROM CLASSIFICATION "
+ "WHERE KEY = #{classification_key} "
+ "</script>")
List<String> getDomainsForClassification(@Param("classification_key") String classificationKey);
@Select("SELECT KEY "
+ "FROM CLASSIFICATION "
+ "WHERE PARENT_CLASSIFICATION_KEY = #{classification_key} "
+ "AND DOMAIN = #{domain}")
List<String> getChildrenOfClassification(@Param("classification_key") String classificationKey, @Param("domain") String domain);
}

View File

@ -170,4 +170,10 @@ public interface TaskMapper {
@Result(property = "custom9", column = "CUSTOM_9"),
@Result(property = "custom10", column = "CUSTOM_10") })
List<TaskSummaryImpl> findTaskSummariesByWorkbasketKey(@Param("workbasketKey") String workbasketKey);
@Select("SELECT COUNT(ID) "
+ "FROM TASK "
+ "WHERE CLASSIFICATION_KEY = #{classificationKey} "
+ "AND DOMAIN = #{domain}")
int countTasksByClassificationAndDomain(@Param("classificationKey") String classificationKey, @Param("domain") String domain);
}

View File

@ -5,17 +5,15 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.sql.SQLException;
import java.util.List;
import org.h2.store.fs.FileUtils;
import org.junit.AfterClass;
import org.junit.Ignore;
import org.junit.Test;
import acceptance.AbstractAccTest;
import pro.taskana.Classification;
import pro.taskana.ClassificationService;
import pro.taskana.ClassificationSummary;
import pro.taskana.exceptions.ClassificationInUseException;
import pro.taskana.exceptions.ClassificationNotFoundException;
import pro.taskana.exceptions.NotAuthorizedException;
@ -24,54 +22,85 @@ import pro.taskana.exceptions.NotAuthorizedException;
*/
public class DeleteClassificationAccTest extends AbstractAccTest {
private ClassificationService classificationService;
public DeleteClassificationAccTest() {
super();
classificationService = taskanaEngine.getClassificationService();
}
@Ignore
@Test
public void testDeleteClassificationInDomain()
throws SQLException, ClassificationNotFoundException, NotAuthorizedException {
ClassificationService classificationService = taskanaEngine.getClassificationService();
// classificationService.deleteClassification("L140101", "DOMAIN_A");
throws SQLException, ClassificationNotFoundException, NotAuthorizedException, ClassificationInUseException {
classificationService.deleteClassification("L140101", "DOMAIN_A");
Classification classification = classificationService.getClassification("L140101", "DOMAIN_A");
assertNotNull(classification);
assertEquals("", classification.getDomain());
List<ClassificationSummary> classifications = classificationService.getAllClassifications("L140101",
"DOMAIN_A");
ClassificationSummary temp = classifications.get(classifications.size() - 1);
classification = classificationService.getClassification(temp.getKey(), temp.getDomain());
classification = classificationService.getClassification("L140101", "DOMAIN_A");
assertTrue(classification.getDomain() == "");
assertTrue("DOMAIN_A" != classification.getDomain());
}
@Test (expected = ClassificationInUseException.class)
public void testThrowExeptionIfDeleteClassificationWithExistingTasks()
throws SQLException, ClassificationNotFoundException, NotAuthorizedException, ClassificationInUseException {
classificationService.deleteClassification("L1050", "DOMAIN_A");
}
@Test (expected = ClassificationInUseException.class)
public void testThrowExeptionIfDeleteMasterClassificationWithExistingTasks()
throws SQLException, ClassificationNotFoundException, NotAuthorizedException, ClassificationInUseException {
classificationService.deleteClassification("L1050", "");
}
@Ignore
@Test
public void testDeleteClassificationFromRootDomain()
throws SQLException, ClassificationNotFoundException, NotAuthorizedException {
ClassificationService classificationService = taskanaEngine.getClassificationService();
// classificationService.deleteClassification("L1050", "DOMAIN_A");
// classificationService.deleteClassification("L1050", "");
public void testDeleteMasterClassification()
throws SQLException, ClassificationNotFoundException, NotAuthorizedException, ClassificationInUseException {
classificationService.deleteClassification("L12010", "");
Classification classification = classificationService.getClassification("L140101", "DOMAIN_A");
assertTrue(classification == null);
boolean classificationNotFound = false;
try {
classificationService.getClassification("L12010", "DOMAIN_A");
} catch (ClassificationNotFoundException e) {
classificationNotFound = true;
}
assertTrue(classificationNotFound);
}
// @Ignore
// @Test(expected = ClassificationInUseException.class)
// public void testGetExceptionIfDeletedClassificationFromRootDomainIsStillUsedInDomain()
// throws SQLException, ClassificationNotFoundException, NotAuthorizedException, ClassificationInUseException {
// ClassificationService classificationService = taskanaEngine.getClassificationService();
// classificationService.deleteClassification("L10000", "");
// }
//
// @Ignore
// @Test(expected = ClassificationInUseException.class)
// public void testGetExceptionIfDeletedClassificationIsStillUsedInTask()
// throws SQLException, ClassificationNotFoundException, NotAuthorizedException, ClassificationInUseException {
// ClassificationService classificationService = taskanaEngine.getClassificationService();
// classificationService.deleteClassification("L10000", "DOMAIN_A");
// }
@Test
public void testThrowExceptionWhenChildClassificationIsInUseAndRollback()
throws ClassificationInUseException, NotAuthorizedException, ClassificationNotFoundException {
boolean classificationInUse = false;
try {
classificationService.deleteClassification("L11010", "DOMAIN_A");
} catch (ClassificationInUseException e) {
classificationInUse = true;
}
assertTrue(classificationInUse);
classificationService.getClassification("L11010", "DOMAIN_A");
classificationInUse = false;
try {
classificationService.deleteClassification("L11010", "");
} catch (ClassificationInUseException e) {
classificationInUse = true;
}
assertTrue(classificationInUse);
classificationService.getClassification("L11010", "");
classificationService.getClassification("L11010", "DOMAIN_A");
}
@Test(expected = ClassificationNotFoundException.class)
public void testThrowClassificationNotFoundIfClassificationNotExists() throws ClassificationNotFoundException, ClassificationInUseException {
classificationService.deleteClassification("not existing classification key", "");
}
@Test(expected = ClassificationNotFoundException.class)
public void testThrowClassificationNotFoundIfClassificationNotExistsInDomain() throws ClassificationNotFoundException, ClassificationInUseException {
classificationService.deleteClassification("L10000", "DOMAIN_B");
}
@AfterClass
public static void cleanUpClass() {

View File

@ -24,7 +24,7 @@ INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000008', 'L
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000009', 'L140101', '', 'EXTERN', 'TASK', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, 'Zustimmungserklärung', 'Zustimmungserklärung', 2, 'P2D', '', 'VNR', '', '', '', '', '', '', '');
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000010', 'T2100', '', 'MANUAL', 'TASK', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, 'T-Vertragstermin VERA', 'T-Vertragstermin VERA', 2, 'P2D', '', 'VNR', '', '', '', '', '', '', '');
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000011', 'T6310', '', 'AUTOMATIC', 'TASK', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, 'T-GUK Honorarrechnung erstellen', 'Generali Unterstützungskasse Honorar wird fällig', 2, 'P2D', '', 'VNR', '', '', '', '', '', '', '');
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000013', 'DOCTYPE_DEFAULT', '', 'EXTERN', 'DOCUMENT', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, 'EP allgemein', 'EP allgemein', 99, 'P2000D', '', 'VNR', '', '', '', '', '', '', '');
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000013', 'DOKTYP_DEFAULT', '', 'EXTERN', 'DOCUMENT', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, 'EP allgemein', 'EP allgemein', 99, 'P2000D', '', 'VNR', '', '', '', '', '', '', '');
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000014', 'L10000', '', 'EXTERN', 'TASK', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, 'BUZ-Leistungsfall', 'BUZ-Leistungsfall', 1, 'P1D', '', 'VNR,RVNR,KOLVNR', '', '', '', '', '', '', '');
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000016', 'T2000', '', 'MANUAL', 'TASK', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, 'T-Vertragstermin', 'T-Vertragstermin', 1, 'P1D', '', 'VNR,RVNR,KOLVNR', '', '', '', '', '', '', '');