diff --git a/lib/taskana-core/src/main/java/pro/taskana/TaskMonitorService.java b/lib/taskana-core/src/main/java/pro/taskana/TaskMonitorService.java index 922d39088..5332713f2 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/TaskMonitorService.java +++ b/lib/taskana-core/src/main/java/pro/taskana/TaskMonitorService.java @@ -1,51 +1,64 @@ -package pro.taskana; - -import java.util.List; - -import pro.taskana.model.DueWorkbasketCounter; -import pro.taskana.model.TaskState; -import pro.taskana.model.TaskStateCounter; - -/** - * The Task Monitor Service manages operations on tasks regarding the monitoring. - */ -public interface TaskMonitorService { - - /** - * This method counts all tasks with a given state. - * - * @param states - * the countable states - * @return a List of {@link TaskStateCounter} objects that specifies how many tasks in the specified states exist in - * the available work baskets - */ - List getTaskCountForState(List states); - - /** - * Count all Tasks in a given work basket where the due date is after "daysInPast" days from today in the past and - * the tasks are in specified states. - * - * @param workbasketId - * the id of the work basket - * @param daysInPast - * identifies the days in the past from today - * @param states - * {@link List} of {@link TaskState} that identifies the states of the tasks to be searched for - * @return the number of Task objects in the given work basket that match the query parameters - */ - long getTaskCountForWorkbasketByDaysInPastAndState(String workbasketId, long daysInPast, List states); - - /** - * Count all Tasks for all work basket objects where the due date is after "daysInPast" days from today in the past - * and the tasks are in specified states. - * - * @param daysInPast - * identifies the days in the past from today - * @param states - * {@link List} of {@link TaskState} objects that identifies the states of the tasks searched - * @return a list of of {@link DueWorkbasketCounter} objects that specifies how many tasks in the requested states - * with appropriate due date exist in the various work baskets - */ - List getTaskCountByWorkbasketAndDaysInPastAndState(long daysInPast, List states); - -} +package pro.taskana; + +import java.util.List; + +import pro.taskana.model.DueWorkbasketCounter; +import pro.taskana.model.Report; +import pro.taskana.model.TaskState; +import pro.taskana.model.TaskStateCounter; + +/** + * The Task Monitor Service manages operations on tasks regarding the monitoring. + */ +public interface TaskMonitorService { + + /** + * This method counts all tasks with a given state. + * + * @param states + * the countable states + * @return a List of {@link TaskStateCounter} objects that specifies how many tasks in the specified states exist in + * the available work baskets + */ + List getTaskCountForState(List states); + + /** + * Count all Tasks in a given work basket where the due date is after "daysInPast" days from today in the past and + * the tasks are in specified states. + * + * @param workbasketId + * the id of the work basket + * @param daysInPast + * identifies the days in the past from today + * @param states + * {@link List} of {@link TaskState} that identifies the states of the tasks to be searched for + * @return the number of Task objects in the given work basket that match the query parameters + */ + long getTaskCountForWorkbasketByDaysInPastAndState(String workbasketId, long daysInPast, List states); + + /** + * Count all Tasks for all work basket objects where the due date is after "daysInPast" days from today in the past + * and the tasks are in specified states. + * + * @param daysInPast + * identifies the days in the past from today + * @param states + * {@link List} of {@link TaskState} objects that identifies the states of the tasks searched + * @return a list of of {@link DueWorkbasketCounter} objects that specifies how many tasks in the requested states + * with appropriate due date exist in the various work baskets + */ + List getTaskCountByWorkbasketAndDaysInPastAndState(long daysInPast, List states); + + /** + * Returns a {@link Report} for a given list of {@link Workbasket} objects and for a given list of {@link TaskState} + * objects. + * + * @param workbaskets + * a list of {@link Workbasket} objects + * @param states + * a list of {@link TaskState} objects + * @return a {@link Report} object + */ + Report getWorkbasketLevelReport(List workbaskets, List states); + +} diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskMonitorServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskMonitorServiceImpl.java index 5d06cd2d5..59868252d 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskMonitorServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskMonitorServiceImpl.java @@ -1,103 +1,131 @@ -package pro.taskana.impl; - -import java.sql.Date; -import java.time.LocalDate; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import pro.taskana.TaskMonitorService; -import pro.taskana.TaskanaEngine; -import pro.taskana.impl.util.LoggerUtils; -import pro.taskana.model.DueWorkbasketCounter; -import pro.taskana.model.TaskState; -import pro.taskana.model.TaskStateCounter; -import pro.taskana.model.mappings.TaskMonitorMapper; - -/** - * This is the implementation of TaskMonitorService. - */ -public class TaskMonitorServiceImpl implements TaskMonitorService { - - private static final Logger LOGGER = LoggerFactory.getLogger(TaskMonitorServiceImpl.class); - - private TaskanaEngineImpl taskanaEngineImpl; - - private TaskMonitorMapper taskMonitorMapper; - - public TaskMonitorServiceImpl(TaskanaEngine taskanaEngine, TaskMonitorMapper taskMonitorMapper) { - super(); - this.taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; - this.taskMonitorMapper = taskMonitorMapper; - } - - @Override - public List getTaskCountForState(List states) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("entry to getTaskCountForState(states = {})", LoggerUtils.listToString(states)); - } - List result = null; - try { - taskanaEngineImpl.openConnection(); - result = taskMonitorMapper.getTaskCountForState(states); - return result; - } finally { - taskanaEngineImpl.returnConnection(); - if (LOGGER.isDebugEnabled()) { - int numberOfResultObjects = result == null ? 0 : result.size(); - LOGGER.debug("exit from getTaskCountForState(). Returning {} resulting Objects: {} ", - numberOfResultObjects, LoggerUtils.listToString(result)); - } - } - } - - @Override - public long getTaskCountForWorkbasketByDaysInPastAndState(String workbasketId, long daysInPast, - List states) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug( - "entry to getTaskCountForWorkbasketByDaysInPastAndState(workbasketId {}, daysInPast={}, states = {})", - workbasketId, daysInPast, LoggerUtils.listToString(states)); - } - long result = -1; - try { - taskanaEngineImpl.openConnection(); - LocalDate time = LocalDate.now(); - time = time.minusDays(daysInPast); - Date fromDate = Date.valueOf(time); - result = taskMonitorMapper.getTaskCountForWorkbasketByDaysInPastAndState(workbasketId, fromDate, states); - return result; - } finally { - taskanaEngineImpl.returnConnection(); - LOGGER.debug("exit from getTaskCountForWorkbasketByDaysInPastAndState(). Returning result {} ", result); - } - } - - @Override - public List getTaskCountByWorkbasketAndDaysInPastAndState(long daysInPast, - List states) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("entry to getTaskCountByWorkbasketAndDaysInPastAndState(daysInPast = {}, states = {})", - daysInPast, LoggerUtils.listToString(states)); - } - List result = null; - try { - taskanaEngineImpl.openConnection(); - LocalDate time = LocalDate.now(); - time = time.minusDays(daysInPast); - Date fromDate = Date.valueOf(time); - result = taskMonitorMapper.getTaskCountByWorkbasketIdAndDaysInPastAndState(fromDate, states); - return result; - } finally { - taskanaEngineImpl.returnConnection(); - if (LOGGER.isDebugEnabled()) { - int numberOfResultObjects = result == null ? 0 : result.size(); - LOGGER.debug( - "exit from getTaskCountByWorkbasketAndDaysInPastAndState(daysInPast,states). Returning {} resulting Objects: {} ", - numberOfResultObjects, LoggerUtils.listToString(result)); - } - } - } - -} +package pro.taskana.impl; + +import java.sql.Date; +import java.time.LocalDate; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import pro.taskana.TaskMonitorService; +import pro.taskana.TaskanaEngine; +import pro.taskana.Workbasket; +import pro.taskana.impl.util.LoggerUtils; +import pro.taskana.model.DueWorkbasketCounter; +import pro.taskana.model.Report; +import pro.taskana.model.ReportLine; +import pro.taskana.model.TaskState; +import pro.taskana.model.TaskStateCounter; +import pro.taskana.model.mappings.TaskMonitorMapper; + +/** + * This is the implementation of TaskMonitorService. + */ +public class TaskMonitorServiceImpl implements TaskMonitorService { + + private static final Logger LOGGER = LoggerFactory.getLogger(TaskMonitorServiceImpl.class); + private TaskanaEngineImpl taskanaEngineImpl; + private TaskMonitorMapper taskMonitorMapper; + + public TaskMonitorServiceImpl(TaskanaEngine taskanaEngine, TaskMonitorMapper taskMonitorMapper) { + super(); + this.taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; + this.taskMonitorMapper = taskMonitorMapper; + } + + @Override + public List getTaskCountForState(List states) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("entry to getTaskCountForState(states = {})", LoggerUtils.listToString(states)); + } + List result = null; + try { + taskanaEngineImpl.openConnection(); + result = taskMonitorMapper.getTaskCountForState(states); + return result; + } finally { + taskanaEngineImpl.returnConnection(); + if (LOGGER.isDebugEnabled()) { + int numberOfResultObjects = result == null ? 0 : result.size(); + LOGGER.debug("exit from getTaskCountForState(). Returning {} resulting Objects: {} ", + numberOfResultObjects, LoggerUtils.listToString(result)); + } + } + } + + @Override + public long getTaskCountForWorkbasketByDaysInPastAndState(String workbasketId, long daysInPast, + List states) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug( + "entry to getTaskCountForWorkbasketByDaysInPastAndState(workbasketId {}, daysInPast={}, states = {})", + workbasketId, daysInPast, LoggerUtils.listToString(states)); + } + long result = -1; + try { + taskanaEngineImpl.openConnection(); + LocalDate time = LocalDate.now(); + time = time.minusDays(daysInPast); + Date fromDate = Date.valueOf(time); + result = taskMonitorMapper.getTaskCountForWorkbasketByDaysInPastAndState(workbasketId, fromDate, states); + return result; + } finally { + taskanaEngineImpl.returnConnection(); + LOGGER.debug("exit from getTaskCountForWorkbasketByDaysInPastAndState(). Returning result {} ", result); + } + } + + @Override + public List getTaskCountByWorkbasketAndDaysInPastAndState(long daysInPast, + List states) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("entry to getTaskCountByWorkbasketAndDaysInPastAndState(daysInPast = {}, states = {})", + daysInPast, LoggerUtils.listToString(states)); + } + List result = null; + try { + taskanaEngineImpl.openConnection(); + LocalDate time = LocalDate.now(); + time = time.minusDays(daysInPast); + Date fromDate = Date.valueOf(time); + result = taskMonitorMapper.getTaskCountByWorkbasketIdAndDaysInPastAndState(fromDate, states); + return result; + } finally { + taskanaEngineImpl.returnConnection(); + if (LOGGER.isDebugEnabled()) { + int numberOfResultObjects = result == null ? 0 : result.size(); + LOGGER.debug( + "exit from getTaskCountByWorkbasketAndDaysInPastAndState(daysInPast,states). Returning {} resulting Objects: {} ", + numberOfResultObjects, LoggerUtils.listToString(result)); + } + } + } + + @Override + public Report getWorkbasketLevelReport(List workbaskets, List states) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("entry to getWorkbasketLevelReport(workbaskets = {})", LoggerUtils.listToString(workbaskets)); + } + try { + taskanaEngineImpl.openConnection(); + Report report = new Report(); + report.setDetailLines(taskMonitorMapper.getDetailLinesByWorkbasketIdsAndStates(workbaskets, states)); + int sumLineTotalCount = 0; + for (ReportLine reportLine : report.getDetailLines()) { + sumLineTotalCount += reportLine.getTotalCount(); + } + ReportLine sumLine = new ReportLine(); + sumLine.setName("SumLine"); + sumLine.setTotalCount(sumLineTotalCount); + report.setSumLine(sumLine); + return report; + + } finally { + taskanaEngineImpl.returnConnection(); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("exit from getTaskCountByWorkbaskets()."); + } + } + } + +} diff --git a/lib/taskana-core/src/main/java/pro/taskana/model/Report.java b/lib/taskana-core/src/main/java/pro/taskana/model/Report.java new file mode 100644 index 000000000..356cea774 --- /dev/null +++ b/lib/taskana-core/src/main/java/pro/taskana/model/Report.java @@ -0,0 +1,35 @@ +package pro.taskana.model; + +import java.util.ArrayList; +import java.util.List; + +/** + * A Report represents a table that consists of {@link ReportLine} objects. + */ +public class Report { + + private List detailLines; + private ReportLine sumLine; + + public Report() { + this.detailLines = new ArrayList<>(); + this.sumLine = new ReportLine(); + } + + public List getDetailLines() { + return detailLines; + } + + public void setDetailLines(List detailLines) { + this.detailLines = detailLines; + } + + public ReportLine getSumLine() { + return sumLine; + } + + public void setSumLine(ReportLine sumLine) { + this.sumLine = sumLine; + } + +} diff --git a/lib/taskana-core/src/main/java/pro/taskana/model/ReportLine.java b/lib/taskana-core/src/main/java/pro/taskana/model/ReportLine.java new file mode 100644 index 000000000..509df5846 --- /dev/null +++ b/lib/taskana-core/src/main/java/pro/taskana/model/ReportLine.java @@ -0,0 +1,44 @@ +package pro.taskana.model; + +import java.util.ArrayList; +import java.util.List; + +/** + * Each ReportLine consists of a name, a list of {@link ReportLineItem} objects and a totalCount that represents the + * count of all tasks. + */ +public class ReportLine { + + private String name; + private List lineItems; + private int totalCount; + + public ReportLine() { + this.lineItems = new ArrayList<>(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getLineItems() { + return lineItems; + } + + public void setLineItems(List lineItems) { + this.lineItems = lineItems; + } + + public int getTotalCount() { + return totalCount; + } + + public void setTotalCount(int totalCount) { + this.totalCount = totalCount; + } + +} diff --git a/lib/taskana-core/src/main/java/pro/taskana/model/ReportLineItem.java b/lib/taskana-core/src/main/java/pro/taskana/model/ReportLineItem.java new file mode 100644 index 000000000..038da8fc0 --- /dev/null +++ b/lib/taskana-core/src/main/java/pro/taskana/model/ReportLineItem.java @@ -0,0 +1,28 @@ +package pro.taskana.model; + +/** + * Each ReportLineItem consists of a {@link ReportLineItemDefinition} that defines the upper and lower limits of this + * item and a count value that represents the count of tasks of this item. + */ +public class ReportLineItem { + + private ReportLineItemDefinition reportLineItemDefinition; + private int count; + + public ReportLineItemDefinition getReportLineItemDefinition() { + return reportLineItemDefinition; + } + + public void setReportLineItemDefinition(ReportLineItemDefinition reportLineItemDefinition) { + this.reportLineItemDefinition = reportLineItemDefinition; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + +} diff --git a/lib/taskana-core/src/main/java/pro/taskana/model/ReportLineItemDefinition.java b/lib/taskana-core/src/main/java/pro/taskana/model/ReportLineItemDefinition.java new file mode 100644 index 000000000..a314fb0f5 --- /dev/null +++ b/lib/taskana-core/src/main/java/pro/taskana/model/ReportLineItemDefinition.java @@ -0,0 +1,28 @@ +package pro.taskana.model; + +/** + * A ReportLineItemDefinition has a lower and an upper limit which subdivide the count of tasks in a workbasket into + * different sections. + */ +public class ReportLineItemDefinition { + + private int lowerLimit; + private int upperLimit; + + public int getLowerLimit() { + return lowerLimit; + } + + public void setLowerLimit(int lowerLimit) { + this.lowerLimit = lowerLimit; + } + + public int getUpperLimit() { + return upperLimit; + } + + public void setUpperLimit(int upperLimit) { + this.upperLimit = upperLimit; + } + +} diff --git a/lib/taskana-core/src/main/java/pro/taskana/model/mappings/TaskMonitorMapper.java b/lib/taskana-core/src/main/java/pro/taskana/model/mappings/TaskMonitorMapper.java index 61bab7d24..1e42b8c04 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/model/mappings/TaskMonitorMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/model/mappings/TaskMonitorMapper.java @@ -1,52 +1,66 @@ -package pro.taskana.model.mappings; - -import java.sql.Date; -import java.util.List; - -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Result; -import org.apache.ibatis.annotations.Results; -import org.apache.ibatis.annotations.Select; - -import pro.taskana.model.DueWorkbasketCounter; -import pro.taskana.model.TaskState; -import pro.taskana.model.TaskStateCounter; - -/** - * This class is the mybatis mapping of task monitoring. - */ -public interface TaskMonitorMapper { - - @Select("") - @Results({ @Result(column = "STATE", property = "state"), @Result(column = "counter", property = "counter") }) - List getTaskCountForState(@Param("status") List status); - - @Select("") - long getTaskCountForWorkbasketByDaysInPastAndState(@Param("workbasketId") String workbasketId, - @Param("fromDate") Date fromDate, @Param("status") List states); - - @Select("") - @Results({ @Result(column = "DUE_DATE", property = "due"), - @Result(column = "WORKBASKETID", property = "workbasketId"), - @Result(column = "counter", property = "taskCounter") }) - List getTaskCountByWorkbasketIdAndDaysInPastAndState(@Param("fromDate") Date fromDate, - @Param("status") List states); - -} +package pro.taskana.model.mappings; + +import java.sql.Date; +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Results; +import org.apache.ibatis.annotations.Select; + +import pro.taskana.Workbasket; +import pro.taskana.model.DueWorkbasketCounter; +import pro.taskana.model.ReportLine; +import pro.taskana.model.TaskState; +import pro.taskana.model.TaskStateCounter; + +/** + * This class is the mybatis mapping of task monitoring. + */ +public interface TaskMonitorMapper { + + @Select("") + @Results({ @Result(column = "STATE", property = "state"), @Result(column = "counter", property = "counter") }) + List getTaskCountForState(@Param("status") List status); + + @Select("") + long getTaskCountForWorkbasketByDaysInPastAndState(@Param("workbasketId") String workbasketId, + @Param("fromDate") Date fromDate, @Param("status") List states); + + @Select("") + @Results({ @Result(column = "DUE_DATE", property = "due"), + @Result(column = "WORKBASKETID", property = "workbasketId"), + @Result(column = "counter", property = "taskCounter") }) + List getTaskCountByWorkbasketIdAndDaysInPastAndState(@Param("fromDate") Date fromDate, + @Param("status") List states); + + @Select("") + @Results({ @Result(column = "WORKBASKET_KEY", property = "name"), + @Result(column = "counter", property = "totalCount") }) + List getDetailLinesByWorkbasketIdsAndStates(@Param("workbaskets") List workbaskets, + @Param("status") List states); + +} diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/TaskMonitorServiceImplTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/TaskMonitorServiceImplTest.java index 9432d2f45..51a901fad 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/TaskMonitorServiceImplTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/TaskMonitorServiceImplTest.java @@ -1,122 +1,146 @@ -package pro.taskana.impl; - -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -import java.sql.Date; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.mockito.junit.MockitoJUnitRunner; - -import pro.taskana.WorkbasketService; -import pro.taskana.configuration.TaskanaEngineConfiguration; -import pro.taskana.model.DueWorkbasketCounter; -import pro.taskana.model.TaskState; -import pro.taskana.model.TaskStateCounter; -import pro.taskana.model.mappings.ObjectReferenceMapper; -import pro.taskana.model.mappings.TaskMonitorMapper; - -/** - * Unit Test for TaskMonitorServiceImpl. - */ -@RunWith(MockitoJUnitRunner.class) -public class TaskMonitorServiceImplTest { - - @InjectMocks - private TaskMonitorServiceImpl cut; - - @Mock - private TaskanaEngineConfiguration taskanaEngineConfigurationMock; - - @Mock - private TaskanaEngineImpl taskanaEngineMock; - - @Mock - private TaskanaEngineImpl taskanaEngineImpl; - - @Mock - private TaskMonitorMapper taskMonitorMapperMock; - - @Mock - private ObjectReferenceMapper objectReferenceMapperMock; - - @Mock - private WorkbasketService workbasketServiceMock; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - Mockito.doNothing().when(taskanaEngineImpl).openConnection(); - Mockito.doNothing().when(taskanaEngineImpl).returnConnection(); - } - - @Test - public void testGetTaskCountForState() { - List taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED); - List expectedResult = new ArrayList<>(); - doReturn(expectedResult).when(taskMonitorMapperMock).getTaskCountForState(taskStates); - - List actualResult = cut.getTaskCountForState(taskStates); - - verify(taskanaEngineImpl, times(1)).openConnection(); - verify(taskMonitorMapperMock, times(1)).getTaskCountForState(taskStates); - verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl, - taskMonitorMapperMock, objectReferenceMapperMock, workbasketServiceMock); - assertThat(actualResult, equalTo(expectedResult)); - } - - @Test - public void testGetTaskCountForWorkbasketByDaysInPastAndState() { - List taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED); - final long daysInPast = 10L; - final long expectedResult = 5L; - String workbasketId = "1"; - doReturn(expectedResult).when(taskMonitorMapperMock).getTaskCountForWorkbasketByDaysInPastAndState(any(), any(), - any()); - - long actualResult = cut.getTaskCountForWorkbasketByDaysInPastAndState(workbasketId, daysInPast, taskStates); - - verify(taskanaEngineImpl, times(1)).openConnection(); - verify(taskMonitorMapperMock, times(1)).getTaskCountForWorkbasketByDaysInPastAndState(any(), any(), any()); - verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl, - taskMonitorMapperMock, objectReferenceMapperMock, workbasketServiceMock); - assertThat(actualResult, equalTo(expectedResult)); - } - - @Test - public void testGetTaskCountByWorkbasketAndDaysInPastAndState() { - final long daysInPast = 10L; - List taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED); - List expectedResult = new ArrayList<>(); - doReturn(expectedResult).when(taskMonitorMapperMock).getTaskCountByWorkbasketIdAndDaysInPastAndState( - any(Date.class), - any()); - - List actualResult = cut.getTaskCountByWorkbasketAndDaysInPastAndState(daysInPast, - taskStates); - - verify(taskanaEngineImpl, times(1)).openConnection(); - verify(taskMonitorMapperMock, times(1)).getTaskCountByWorkbasketIdAndDaysInPastAndState(any(Date.class), any()); - verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl, - taskMonitorMapperMock, objectReferenceMapperMock, workbasketServiceMock); - assertThat(actualResult, equalTo(expectedResult)); - } - -} +package pro.taskana.impl; + +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import java.sql.Date; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnitRunner; + +import pro.taskana.Workbasket; +import pro.taskana.WorkbasketService; +import pro.taskana.configuration.TaskanaEngineConfiguration; +import pro.taskana.model.DueWorkbasketCounter; +import pro.taskana.model.Report; +import pro.taskana.model.ReportLine; +import pro.taskana.model.TaskState; +import pro.taskana.model.TaskStateCounter; +import pro.taskana.model.mappings.ObjectReferenceMapper; +import pro.taskana.model.mappings.TaskMonitorMapper; + +/** + * Unit Test for TaskMonitorServiceImpl. + */ +@RunWith(MockitoJUnitRunner.class) +public class TaskMonitorServiceImplTest { + + @InjectMocks + private TaskMonitorServiceImpl cut; + + @Mock + private TaskanaEngineConfiguration taskanaEngineConfigurationMock; + + @Mock + private TaskanaEngineImpl taskanaEngineMock; + + @Mock + private TaskanaEngineImpl taskanaEngineImpl; + + @Mock + private TaskMonitorMapper taskMonitorMapperMock; + + @Mock + private ObjectReferenceMapper objectReferenceMapperMock; + + @Mock + private WorkbasketService workbasketServiceMock; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + Mockito.doNothing().when(taskanaEngineImpl).openConnection(); + Mockito.doNothing().when(taskanaEngineImpl).returnConnection(); + } + + @Test + public void testGetTaskCountForState() { + List taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED); + List expectedResult = new ArrayList<>(); + doReturn(expectedResult).when(taskMonitorMapperMock).getTaskCountForState(taskStates); + + List actualResult = cut.getTaskCountForState(taskStates); + + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(taskMonitorMapperMock, times(1)).getTaskCountForState(taskStates); + verify(taskanaEngineImpl, times(1)).returnConnection(); + verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl, + taskMonitorMapperMock, objectReferenceMapperMock, workbasketServiceMock); + assertThat(actualResult, equalTo(expectedResult)); + } + + @Test + public void testGetTaskCountForWorkbasketByDaysInPastAndState() { + List taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED); + final long daysInPast = 10L; + final long expectedResult = 5L; + String workbasketId = "1"; + doReturn(expectedResult).when(taskMonitorMapperMock).getTaskCountForWorkbasketByDaysInPastAndState(any(), any(), + any()); + + long actualResult = cut.getTaskCountForWorkbasketByDaysInPastAndState(workbasketId, daysInPast, taskStates); + + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(taskMonitorMapperMock, times(1)).getTaskCountForWorkbasketByDaysInPastAndState(any(), any(), any()); + verify(taskanaEngineImpl, times(1)).returnConnection(); + verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl, + taskMonitorMapperMock, objectReferenceMapperMock, workbasketServiceMock); + assertThat(actualResult, equalTo(expectedResult)); + } + + @Test + public void testGetTaskCountByWorkbasketAndDaysInPastAndState() { + final long daysInPast = 10L; + List taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED); + List expectedResult = new ArrayList<>(); + doReturn(expectedResult).when(taskMonitorMapperMock).getTaskCountByWorkbasketIdAndDaysInPastAndState( + any(Date.class), + any()); + + List actualResult = cut.getTaskCountByWorkbasketAndDaysInPastAndState(daysInPast, + taskStates); + + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(taskMonitorMapperMock, times(1)).getTaskCountByWorkbasketIdAndDaysInPastAndState(any(Date.class), any()); + verify(taskanaEngineImpl, times(1)).returnConnection(); + verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl, + taskMonitorMapperMock, objectReferenceMapperMock, workbasketServiceMock); + assertThat(actualResult, equalTo(expectedResult)); + } + + @Test + public void testGetWorkbasketLevelReport() { + List workbaskets = Arrays.asList(new WorkbasketImpl(), new WorkbasketImpl()); + List states = Arrays.asList(TaskState.CLAIMED, TaskState.READY); + + Report expectedResult = new Report(); + List expectedDetailLines = new ArrayList<>(); + doReturn(expectedDetailLines).when(taskMonitorMapperMock).getDetailLinesByWorkbasketIdsAndStates(any(), any()); + + Report actualResult = cut.getWorkbasketLevelReport(workbaskets, states); + + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(taskMonitorMapperMock, times(1)).getDetailLinesByWorkbasketIdsAndStates(any(), any()); + verify(taskanaEngineImpl, times(1)).returnConnection(); + verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl, + taskMonitorMapperMock, objectReferenceMapperMock, workbasketServiceMock); + Assert.assertNotNull(actualResult); + assertThat(actualResult.getDetailLines(), equalTo(expectedResult.getDetailLines())); + } + +} diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskMonitorServiceImplIntAutocommitTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskMonitorServiceImplIntAutocommitTest.java new file mode 100644 index 000000000..209ee6c4b --- /dev/null +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskMonitorServiceImplIntAutocommitTest.java @@ -0,0 +1,179 @@ +package pro.taskana.impl.integration; + +import java.io.FileNotFoundException; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +import javax.security.auth.login.LoginException; +import javax.sql.DataSource; + +import org.h2.store.fs.FileUtils; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import pro.taskana.Classification; +import pro.taskana.ClassificationService; +import pro.taskana.TaskMonitorService; +import pro.taskana.TaskanaEngine; +import pro.taskana.TaskanaEngine.ConnectionManagementMode; +import pro.taskana.Workbasket; +import pro.taskana.WorkbasketService; +import pro.taskana.configuration.TaskanaEngineConfiguration; +import pro.taskana.exceptions.ClassificationAlreadyExistException; +import pro.taskana.exceptions.ClassificationNotFoundException; +import pro.taskana.exceptions.InvalidArgumentException; +import pro.taskana.exceptions.InvalidOwnerException; +import pro.taskana.exceptions.InvalidStateException; +import pro.taskana.exceptions.InvalidWorkbasketException; +import pro.taskana.exceptions.NotAuthorizedException; +import pro.taskana.exceptions.TaskAlreadyExistException; +import pro.taskana.exceptions.TaskNotFoundException; +import pro.taskana.exceptions.WorkbasketNotFoundException; +import pro.taskana.impl.JunitHelper; +import pro.taskana.impl.TaskImpl; +import pro.taskana.impl.TaskServiceImpl; +import pro.taskana.impl.TaskanaEngineImpl; +import pro.taskana.impl.WorkbasketImpl; +import pro.taskana.impl.configuration.DBCleaner; +import pro.taskana.impl.configuration.TaskanaEngineConfigurationTest; +import pro.taskana.impl.util.IdGenerator; +import pro.taskana.model.Report; +import pro.taskana.model.TaskState; +import pro.taskana.model.WorkbasketAccessItem; +import pro.taskana.model.WorkbasketType; +import pro.taskana.security.JAASRunner; +import pro.taskana.security.WithAccessId; + +/** + * Integration Test for TaskMonitorServiceImpl transactions with connection management mode AUTOCOMMIT. + */ +@RunWith(JAASRunner.class) +public class TaskMonitorServiceImplIntAutocommitTest { + + private DataSource dataSource; + private TaskServiceImpl taskServiceImpl; + private TaskanaEngineConfiguration taskanaEngineConfiguration; + private TaskanaEngine taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; + private ClassificationService classificationService; + private WorkbasketService workBasketService; + private TaskMonitorService taskMonitorService; + + @BeforeClass + public static void resetDb() throws SQLException { + DataSource ds = TaskanaEngineConfigurationTest.getDataSource(); + DBCleaner cleaner = new DBCleaner(); + cleaner.clearDb(ds, true); + } + + @Before + public void setup() throws FileNotFoundException, SQLException, LoginException { + dataSource = TaskanaEngineConfigurationTest.getDataSource(); + taskanaEngineConfiguration = new TaskanaEngineConfiguration(dataSource, false); + taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); + taskServiceImpl = (TaskServiceImpl) taskanaEngine.getTaskService(); + taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; + classificationService = taskanaEngine.getClassificationService(); + taskanaEngineImpl.setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT); + workBasketService = taskanaEngine.getWorkbasketService(); + taskMonitorService = taskanaEngine.getTaskMonitorService(); + DBCleaner cleaner = new DBCleaner(); + cleaner.clearDb(dataSource, false); + } + + @WithAccessId(userName = "Elena") + @Test + public void testGetWorkbasketLevelReport() throws ClassificationAlreadyExistException, WorkbasketNotFoundException, + ClassificationNotFoundException, NotAuthorizedException, TaskAlreadyExistException, InvalidWorkbasketException, + InvalidArgumentException, TaskNotFoundException, InvalidStateException, InvalidOwnerException { + + generateSampleAccessItems(); + + WorkbasketImpl workbasket1 = (WorkbasketImpl) workBasketService.newWorkbasket(); + workbasket1.setName("wb1"); + workbasket1.setId("1"); + workbasket1.setKey("1"); + workbasket1.setDomain("novatec"); + workbasket1.setType(WorkbasketType.GROUP); + workBasketService.createWorkbasket(workbasket1); + + WorkbasketImpl workbasket2 = (WorkbasketImpl) workBasketService.newWorkbasket(); + workbasket2.setName("wb2"); + workbasket2.setId("2"); + workbasket2.setKey("2"); + workbasket2.setDomain("novatec"); + workbasket2.setType(WorkbasketType.GROUP); + workBasketService.createWorkbasket(workbasket2); + + Classification classification = classificationService.newClassification(); + classification.setKey("TEST"); + classification.setDomain("novatec"); + classificationService.createClassification(classification); + + TaskImpl task1 = (TaskImpl) taskServiceImpl.newTask(); + task1.setWorkbasketKey(workbasket1.getKey()); + task1.setClassificationKey(classification.getKey()); + task1.setPrimaryObjRef(JunitHelper.createDefaultObjRef()); + task1 = (TaskImpl) taskServiceImpl.createTask(task1); + + TaskImpl task2 = (TaskImpl) taskServiceImpl.newTask(); + task2.setWorkbasketKey(workbasket2.getKey()); + task2.setClassificationKey(classification.getKey()); + task2.setPrimaryObjRef(JunitHelper.createDefaultObjRef()); + task2 = (TaskImpl) taskServiceImpl.createTask(task2); + + TaskImpl task3 = (TaskImpl) taskServiceImpl.newTask(); + task3.setWorkbasketKey(workbasket2.getKey()); + task3.setClassificationKey(classification.getKey()); + task3.setPrimaryObjRef(JunitHelper.createDefaultObjRef()); + task3 = (TaskImpl) taskServiceImpl.createTask(task3); + + List workbaskets = Arrays.asList(workbasket1, workbasket2); + List states = Arrays.asList(TaskState.READY, TaskState.CLAIMED); + Report report = taskMonitorService.getWorkbasketLevelReport(workbaskets, states); + + int countWorkbasket1 = report.getDetailLines().get(0).getTotalCount(); + int countWorkbasket2 = report.getDetailLines().get(1).getTotalCount(); + int totalCount = report.getSumLine().getTotalCount(); + + Assert.assertNotNull(report); + Assert.assertEquals(countWorkbasket1, 1); + Assert.assertEquals(countWorkbasket2, 2); + Assert.assertEquals(countWorkbasket1 + countWorkbasket2, totalCount); + } + + private void generateSampleAccessItems() { + WorkbasketAccessItem accessItem = new WorkbasketAccessItem(); + accessItem.setId(IdGenerator.generateWithPrefix("WAI")); + accessItem.setWorkbasketKey("1"); + accessItem.setAccessId("Elena"); + accessItem.setPermAppend(true); + accessItem.setPermRead(true); + workBasketService.createWorkbasketAuthorization(accessItem); + + WorkbasketAccessItem accessItem2 = new WorkbasketAccessItem(); + accessItem2.setId(IdGenerator.generateWithPrefix("WAI")); + accessItem2.setWorkbasketKey("2"); + accessItem2.setAccessId("Elena"); + accessItem2.setPermAppend(true); + accessItem2.setPermRead(true); + workBasketService.createWorkbasketAuthorization(accessItem2); + } + + @After + public void cleanUp() { + taskanaEngineImpl.setConnection(null); + } + + @AfterClass + public static void cleanUpClass() { + FileUtils.deleteRecursive("~/data", true); + } + +} diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskMonitorServiceImplIntExplicitTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskMonitorServiceImplIntExplicitTest.java new file mode 100644 index 000000000..5482ab4d2 --- /dev/null +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/integration/TaskMonitorServiceImplIntExplicitTest.java @@ -0,0 +1,188 @@ +package pro.taskana.impl.integration; + +import java.io.FileNotFoundException; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +import javax.security.auth.login.LoginException; +import javax.sql.DataSource; + +import org.h2.store.fs.FileUtils; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import pro.taskana.Classification; +import pro.taskana.ClassificationService; +import pro.taskana.TaskMonitorService; +import pro.taskana.TaskanaEngine; +import pro.taskana.TaskanaEngine.ConnectionManagementMode; +import pro.taskana.Workbasket; +import pro.taskana.WorkbasketService; +import pro.taskana.configuration.TaskanaEngineConfiguration; +import pro.taskana.exceptions.ClassificationAlreadyExistException; +import pro.taskana.exceptions.ClassificationNotFoundException; +import pro.taskana.exceptions.InvalidArgumentException; +import pro.taskana.exceptions.InvalidOwnerException; +import pro.taskana.exceptions.InvalidStateException; +import pro.taskana.exceptions.InvalidWorkbasketException; +import pro.taskana.exceptions.NotAuthorizedException; +import pro.taskana.exceptions.TaskAlreadyExistException; +import pro.taskana.exceptions.TaskNotFoundException; +import pro.taskana.exceptions.WorkbasketNotFoundException; +import pro.taskana.impl.JunitHelper; +import pro.taskana.impl.TaskImpl; +import pro.taskana.impl.TaskServiceImpl; +import pro.taskana.impl.TaskanaEngineImpl; +import pro.taskana.impl.WorkbasketImpl; +import pro.taskana.impl.configuration.DBCleaner; +import pro.taskana.impl.configuration.TaskanaEngineConfigurationTest; +import pro.taskana.impl.util.IdGenerator; +import pro.taskana.model.Report; +import pro.taskana.model.TaskState; +import pro.taskana.model.WorkbasketAccessItem; +import pro.taskana.model.WorkbasketType; +import pro.taskana.security.JAASRunner; +import pro.taskana.security.WithAccessId; + +/** + * Integration Test for TaskMonitorServiceImpl transactions with connection management mode EXPLICIT. + */ +@RunWith(JAASRunner.class) +public class TaskMonitorServiceImplIntExplicitTest { + + private DataSource dataSource; + private TaskServiceImpl taskServiceImpl; + private TaskanaEngineConfiguration taskanaEngineConfiguration; + private TaskanaEngine taskanaEngine; + private TaskanaEngineImpl taskanaEngineImpl; + private ClassificationService classificationService; + private WorkbasketService workBasketService; + private TaskMonitorService taskMonitorService; + + @BeforeClass + public static void resetDb() throws SQLException { + DataSource ds = TaskanaEngineConfigurationTest.getDataSource(); + DBCleaner cleaner = new DBCleaner(); + cleaner.clearDb(ds, true); + } + + @Before + public void setup() throws FileNotFoundException, SQLException, LoginException { + dataSource = TaskanaEngineConfigurationTest.getDataSource(); + taskanaEngineConfiguration = new TaskanaEngineConfiguration(dataSource, false); + taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine(); + taskServiceImpl = (TaskServiceImpl) taskanaEngine.getTaskService(); + taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine; + classificationService = taskanaEngine.getClassificationService(); + taskanaEngineImpl.setConnectionManagementMode(ConnectionManagementMode.EXPLICIT); + workBasketService = taskanaEngine.getWorkbasketService(); + DBCleaner cleaner = new DBCleaner(); + cleaner.clearDb(dataSource, false); + } + + @WithAccessId(userName = "Elena") + @Test + public void testGetWorkbasketLevelReport() throws SQLException, ClassificationAlreadyExistException, + WorkbasketNotFoundException, ClassificationNotFoundException, NotAuthorizedException, TaskNotFoundException, + TaskAlreadyExistException, InvalidWorkbasketException, InvalidArgumentException, InvalidOwnerException, + InvalidStateException { + Connection connection = dataSource.getConnection(); + taskanaEngineImpl.setConnection(connection); + + taskMonitorService = taskanaEngine.getTaskMonitorService(); + + generateSampleAccessItems(); + + WorkbasketImpl workbasket1 = (WorkbasketImpl) workBasketService.newWorkbasket(); + workbasket1.setName("wb1"); + workbasket1.setId("1"); + workbasket1.setKey("1"); + workbasket1.setDomain("novatec"); + workbasket1.setType(WorkbasketType.GROUP); + workBasketService.createWorkbasket(workbasket1); + + WorkbasketImpl workbasket2 = (WorkbasketImpl) workBasketService.newWorkbasket(); + workbasket2.setName("wb2"); + workbasket2.setId("2"); + workbasket2.setKey("2"); + workbasket2.setDomain("novatec"); + workbasket2.setType(WorkbasketType.GROUP); + workBasketService.createWorkbasket(workbasket2); + + Classification classification = classificationService.newClassification(); + classification.setKey("TEST"); + classification.setDomain("novatec"); + classificationService.createClassification(classification); + + TaskImpl task1 = (TaskImpl) taskServiceImpl.newTask(); + task1.setWorkbasketKey(workbasket1.getKey()); + task1.setClassificationKey(classification.getKey()); + task1.setPrimaryObjRef(JunitHelper.createDefaultObjRef()); + task1 = (TaskImpl) taskServiceImpl.createTask(task1); + connection.commit(); + + TaskImpl task2 = (TaskImpl) taskServiceImpl.newTask(); + task2.setWorkbasketKey(workbasket2.getId()); + task2.setClassificationKey(classification.getKey()); + task2.setPrimaryObjRef(JunitHelper.createDefaultObjRef()); + task2 = (TaskImpl) taskServiceImpl.createTask(task2); + connection.commit(); + + TaskImpl task3 = (TaskImpl) taskServiceImpl.newTask(); + task3.setWorkbasketKey(workbasket2.getId()); + task3.setClassificationKey(classification.getKey()); + task3.setPrimaryObjRef(JunitHelper.createDefaultObjRef()); + task3 = (TaskImpl) taskServiceImpl.createTask(task3); + connection.commit(); + + List workbaskets = Arrays.asList(workbasket1, workbasket2); + List states = Arrays.asList(TaskState.READY, TaskState.CLAIMED); + Report report = taskMonitorService.getWorkbasketLevelReport(workbaskets, states); + + int countWorkbasket1 = report.getDetailLines().get(0).getTotalCount(); + int countWorkbasket2 = report.getDetailLines().get(1).getTotalCount(); + int totalCount = report.getSumLine().getTotalCount(); + + Assert.assertNotNull(report); + Assert.assertEquals(countWorkbasket1, 1); + Assert.assertEquals(countWorkbasket2, 2); + Assert.assertEquals(countWorkbasket1 + countWorkbasket2, totalCount); + connection.commit(); + } + + private void generateSampleAccessItems() { + WorkbasketAccessItem accessItem = new WorkbasketAccessItem(); + accessItem.setId(IdGenerator.generateWithPrefix("WAI")); + accessItem.setWorkbasketKey("1"); + accessItem.setAccessId("Elena"); + accessItem.setPermAppend(true); + accessItem.setPermRead(true); + workBasketService.createWorkbasketAuthorization(accessItem); + + WorkbasketAccessItem accessItem2 = new WorkbasketAccessItem(); + accessItem2.setId(IdGenerator.generateWithPrefix("WAI")); + accessItem2.setWorkbasketKey("2"); + accessItem2.setAccessId("Elena"); + accessItem2.setPermAppend(true); + accessItem2.setPermRead(true); + workBasketService.createWorkbasketAuthorization(accessItem2); + } + + @After + public void cleanUp() { + taskanaEngineImpl.setConnection(null); + } + + @AfterClass + public static void cleanUpClass() { + FileUtils.deleteRecursive("~/data", true); + } + +}