diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/MinimalTaskSummary.java b/lib/taskana-core/src/main/java/pro/taskana/impl/MinimalTaskSummary.java index abd35b524..ce6aa7c62 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/MinimalTaskSummary.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/MinimalTaskSummary.java @@ -8,7 +8,7 @@ import pro.taskana.TaskState; public class MinimalTaskSummary { private String taskId; - private String workbasketKey; + private String workbasketId; private TaskState taskState; MinimalTaskSummary() { @@ -23,12 +23,12 @@ public class MinimalTaskSummary { this.taskId = taskId; } - public String getWorkbasketKey() { - return workbasketKey; + public String getWorkbasketId() { + return workbasketId; } - public void setWorkbasketKey(String workbasketKey) { - this.workbasketKey = workbasketKey; + public void setWorkbasketId(String workbasketKey) { + this.workbasketId = workbasketKey; } public TaskState getTaskState() { @@ -44,8 +44,8 @@ public class MinimalTaskSummary { StringBuilder builder = new StringBuilder(); builder.append("MinimalTaskSummary [taskId="); builder.append(taskId); - builder.append(", workbasketKey="); - builder.append(workbasketKey); + builder.append(", workbasketId="); + builder.append(workbasketId); builder.append(", taskState="); builder.append(taskState); builder.append("]"); diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskCountPerWorkbasket.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskCountPerWorkbasket.java new file mode 100644 index 000000000..674346d69 --- /dev/null +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskCountPerWorkbasket.java @@ -0,0 +1,29 @@ +package pro.taskana.impl; + +/** + * This class keeps a count of tasks that are contained in a workbasket. + * + * @author bbr + */ +public class TaskCountPerWorkbasket { + + Integer taskCount; + String workbasketId; + + public Integer getTaskCount() { + return taskCount; + } + + public void setTaskCount(Integer taskCount) { + this.taskCount = taskCount; + } + + public String getWorkbasketId() { + return workbasketId; + } + + public void setWorkbasketId(String workbasketId) { + this.workbasketId = workbasketId; + } + +} diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskQueryImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskQueryImpl.java index 7ada8e3f2..b6bd78b3e 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskQueryImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskQueryImpl.java @@ -3,6 +3,8 @@ package pro.taskana.impl; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import org.apache.ibatis.exceptions.PersistenceException; import org.apache.ibatis.session.RowBounds; @@ -18,6 +20,7 @@ import pro.taskana.TaskanaEngine; import pro.taskana.TaskanaRole; import pro.taskana.TimeInterval; import pro.taskana.WorkbasketPermission; +import pro.taskana.WorkbasketSummary; import pro.taskana.exceptions.InvalidArgumentException; import pro.taskana.exceptions.NotAuthorizedException; import pro.taskana.exceptions.NotAuthorizedToQueryWorkbasketException; @@ -31,7 +34,7 @@ import pro.taskana.impl.util.LoggerUtils; public class TaskQueryImpl implements TaskQuery { private static final String LINK_TO_MAPPER = "pro.taskana.mappings.QueryMapper.queryTaskSummaries"; - private static final String LINK_TO_COUNTER = "pro.taskana.mappings.QueryMapper.countQueryTasks"; + private static final String LINK_TO_TASK_COUNT_PER_WORKBASKET = "pro.taskana.mappings.QueryMapper.queryTaskCountPerWorkbasket"; private static final String LINK_TO_VALUEMAPPER = "pro.taskana.mappings.QueryMapper.queryTaskColumnValues"; private static final String TIME_INTERVAL = "TimeInterval "; private static final String IS_INVALID = " is invalid."; @@ -804,14 +807,36 @@ public class TaskQueryImpl implements TaskQuery { try { taskanaEngine.openConnection(); checkOpenPermissionForSpecifiedWorkbaskets(); - rowCount = taskanaEngine.getSqlSession().selectOne(LINK_TO_COUNTER, this); - return (rowCount == null) ? 0L : rowCount; + List taskCounts = taskanaEngine.getSqlSession() + .selectList(LINK_TO_TASK_COUNT_PER_WORKBASKET, this); + return countTasksInAuthorizedWorkbaskets(taskCounts); } finally { taskanaEngine.returnConnection(); LOGGER.debug("exit from count(). Returning result {} ", rowCount); } } + private long countTasksInAuthorizedWorkbaskets(List taskCounts) { + Set retrievedWorkbasketIds = taskCounts.stream().map(TaskCountPerWorkbasket::getWorkbasketId).collect( + Collectors.toSet()); + // use WorkbasketQuery to filter for authorized WorkBaskets + WorkbasketQueryImpl query = (WorkbasketQueryImpl) taskanaEngine.getWorkbasketService().createWorkbasketQuery(); + query.setUsedToAugmentTasks(true); + List allowedWorkbaskets = query + .idIn(retrievedWorkbasketIds.toArray(new String[0])) + .list(); + Set authorizedWorkbasketIds = allowedWorkbaskets.stream().map(WorkbasketSummary::getId).collect( + Collectors.toSet()); + + long count = 0; + for (TaskCountPerWorkbasket taskCount : taskCounts) { + if (authorizedWorkbasketIds.contains(taskCount.getWorkbasketId())) { + count += taskCount.getTaskCount().intValue(); + } + } + return count; + } + private void checkOpenPermissionForSpecifiedWorkbaskets() { if (taskanaEngine.isUserInRole(TaskanaRole.ADMIN)) { LOGGER.debug("Skipping permissions check since user is in role ADMIN."); diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java index e32843865..5ba03bede 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java @@ -538,13 +538,13 @@ public class TaskServiceImpl implements TaskService { List taskSummaries = taskMapper.findExistingTasks(taskIds); // check source WB (read)+transfer - Set workbasketKeys = new HashSet<>(); - taskSummaries.stream().forEach(t -> workbasketKeys.add(t.getWorkbasketKey())); + Set workbasketIds = new HashSet<>(); + taskSummaries.stream().forEach(t -> workbasketIds.add(t.getWorkbasketId())); WorkbasketQueryImpl query = (WorkbasketQueryImpl) workbasketService.createWorkbasketQuery(); query.setUsedToAugmentTasks(true); List sourceWorkbaskets = query .callerHasPermission(WorkbasketPermission.TRANSFER) - .keyIn(workbasketKeys.toArray(new String[0])) + .idIn(workbasketIds.toArray(new String[0])) .list(); taskIdIterator = taskIds.iterator(); while (taskIdIterator.hasNext()) { @@ -558,7 +558,7 @@ public class TaskServiceImpl implements TaskService { new TaskNotFoundException(currentTaskId, "Task with id " + currentTaskId + " was not found.")); taskIdIterator.remove(); } else if (!sourceWorkbaskets.stream() - .anyMatch(wb -> taskSummary.getWorkbasketKey().equals(wb.getKey()))) { + .anyMatch(wb -> taskSummary.getWorkbasketId().equals(wb.getId()))) { bulkLog.addError(currentTaskId, new NotAuthorizedException( "The workbasket of this task got not TRANSFER permissions. TaskId=" + currentTaskId)); diff --git a/lib/taskana-core/src/main/java/pro/taskana/mappings/QueryMapper.java b/lib/taskana-core/src/main/java/pro/taskana/mappings/QueryMapper.java index 01b847522..5581971f0 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/mappings/QueryMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/mappings/QueryMapper.java @@ -10,6 +10,7 @@ import pro.taskana.impl.ClassificationQueryImpl; import pro.taskana.impl.ClassificationSummaryImpl; import pro.taskana.impl.ObjectReference; import pro.taskana.impl.ObjectReferenceQueryImpl; +import pro.taskana.impl.TaskCountPerWorkbasket; import pro.taskana.impl.TaskQueryImpl; import pro.taskana.impl.TaskSummaryImpl; import pro.taskana.impl.WorkbasketAccessItemImpl; @@ -347,7 +348,7 @@ public interface QueryMapper { @Result(property = "permCustom12", column = "PERM_CUSTOM_12")}) List queryWorkbasketAccessItems(WorkbasketAccessItemQueryImpl accessItemQuery); - @Select("") - Long countQueryTasks(TaskQueryImpl taskQuery); + @Results(value = { + @Result(property = "taskCount", column = "TASK_COUNT"), + @Result(property = "workbasketId", column = "WORKBASKET_ID")}) + List queryTaskCountPerWorkbasket(TaskQueryImpl taskQuery); @Select("") @Results(value = { @Result(property = "taskId", column = "ID"), - @Result(property = "workbasketKey", column = "WORKBASKET_KEY"), + @Result(property = "workbasketId", column = "WORKBASKET_ID"), @Result(property = "taskState", column = "STATE")}) List findExistingTasks(@Param("taskIds") List taskIds); diff --git a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksAccTest.java index 59cb14e8e..80e3dc6b2 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/QueryTasksAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/QueryTasksAccTest.java @@ -24,6 +24,7 @@ import pro.taskana.AttachmentSummary; import pro.taskana.BaseQuery.SortDirection; import pro.taskana.KeyDomain; import pro.taskana.Task; +import pro.taskana.TaskQuery; import pro.taskana.TaskService; import pro.taskana.TaskSummary; import pro.taskana.exceptions.AttachmentPersistenceException; @@ -604,4 +605,21 @@ public class QueryTasksAccTest extends AbstractAccTest { } } + @WithAccessId( + userName = "user_1_1", + groupNames = {"group_1"}) + @Test + public void testQueryAndCountMatch() { + TaskService taskService = taskanaEngine.getTaskService(); + TaskQuery taskQuery = taskService.createTaskQuery(); + List tasks = taskQuery + .nameIn("Task99", "Task01", "Widerruf") + .list(); + long numberOfTasks = taskQuery + .nameIn("Task99", "Task01", "Widerruf") + .count(); + Assert.assertEquals(numberOfTasks, tasks.size()); + + } + }