TSK-273: Complete a bulk of tasks. Improved Delete bulk of tasks. Renamed claimTaskBulk to claimTasks.

This commit is contained in:
Marcel Lengl 2018-02-15 11:16:35 +01:00 committed by BerndBreier
parent ebc198ce99
commit d9db1d9a45
6 changed files with 123 additions and 31 deletions

View File

@ -290,7 +290,7 @@ public interface TaskService {
* @throws WorkbasketNotFoundException
* if the target WB can´t be found.
*/
BulkOperationResults<String, TaskanaException> transferBulk(String destinationWorkbasketKey, List<String> taskIds)
BulkOperationResults<String, TaskanaException> transferTasks(String destinationWorkbasketKey, List<String> taskIds)
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException;
/**
@ -325,6 +325,21 @@ public interface TaskService {
* @param tasks
* the ids of the tasks to delete.
* @return the result of the operations with Id and Exception for each failed task deletion.
* @throws InvalidArgumentException
* if the TaskIds parameter is NULL
*/
BulkOperationResults<String, TaskanaException> deleteTasks(List<String> tasks);
BulkOperationResults<String, TaskanaException> deleteTasks(List<String> tasks) throws InvalidArgumentException;
/**
* Completes a list of tasks.
*
* @param taskIds
* of the tasks which should be completed.
* @return the result of the operations with Id and Exception for each failed task completion.
* @throws InvalidArgumentException
* If the taskId parameter is NULL.
* @throws NotAuthorizedException
*/
BulkOperationResults<String, TaskanaException> completeTasks(List<String> taskIds)
throws InvalidArgumentException, NotAuthorizedException;
}

View File

@ -200,6 +200,7 @@ public class TaskServiceImpl implements TaskService {
task.setCompleted(now);
task.setModified(now);
task.setState(TaskState.COMPLETED);
task.setOwner(CurrentUserContext.getUserid());
taskMapper.update(task);
LOGGER.debug("Method completeTask() completed Task '{}'.", taskId);
} finally {
@ -209,6 +210,72 @@ public class TaskServiceImpl implements TaskService {
return task;
}
@Override
public BulkOperationResults<String, TaskanaException> completeTasks(List<String> taskIds)
throws InvalidArgumentException, NotAuthorizedException {
try {
LOGGER.debug("entry to completeTasks(taskIds = {})", taskIds);
taskanaEngineImpl.openConnection();
// Check pre-conditions with throwing Exceptions
if (taskIds == null) {
throw new InvalidArgumentException(
"TaskIds can´t be used as NULL-Parameter.");
}
// process bulk-complete
BulkOperationResults<String, TaskanaException> bulkLog = new BulkOperationResults<>();
if (!taskIds.isEmpty()) {
// remove null/empty taskIds with message
Iterator<String> taskIdIterator = taskIds.iterator();
while (taskIdIterator.hasNext()) {
String currentTaskId = taskIdIterator.next();
if (currentTaskId == null || currentTaskId.isEmpty()) {
bulkLog.addError("",
new InvalidArgumentException("IDs with EMPTY or NULL value are not allowed and invalid."));
taskIdIterator.remove();
}
}
// query for existing tasks, modify values and LOG missing ones.
List<TaskSummary> taskSummaries = this.createTaskQuery().idIn(taskIds.toArray(new String[0])).list();
Instant now = Instant.now();
taskIdIterator = taskIds.iterator();
while (taskIdIterator.hasNext()) {
String currentTaskId = taskIdIterator.next();
TaskSummaryImpl taskSummary = (TaskSummaryImpl) taskSummaries.stream()
.filter(ts -> currentTaskId.equals(ts.getTaskId()))
.findFirst()
.orElse(null);
if (taskSummary == null) {
bulkLog.addError(currentTaskId, new TaskNotFoundException(currentTaskId));
taskIdIterator.remove();
} else if (taskSummary.getClaimed() == null || taskSummary.getState() != TaskState.CLAIMED) {
bulkLog.addError(currentTaskId, new InvalidStateException(currentTaskId));
taskIdIterator.remove();
} else if (!CurrentUserContext.getAccessIds().contains(taskSummary.getOwner())) {
bulkLog.addError(currentTaskId, new InvalidOwnerException(
"TaskOwner is" + taskSummary.getOwner() + ", but current User is "
+ CurrentUserContext.getUserid()));
taskIdIterator.remove();
} else {
taskSummary.setCompleted(now);
taskSummary.setModified(now);
taskSummary.setState(TaskState.COMPLETED);
}
}
if (!taskIds.isEmpty() && !taskSummaries.isEmpty()) {
taskMapper.updateCompleted(taskIds, (TaskSummaryImpl) taskSummaries.get(0));
}
}
return bulkLog;
} finally {
taskanaEngineImpl.returnConnection();
LOGGER.debug("exit from to completeTasks(taskIds = {})", taskIds);
}
}
@Override
public Task createTask(Task taskToCreate)
throws NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException,
@ -325,7 +392,7 @@ public class TaskServiceImpl implements TaskService {
}
@Override
public BulkOperationResults<String, TaskanaException> transferBulk(String destinationWorkbasketKey,
public BulkOperationResults<String, TaskanaException> transferTasks(String destinationWorkbasketKey,
List<String> taskIds) throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException {
try {
taskanaEngineImpl.openConnection();
@ -837,12 +904,16 @@ public class TaskServiceImpl implements TaskService {
}
@Override
public BulkOperationResults<String, TaskanaException> deleteTasks(List<String> taskIds) {
public BulkOperationResults<String, TaskanaException> deleteTasks(List<String> taskIds)
throws InvalidArgumentException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("entry to deleteTasks(tasks = {})", LoggerUtils.listToString(taskIds));
}
try {
taskanaEngineImpl.openConnection();
if (taskIds == null) {
throw new InvalidArgumentException("TaskIds can´t be NULL as parameter for deleteTasks().");
}
BulkOperationResults<String, TaskanaException> bulkLog = new BulkOperationResults<>();
List<MinimalTaskSummary> taskSummaries = taskMapper.findExistingTasks(taskIds);
@ -870,7 +941,9 @@ public class TaskServiceImpl implements TaskService {
}
}
}
taskMapper.deleteMultiple(taskIds);
if (!taskIds.isEmpty()) {
taskMapper.deleteMultiple(taskIds);
}
return bulkLog;
} finally {
LOGGER.debug("exit from deleteTasks()");

View File

@ -183,6 +183,13 @@ public interface TaskMapper {
void updateTransfered(@Param("taskIds") List<String> taskIds,
@Param("referencetask") TaskSummaryImpl referencetask);
@Update("<script>"
+ " UPDATE TASK SET COMPLETED = #{referencetask.completed}, MODIFIED = #{referencetask.modified}, STATE = #{referencetask.state}"
+ " WHERE ID IN <foreach item='taskId' index='index' separator=',' open='(' close=')' collection='taskIds'>#{taskId}</foreach>"
+ "</script>")
void updateCompleted(@Param("taskIds") List<String> taskIds,
@Param("referencetask") TaskSummaryImpl referencetask);
@Select("<script>SELECT ID, STATE, WORKBASKET_KEY FROM TASK "
+ "WHERE ID IN(<foreach item='item' collection='taskIds' separator=',' >#{item}</foreach>) "
+ "</script>")

View File

@ -16,6 +16,7 @@ import org.junit.runner.RunWith;
import acceptance.AbstractAccTest;
import pro.taskana.Task;
import pro.taskana.TaskService;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.exceptions.InvalidStateException;
import pro.taskana.exceptions.TaskNotFoundException;
import pro.taskana.exceptions.TaskanaException;
@ -80,7 +81,7 @@ public class DeleteTaskAccTest extends AbstractAccTest {
userName = "user_1_2",
groupNames = {"group_1"})
@Test(expected = TaskNotFoundException.class)
public void testBulkDeleteTask() throws TaskNotFoundException {
public void testBulkDeleteTask() throws TaskNotFoundException, InvalidArgumentException {
TaskService taskService = taskanaEngine.getTaskService();
ArrayList<String> taskIdList = new ArrayList<>();
@ -97,7 +98,7 @@ public class DeleteTaskAccTest extends AbstractAccTest {
userName = "user_1_2",
groupNames = {"group_1"})
@Test(expected = TaskNotFoundException.class)
public void testBulkDeleteTasksWithException() throws TaskNotFoundException {
public void testBulkDeleteTasksWithException() throws TaskNotFoundException, InvalidArgumentException {
TaskService taskService = taskanaEngine.getTaskService();
ArrayList<String> taskIdList = new ArrayList<>();

View File

@ -126,7 +126,7 @@ public class TransferTaskAccTest extends AbstractAccTest {
taskIdList.add("TKI:000000000000000000000000000000000004");
taskIdList.add("TKI:000000000000000000000000000000000005");
BulkOperationResults<String, TaskanaException> results = taskService.transferBulk("USER_1_1", taskIdList);
BulkOperationResults<String, TaskanaException> results = taskService.transferTasks("USER_1_1", taskIdList);
assertFalse(results.containsErrors());
Workbasket wb = taskanaEngine.getWorkbasketService().getWorkbasketByKey("USER_1_1");
@ -166,7 +166,7 @@ public class TransferTaskAccTest extends AbstractAccTest {
taskIdList.add(null); // InvalidArgument (added with ""), duplicate
taskIdList.add("TKI:000000000000000000000000000000000099"); // TaskNotFound
BulkOperationResults<String, TaskanaException> results = taskService.transferBulk("USER_1_1", taskIdList);
BulkOperationResults<String, TaskanaException> results = taskService.transferTasks("USER_1_1", taskIdList);
assertTrue(results.containsErrors());
assertThat(results.getErrorMap().values().size(), equalTo(3));
// react to result

View File

@ -1,19 +1,22 @@
package acceptance.task;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.sql.SQLException;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import org.h2.store.fs.FileUtils;
import org.junit.AfterClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -30,7 +33,9 @@ import pro.taskana.exceptions.InvalidWorkbasketException;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.exceptions.TaskAlreadyExistException;
import pro.taskana.exceptions.TaskNotFoundException;
import pro.taskana.exceptions.TaskanaException;
import pro.taskana.exceptions.WorkbasketNotFoundException;
import pro.taskana.impl.BulkOperationResults;
import pro.taskana.model.TaskState;
import pro.taskana.security.JAASRunner;
import pro.taskana.security.WithAccessId;
@ -227,7 +232,6 @@ public class WorkOnTaskAccTest extends AbstractAccTest {
taskService.completeTask(claimedTask.getId());
}
@Ignore
@WithAccessId(
userName = "user_1_2",
groupNames = {"group_1"})
@ -250,24 +254,23 @@ public class WorkOnTaskAccTest extends AbstractAccTest {
assertEquals("user_1_2", completedTask.getOwner());
}
@Ignore
@WithAccessId(
userName = "user_1_2",
groupNames = {"group_1"})
@Test(expected = TaskNotFoundException.class)
@Test
public void testBulkCompleteTasks()
throws SQLException, NotAuthorizedException, InvalidArgumentException, ClassificationNotFoundException,
WorkbasketNotFoundException, TaskAlreadyExistException, InvalidWorkbasketException, TaskNotFoundException,
ConcurrencyException, AttachmentPersistenceException {
TaskService taskService = taskanaEngine.getTaskService();
ArrayList<String> taskIdList = new ArrayList<>();
List<String> taskIdList = new ArrayList<>();
taskIdList.add("TKI:000000000000000000000000000000000100");
taskIdList.add("TKI:000000000000000000000000000000000101");
// BulkOperationResults results = taskService.completeTasks(taskIdList);
BulkOperationResults<String, TaskanaException> results = taskService.completeTasks(taskIdList);
// assertFalse(results.containsError());
assertFalse(results.containsErrors());
Task completedTask1 = taskService.getTask("TKI:000000000000000000000000000000000100");
assertEquals(TaskState.COMPLETED, completedTask1.getState());
assertNotNull(completedTask1.getCompleted());
@ -276,33 +279,26 @@ public class WorkOnTaskAccTest extends AbstractAccTest {
assertNotNull(completedTask2.getCompleted());
}
@Ignore
@WithAccessId(
userName = "user_1_2",
groupNames = {"group_1"})
@Test(expected = TaskNotFoundException.class)
@Test
public void testBulkDeleteTasksWithException()
throws SQLException, NotAuthorizedException, InvalidArgumentException, ClassificationNotFoundException,
WorkbasketNotFoundException, TaskAlreadyExistException, InvalidWorkbasketException, TaskNotFoundException,
ConcurrencyException, AttachmentPersistenceException {
TaskService taskService = taskanaEngine.getTaskService();
ArrayList<String> taskIdList = new ArrayList<>();
List<String> taskIdList = new ArrayList<>();
taskIdList.add("TKI:000000000000000000000000000000000102");
taskIdList.add("TKI:000000000000000000000000000000000103");
taskIdList.add("TKI:000000000000000000000000000000000033");
taskIdList.add("TKI:000000000000000000000000000000003333");
// BulkOperationResults results = taskService.deleteTasks(taskIdList);
BulkOperationResults<String, TaskanaException> results = taskService.deleteTasks(taskIdList);
// assertTrue(results.containsError());
// more assertions ...
// assert exception is invalidstateexception
Task completedTask1 = taskService.getTask("TKI:000000000000000000000000000000000102");
assertEquals(TaskState.COMPLETED, completedTask1.getState());
assertNotNull(completedTask1.getCompleted());
Task completedTask2 = taskService.getTask("TKI:000000000000000000000000000000000103");
assertEquals(TaskState.COMPLETED, completedTask2.getState());
assertNotNull(completedTask2.getCompleted());
assertTrue(results.containsErrors());
assertThat(results.getErrorMap().size(), equalTo(2));
assertTrue(results.getErrorForId("TKI:000000000000000000000000000000003333") instanceof TaskNotFoundException);
assertTrue(results.getErrorForId("TKI:000000000000000000000000000000000102") instanceof InvalidStateException);
}
@AfterClass