TSK-109: Separate monitor and task operations
- Add TaskMonitorService and move the needed methods from TaskService - Update TaskanaEngine with TaskMonitorService - Update MonitorController and RestApplication - Add TaskMonitorMapper
This commit is contained in:
parent
f1ddf6780c
commit
75e35a7593
|
@ -0,0 +1,51 @@
|
|||
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<TaskStateCounter> getTaskCountForState(List<TaskState> 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<TaskState> 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<DueWorkbasketCounter> getTaskCountByWorkbasketAndDaysInPastAndState(long daysInPast, List<TaskState> states);
|
||||
|
||||
}
|
|
@ -8,10 +8,8 @@ import pro.taskana.exceptions.InvalidStateException;
|
|||
import pro.taskana.exceptions.NotAuthorizedException;
|
||||
import pro.taskana.exceptions.TaskNotFoundException;
|
||||
import pro.taskana.exceptions.WorkbasketNotFoundException;
|
||||
import pro.taskana.model.DueWorkbasketCounter;
|
||||
import pro.taskana.model.Task;
|
||||
import pro.taskana.model.TaskState;
|
||||
import pro.taskana.model.TaskStateCounter;
|
||||
import pro.taskana.model.TaskSummary;
|
||||
|
||||
/**
|
||||
|
@ -55,29 +53,35 @@ public interface TaskService {
|
|||
/**
|
||||
* Complete a claimed Task as owner/admin and update State and Timestamps.
|
||||
*
|
||||
* @param taskId - Id of the Task which should be completed.
|
||||
*
|
||||
* @param taskId
|
||||
* - Id of the Task which should be completed.
|
||||
* @return Task - updated task after completion.
|
||||
*
|
||||
* @throws InvalidStateException when Task wasn´t claimed before.
|
||||
* @throws TaskNotFoundException if the given Task can´t be found in DB.
|
||||
* @throws InvalidOwnerException if current user is not the task-owner or administrator.
|
||||
* @throws InvalidStateException
|
||||
* when Task wasn´t claimed before.
|
||||
* @throws TaskNotFoundException
|
||||
* if the given Task can´t be found in DB.
|
||||
* @throws InvalidOwnerException
|
||||
* if current user is not the task-owner or administrator.
|
||||
*/
|
||||
Task completeTask(String taskId) throws TaskNotFoundException, InvalidOwnerException, InvalidStateException;
|
||||
|
||||
/**
|
||||
* Complete a claimed Task and update State and Timestamps.
|
||||
*
|
||||
* @param taskId - Id of the Task which should be completed.
|
||||
* @param isForced - Flag which can complete a Task in every case if Task does exist.
|
||||
*
|
||||
* @param taskId
|
||||
* - Id of the Task which should be completed.
|
||||
* @param isForced
|
||||
* - Flag which can complete a Task in every case if Task does exist.
|
||||
* @return Task - updated task after completion.
|
||||
*
|
||||
* @throws InvalidStateException when Task wasn´t claimed before.
|
||||
* @throws TaskNotFoundException if the given Task can´t be found in DB.
|
||||
* @throws InvalidOwnerException if current user is not the task-owner or administrator.
|
||||
* @throws InvalidStateException
|
||||
* when Task wasn´t claimed before.
|
||||
* @throws TaskNotFoundException
|
||||
* if the given Task can´t be found in DB.
|
||||
* @throws InvalidOwnerException
|
||||
* if current user is not the task-owner or administrator.
|
||||
*/
|
||||
Task completeTask(String taskId, boolean isForced) throws TaskNotFoundException, InvalidOwnerException, InvalidStateException;
|
||||
Task completeTask(String taskId, boolean isForced)
|
||||
throws TaskNotFoundException, InvalidOwnerException, InvalidStateException;
|
||||
|
||||
/**
|
||||
* Create and persist a task.
|
||||
|
@ -106,43 +110,6 @@ public interface TaskService {
|
|||
*/
|
||||
Task getTaskById(String taskId) throws TaskNotFoundException;
|
||||
|
||||
/**
|
||||
* 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<TaskStateCounter> getTaskCountForState(List<TaskState> 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 {@link Task} objects in the given work basket that match the query parameters
|
||||
*/
|
||||
long getTaskCountForWorkbasketByDaysInPastAndState(String workbasketId, long daysInPast, List<TaskState> 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<DueWorkbasketCounter> getTaskCountByWorkbasketAndDaysInPastAndState(long daysInPast, List<TaskState> states);
|
||||
|
||||
/**
|
||||
* Transfer a task to another work basket. The transfer sets the transferred flag and resets the read flag.
|
||||
*
|
||||
|
|
|
@ -9,24 +9,35 @@ public interface TaskanaEngine {
|
|||
|
||||
/**
|
||||
* The TaskService can be used for operations on all Tasks.
|
||||
*
|
||||
* @return the TaskService
|
||||
*/
|
||||
TaskService getTaskService();
|
||||
|
||||
/**
|
||||
* The TaskMonitorService can be used for monitoring Tasks.
|
||||
*
|
||||
* @return the TaskMonitorService
|
||||
*/
|
||||
TaskMonitorService getTaskMonitorService();
|
||||
|
||||
/**
|
||||
* The WorkbasketService can be used for operations on all Workbaskets.
|
||||
*
|
||||
* @return the TaskService
|
||||
*/
|
||||
WorkbasketService getWorkbasketService();
|
||||
|
||||
/**
|
||||
* The ClassificationService can be used for operations on all Categories.
|
||||
*
|
||||
* @return the TaskService
|
||||
*/
|
||||
ClassificationService getClassificationService();
|
||||
|
||||
/**
|
||||
* The Taskana configuration.
|
||||
*
|
||||
* @return the TaskanaConfiguration
|
||||
*/
|
||||
TaskanaEngineConfiguration getConfiguration();
|
||||
|
@ -34,33 +45,35 @@ public interface TaskanaEngine {
|
|||
/**
|
||||
* sets the connection management mode for taskana.
|
||||
*
|
||||
* @param mode See ConnectionManagementMode
|
||||
* @param mode
|
||||
* See ConnectionManagementMode
|
||||
*/
|
||||
void setConnectionManagementMode(ConnectionManagementMode mode);
|
||||
|
||||
/**
|
||||
* Set the connection to be used by taskana in mode CONNECTION_MANAGED_EXTERNALLY.
|
||||
* If this Api is called, taskana uses the connection passed by the client for all subsequent API calls
|
||||
* until the client resets this connection.
|
||||
* Control over commit and rollback of the connection is the responsibility of the client.
|
||||
* In order to close the connection, closeConnection() or setConnection(null) has to be called.
|
||||
* Set the connection to be used by taskana in mode CONNECTION_MANAGED_EXTERNALLY. If this Api is called, taskana
|
||||
* uses the connection passed by the client for all subsequent API calls until the client resets this connection.
|
||||
* Control over commit and rollback of the connection is the responsibility of the client. In order to close the
|
||||
* connection, closeConnection() or setConnection(null) has to be called.
|
||||
*
|
||||
* @param connection - The java.sql.Connection that is controlled by the client
|
||||
* @param connection
|
||||
* - The java.sql.Connection that is controlled by the client
|
||||
*/
|
||||
void setConnection(java.sql.Connection connection);
|
||||
|
||||
/**
|
||||
* Closes the client's connection, sets it to null and switches to mode PARTICIPATE.
|
||||
* Only applicable in mode EXPLICIT. Has the same effect as setConnection(null).
|
||||
* Closes the client's connection, sets it to null and switches to mode PARTICIPATE. Only applicable in mode
|
||||
* EXPLICIT. Has the same effect as setConnection(null).
|
||||
*/
|
||||
void closeConnection();
|
||||
|
||||
/**
|
||||
* Connection management mode.
|
||||
* Controls the connection handling of taskana
|
||||
* PARTICIPATE - taskana participates in global transaction. This is the default mode
|
||||
* AUTOCOMMIT - taskana commits each API call separately
|
||||
* EXPLICIT - commit processing is managed explicitly by the client
|
||||
* Connection management mode. Controls the connection handling of taskana
|
||||
* <ul>
|
||||
* <li>PARTICIPATE - taskana participates in global transaction. This is the default mode</li>
|
||||
* <li>AUTOCOMMIT - taskana commits each API call separately</li>
|
||||
* <li>EXPLICIT - commit processing is managed explicitly by the client</li>
|
||||
* </ul>
|
||||
*/
|
||||
enum ConnectionManagementMode {
|
||||
PARTICIPATE,
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
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<TaskStateCounter> getTaskCountForState(List<TaskState> states) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("entry to getTaskCountForState(states = {})", LoggerUtils.listToString(states));
|
||||
}
|
||||
List<TaskStateCounter> 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<TaskState> 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<DueWorkbasketCounter> getTaskCountByWorkbasketAndDaysInPastAndState(long daysInPast,
|
||||
List<TaskState> states) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("entry to getTaskCountByWorkbasketAndDaysInPastAndState(daysInPast = {}, states = {})",
|
||||
daysInPast, LoggerUtils.listToString(states));
|
||||
}
|
||||
List<DueWorkbasketCounter> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
package pro.taskana.impl;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -24,11 +22,9 @@ import pro.taskana.exceptions.TaskNotFoundException;
|
|||
import pro.taskana.exceptions.WorkbasketNotFoundException;
|
||||
import pro.taskana.impl.util.IdGenerator;
|
||||
import pro.taskana.impl.util.LoggerUtils;
|
||||
import pro.taskana.model.DueWorkbasketCounter;
|
||||
import pro.taskana.model.ObjectReference;
|
||||
import pro.taskana.model.Task;
|
||||
import pro.taskana.model.TaskState;
|
||||
import pro.taskana.model.TaskStateCounter;
|
||||
import pro.taskana.model.TaskSummary;
|
||||
import pro.taskana.model.WorkbasketAuthorization;
|
||||
import pro.taskana.model.mappings.ObjectReferenceMapper;
|
||||
|
@ -116,7 +112,8 @@ public class TaskServiceImpl implements TaskService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Task completeTask(String taskId, boolean isForced) throws TaskNotFoundException, InvalidOwnerException, InvalidStateException {
|
||||
public Task completeTask(String taskId, boolean isForced)
|
||||
throws TaskNotFoundException, InvalidOwnerException, InvalidStateException {
|
||||
LOGGER.debug("entry to completeTask(id = {}, isForced {})", taskId, isForced);
|
||||
Task task = null;
|
||||
try {
|
||||
|
@ -125,11 +122,15 @@ public class TaskServiceImpl implements TaskService {
|
|||
// check pre-conditions for non-forced invocation
|
||||
if (!isForced) {
|
||||
if (task.getClaimed() == null || task.getState() != TaskState.CLAIMED) {
|
||||
LOGGER.warn("Method completeTask() does expect a task which need to be CLAIMED before. TaskId={}", taskId);
|
||||
LOGGER.warn("Method completeTask() does expect a task which need to be CLAIMED before. TaskId={}",
|
||||
taskId);
|
||||
throw new InvalidStateException(taskId);
|
||||
} else if (CurrentUserContext.getUserid() != task.getOwner()) {
|
||||
LOGGER.warn("Method completeTask() does expect to be invoced by the task-owner or a administrator. TaskId={}, TaskOwner={}, CurrentUser={}", taskId, task.getOwner(), CurrentUserContext.getUserid());
|
||||
throw new InvalidOwnerException("TaskOwner is" + task.getOwner() + ", but current User is " + CurrentUserContext.getUserid());
|
||||
LOGGER.warn(
|
||||
"Method completeTask() does expect to be invoced by the task-owner or a administrator. TaskId={}, TaskOwner={}, CurrentUser={}",
|
||||
taskId, task.getOwner(), CurrentUserContext.getUserid());
|
||||
throw new InvalidOwnerException(
|
||||
"TaskOwner is" + task.getOwner() + ", but current User is " + CurrentUserContext.getUserid());
|
||||
}
|
||||
} else {
|
||||
// CLAIM-forced, if task was not already claimed before.
|
||||
|
@ -195,48 +196,6 @@ public class TaskServiceImpl implements TaskService {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TaskStateCounter> getTaskCountForState(List<TaskState> states) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("entry to getTaskCountForState(states = {})", LoggerUtils.listToString(states));
|
||||
}
|
||||
List<TaskStateCounter> result = null;
|
||||
try {
|
||||
taskanaEngineImpl.openConnection();
|
||||
result = taskMapper.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<TaskState> 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 = taskMapper.getTaskCountForWorkbasketByDaysInPastAndState(workbasketId, fromDate, states);
|
||||
return result;
|
||||
} finally {
|
||||
taskanaEngineImpl.returnConnection();
|
||||
LOGGER.debug("exit from getTaskCountForWorkbasketByDaysInPastAndState(). Returning result {} ", result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task transfer(String taskId, String destinationWorkbasketId)
|
||||
throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException {
|
||||
|
@ -275,32 +234,6 @@ public class TaskServiceImpl implements TaskService {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DueWorkbasketCounter> getTaskCountByWorkbasketAndDaysInPastAndState(long daysInPast,
|
||||
List<TaskState> states) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("entry to getTaskCountByWorkbasketAndDaysInPastAndState(daysInPast = {}, states = {})",
|
||||
daysInPast, LoggerUtils.listToString(states));
|
||||
}
|
||||
List<DueWorkbasketCounter> result = null;
|
||||
try {
|
||||
taskanaEngineImpl.openConnection();
|
||||
LocalDate time = LocalDate.now();
|
||||
time = time.minusDays(daysInPast);
|
||||
Date fromDate = Date.valueOf(time);
|
||||
result = taskMapper.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 Task setTaskRead(String taskId, boolean isRead) throws TaskNotFoundException {
|
||||
LOGGER.debug("entry to setTaskRead(taskId = {}, isRead = {})", taskId, isRead);
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import pro.taskana.ClassificationService;
|
||||
import pro.taskana.TaskMonitorService;
|
||||
import pro.taskana.TaskService;
|
||||
import pro.taskana.TaskanaEngine;
|
||||
import pro.taskana.WorkbasketService;
|
||||
|
@ -27,6 +28,7 @@ import pro.taskana.model.mappings.DistributionTargetMapper;
|
|||
import pro.taskana.model.mappings.ObjectReferenceMapper;
|
||||
import pro.taskana.model.mappings.QueryMapper;
|
||||
import pro.taskana.model.mappings.TaskMapper;
|
||||
import pro.taskana.model.mappings.TaskMonitorMapper;
|
||||
import pro.taskana.model.mappings.WorkbasketAccessMapper;
|
||||
import pro.taskana.model.mappings.WorkbasketMapper;
|
||||
|
||||
|
@ -36,14 +38,21 @@ import pro.taskana.model.mappings.WorkbasketMapper;
|
|||
public class TaskanaEngineImpl implements TaskanaEngine {
|
||||
|
||||
private static final String DEFAULT = "default";
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TaskanaEngineImpl.class);
|
||||
|
||||
protected static ThreadLocal<Stack<SqlSessionManager>> sessionStack = new ThreadLocal<Stack<SqlSessionManager>>();
|
||||
|
||||
protected TaskanaEngineConfiguration taskanaEngineConfiguration;
|
||||
|
||||
protected TransactionFactory transactionFactory;
|
||||
|
||||
protected SqlSessionManager sessionManager;
|
||||
|
||||
protected SqlSessionFactory sessionFactory;
|
||||
|
||||
protected ConnectionManagementMode mode = ConnectionManagementMode.PARTICIPATE;
|
||||
|
||||
protected java.sql.Connection connection = null;
|
||||
|
||||
public TaskanaEngineImpl(TaskanaEngineConfiguration taskanaEngineConfiguration) {
|
||||
|
@ -55,16 +64,26 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
@Override
|
||||
public TaskService getTaskService() {
|
||||
SqlSession session = this.sessionManager;
|
||||
TaskServiceImpl taskServiceImpl = new TaskServiceImpl(this, session.getMapper(TaskMapper.class), session.getMapper(ObjectReferenceMapper.class));
|
||||
TaskServiceImpl taskServiceImpl = new TaskServiceImpl(this, session.getMapper(TaskMapper.class),
|
||||
session.getMapper(ObjectReferenceMapper.class));
|
||||
return taskServiceImpl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskMonitorService getTaskMonitorService() {
|
||||
SqlSession session = this.sessionManager;
|
||||
TaskMonitorServiceImpl taskMonitorServiceImpl = new TaskMonitorServiceImpl(this,
|
||||
session.getMapper(TaskMonitorMapper.class));
|
||||
return taskMonitorServiceImpl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkbasketService getWorkbasketService() {
|
||||
SqlSession session = this.sessionManager;
|
||||
WorkbasketServiceImpl workbasketServiceImpl = new WorkbasketServiceImpl(this, session.getMapper(WorkbasketMapper.class),
|
||||
session.getMapper(DistributionTargetMapper.class),
|
||||
session.getMapper(WorkbasketAccessMapper.class));
|
||||
WorkbasketServiceImpl workbasketServiceImpl = new WorkbasketServiceImpl(this,
|
||||
session.getMapper(WorkbasketMapper.class),
|
||||
session.getMapper(DistributionTargetMapper.class),
|
||||
session.getMapper(WorkbasketAccessMapper.class));
|
||||
return workbasketServiceImpl;
|
||||
}
|
||||
|
||||
|
@ -82,16 +101,18 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
/**
|
||||
* sets the connection management mode.
|
||||
*
|
||||
* @param mode - the connection management mode
|
||||
* Valid values are
|
||||
* PARTICIPATE - taskana participates in global transaction. This is the default mode
|
||||
* AUTOCOMMIT - taskana commits each API call separately
|
||||
* EXPLICIT - commit processing is managed explicitly by the client
|
||||
* @param mode
|
||||
* - the connection management mode Valid values are:
|
||||
* <ul>
|
||||
* <li>PARTICIPATE - taskana participates in global transaction. This is the default mode.</li>
|
||||
* <li>AUTOCOMMIT - taskana commits each API call separately</li>
|
||||
* <li>EXPLICIT - commit processing is managed explicitly by the client</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public void setConnectionManagementMode(ConnectionManagementMode mode) {
|
||||
if (this.mode == ConnectionManagementMode.EXPLICIT && connection != null
|
||||
&& mode != ConnectionManagementMode.EXPLICIT) {
|
||||
&& mode != ConnectionManagementMode.EXPLICIT) {
|
||||
if (sessionManager.isManagedSessionStarted()) {
|
||||
sessionManager.close();
|
||||
}
|
||||
|
@ -101,13 +122,13 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the database connection to be used by taskana.
|
||||
* If this Api is called, taskana uses the connection passed by the client for database
|
||||
* access in all subsequent API calls until the client resets this connection.
|
||||
* Control over commit and rollback is the responsibility of the client.
|
||||
* In order to close the connection, the client can call TaskanaEngine.closeConnection() or
|
||||
* TaskanaEngine.setConnection(null). Both calls have the same effect.
|
||||
* @param connection TODO
|
||||
* Set the database connection to be used by taskana. If this Api is called, taskana uses the connection passed by
|
||||
* the client for database access in all subsequent API calls until the client resets this connection. Control over
|
||||
* commit and rollback is the responsibility of the client. In order to close the connection, the client can call
|
||||
* TaskanaEngine.closeConnection() or TaskanaEngine.setConnection(null). Both calls have the same effect.
|
||||
*
|
||||
* @param connection
|
||||
* TODO
|
||||
*/
|
||||
@Override
|
||||
public void setConnection(java.sql.Connection connection) {
|
||||
|
@ -125,9 +146,8 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
}
|
||||
|
||||
/**
|
||||
* closes the connection to the database in mode EXPLICIT.
|
||||
* In mode EXPLICIT, closes the client's connection, sets it to null and switches to mode PARTICIPATE
|
||||
* Has the same effect as setConnection(null)
|
||||
* closes the connection to the database in mode EXPLICIT. In mode EXPLICIT, closes the client's connection, sets it
|
||||
* to null and switches to mode PARTICIPATE Has the same effect as setConnection(null)
|
||||
*/
|
||||
@Override
|
||||
public void closeConnection() {
|
||||
|
@ -141,9 +161,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
}
|
||||
|
||||
/**
|
||||
* Open the connection to the database.
|
||||
* to be called at the begin of each Api call that accesses the database
|
||||
*
|
||||
* Open the connection to the database. to be called at the begin of each Api call that accesses the database
|
||||
*/
|
||||
void openConnection() {
|
||||
initSqlSession();
|
||||
|
@ -153,8 +171,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
}
|
||||
|
||||
/**
|
||||
* Initializes the SqlSessionManager.
|
||||
*
|
||||
* Initializes the SqlSessionManager.
|
||||
*/
|
||||
void initSqlSession() {
|
||||
if (mode == ConnectionManagementMode.EXPLICIT && this.connection == null) {
|
||||
|
@ -167,17 +184,15 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the database connection into the pool.
|
||||
* In the case of nested calls, simply pops the latest session from the session stack.
|
||||
* Closes the connection if the session stack is empty.
|
||||
* In mode AUTOCOMMIT commits before the connection is closed.
|
||||
* To be called at the end of each Api call that accesses the database
|
||||
* Returns the database connection into the pool. In the case of nested calls, simply pops the latest session from
|
||||
* the session stack. Closes the connection if the session stack is empty. In mode AUTOCOMMIT commits before the
|
||||
* connection is closed. To be called at the end of each Api call that accesses the database
|
||||
*/
|
||||
void returnConnection() {
|
||||
if (this.mode != ConnectionManagementMode.EXPLICIT) {
|
||||
popSessionFromStack();
|
||||
if (getSessionStack().isEmpty()
|
||||
&& this.sessionManager != null && this.sessionManager.isManagedSessionStarted()) {
|
||||
&& this.sessionManager != null && this.sessionManager.isManagedSessionStarted()) {
|
||||
if (this.mode == ConnectionManagementMode.AUTOCOMMIT) {
|
||||
try {
|
||||
this.sessionManager.commit();
|
||||
|
@ -193,23 +208,25 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
|
||||
/**
|
||||
* retrieve the SqlSession used by taskana.
|
||||
* @return the myBatis SqlSession object used by taskana
|
||||
*
|
||||
* @return the myBatis SqlSession object used by taskana
|
||||
*/
|
||||
SqlSession getSqlSession() {
|
||||
return this.sessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates the sqlSessionManager of myBatis. It integrates all the
|
||||
* SQL mappers
|
||||
* This method creates the sqlSessionManager of myBatis. It integrates all the SQL mappers
|
||||
*
|
||||
* @return a {@link SqlSessionFactory}
|
||||
*/
|
||||
private SqlSessionManager createSqlSessionManager() {
|
||||
Environment environment = new Environment(DEFAULT, this.transactionFactory,
|
||||
taskanaEngineConfiguration.getDatasource());
|
||||
taskanaEngineConfiguration.getDatasource());
|
||||
Configuration configuration = new Configuration(environment);
|
||||
// add mappers
|
||||
configuration.addMapper(TaskMapper.class);
|
||||
configuration.addMapper(TaskMonitorMapper.class);
|
||||
configuration.addMapper(WorkbasketMapper.class);
|
||||
configuration.addMapper(DistributionTargetMapper.class);
|
||||
configuration.addMapper(ClassificationMapper.class);
|
||||
|
@ -224,6 +241,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
|
||||
/**
|
||||
* creates the MyBatis transaction factory.
|
||||
*
|
||||
* @param useContainerManagedTransactions
|
||||
*/
|
||||
private void createTransactionFactory(boolean useContainerManagedTransactions) {
|
||||
|
@ -235,15 +253,15 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
}
|
||||
|
||||
/**
|
||||
* With sessionStack, we maintain a Stack of SqlSessionManager objects on a per thread basis.
|
||||
* SqlSessionManager is the MyBatis object that wraps database connections.
|
||||
* The purpose of this stack is to keep track of nested calls.
|
||||
* Each external API call is wrapped into taskanaEngineImpl.openConnection(); ..... taskanaEngineImpl.returnConnection(); calls.
|
||||
* In order to avoid duplicate opening / closing of connections, we use the sessionStack in the following way:
|
||||
* Each time, an openConnection call is received, we push the current sessionManager onto the stack.
|
||||
* On the first call to openConnection, we call sessionManager.startManagedSession() to open a database connection.
|
||||
* On each call to returnConnection() we pop one instance of sessionManager from the stack.
|
||||
* When the stack becomes empty, we close the database connection by calling sessionManager.close()
|
||||
* With sessionStack, we maintain a Stack of SqlSessionManager objects on a per thread basis. SqlSessionManager is
|
||||
* the MyBatis object that wraps database connections. The purpose of this stack is to keep track of nested calls.
|
||||
* Each external API call is wrapped into taskanaEngineImpl.openConnection(); .....
|
||||
* taskanaEngineImpl.returnConnection(); calls. In order to avoid duplicate opening / closing of connections, we use
|
||||
* the sessionStack in the following way: Each time, an openConnection call is received, we push the current
|
||||
* sessionManager onto the stack. On the first call to openConnection, we call sessionManager.startManagedSession()
|
||||
* to open a database connection. On each call to returnConnection() we pop one instance of sessionManager from the
|
||||
* stack. When the stack becomes empty, we close the database connection by calling sessionManager.close()
|
||||
*
|
||||
* @return Stack of SqlSessionManager
|
||||
*/
|
||||
protected static Stack<SqlSessionManager> getSessionStack() {
|
||||
|
|
|
@ -1,15 +1,26 @@
|
|||
package pro.taskana.model.mappings;
|
||||
|
||||
import org.apache.ibatis.annotations.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.One;
|
||||
import org.apache.ibatis.annotations.Options;
|
||||
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 org.apache.ibatis.annotations.Update;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import pro.taskana.Classification;
|
||||
import pro.taskana.impl.persistence.MapTypeHandler;
|
||||
import pro.taskana.model.*;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import pro.taskana.model.ClassificationImpl;
|
||||
import pro.taskana.model.ObjectReference;
|
||||
import pro.taskana.model.Task;
|
||||
import pro.taskana.model.TaskState;
|
||||
import pro.taskana.model.TaskSummary;
|
||||
|
||||
/**
|
||||
* This class is the mybatis mapping of task.
|
||||
|
@ -17,136 +28,114 @@ import java.util.Map;
|
|||
public interface TaskMapper {
|
||||
|
||||
String OBJECTREFERENCEMAPPER_FINDBYID = "pro.taskana.model.mappings.ObjectReferenceMapper.findById";
|
||||
|
||||
String CLASSIFICATION_FINDBYKEYROOTDOMAIN = "pro.taskana.model.mappings.ClassificationMapper.findByKeyRootDomain";
|
||||
|
||||
@Select("SELECT ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, DUE, NAME, DESCRIPTION, PRIORITY, STATE, CLASSIFICATION_KEY, WORKBASKETID, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, OWNER, PRIMARY_OBJ_REF_ID, IS_READ, IS_TRANSFERRED, CUSTOM_ATTRIBUTES, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, CUSTOM_5, CUSTOM_6, CUSTOM_7, CUSTOM_8, CUSTOM_9, CUSTOM_10 "
|
||||
+ "FROM TASK "
|
||||
+ "WHERE ID = #{id}")
|
||||
+ "FROM TASK "
|
||||
+ "WHERE ID = #{id}")
|
||||
@Results(value = {
|
||||
@Result(property = "id", column = "ID"),
|
||||
@Result(property = "created", column = "CREATED"),
|
||||
@Result(property = "claimed", column = "CLAIMED"),
|
||||
@Result(property = "completed", column = "COMPLETED"),
|
||||
@Result(property = "modified", column = "MODIFIED"),
|
||||
@Result(property = "planned", column = "PLANNED"),
|
||||
@Result(property = "due", column = "DUE"),
|
||||
@Result(property = "name", column = "NAME"),
|
||||
@Result(property = "description", column = "DESCRIPTION"),
|
||||
@Result(property = "priority", column = "PRIORITY"),
|
||||
@Result(property = "state", column = "STATE"),
|
||||
@Result(property = "classification", column = "CLASSIFICATION_KEY", javaType = ClassificationImpl.class, one = @One(select = CLASSIFICATION_FINDBYKEYROOTDOMAIN)),
|
||||
@Result(property = "workbasketId", column = "WORKBASKETID"),
|
||||
@Result(property = "businessProcessId", column = "BUSINESS_PROCESS_ID"),
|
||||
@Result(property = "parentBusinessProcessId", column = "PARENT_BUSINESS_PROCESS_ID"),
|
||||
@Result(property = "owner", column = "OWNER"),
|
||||
@Result(property = "primaryObjRef", column = "PRIMARY_OBJ_REF_ID", javaType = ObjectReference.class, one = @One(select = OBJECTREFERENCEMAPPER_FINDBYID)),
|
||||
@Result(property = "isRead", column = "IS_READ"),
|
||||
@Result(property = "isTransferred", column = "IS_TRANSFERRED"),
|
||||
@Result(property = "customAttributes", column = "CUSTOM_ATTRIBUTES", jdbcType = JdbcType.BLOB, javaType = Map.class, typeHandler = MapTypeHandler.class),
|
||||
@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"),
|
||||
@Result(property = "custom9", column = "CUSTOM_9"),
|
||||
@Result(property = "custom10", column = "CUSTOM_10")
|
||||
@Result(property = "id", column = "ID"),
|
||||
@Result(property = "created", column = "CREATED"),
|
||||
@Result(property = "claimed", column = "CLAIMED"),
|
||||
@Result(property = "completed", column = "COMPLETED"),
|
||||
@Result(property = "modified", column = "MODIFIED"),
|
||||
@Result(property = "planned", column = "PLANNED"),
|
||||
@Result(property = "due", column = "DUE"),
|
||||
@Result(property = "name", column = "NAME"),
|
||||
@Result(property = "description", column = "DESCRIPTION"),
|
||||
@Result(property = "priority", column = "PRIORITY"),
|
||||
@Result(property = "state", column = "STATE"),
|
||||
@Result(property = "classification", column = "CLASSIFICATION_KEY", javaType = ClassificationImpl.class,
|
||||
one = @One(select = CLASSIFICATION_FINDBYKEYROOTDOMAIN)),
|
||||
@Result(property = "workbasketId", column = "WORKBASKETID"),
|
||||
@Result(property = "businessProcessId", column = "BUSINESS_PROCESS_ID"),
|
||||
@Result(property = "parentBusinessProcessId", column = "PARENT_BUSINESS_PROCESS_ID"),
|
||||
@Result(property = "owner", column = "OWNER"),
|
||||
@Result(property = "primaryObjRef", column = "PRIMARY_OBJ_REF_ID", javaType = ObjectReference.class,
|
||||
one = @One(select = OBJECTREFERENCEMAPPER_FINDBYID)),
|
||||
@Result(property = "isRead", column = "IS_READ"),
|
||||
@Result(property = "isTransferred", column = "IS_TRANSFERRED"),
|
||||
@Result(property = "customAttributes", column = "CUSTOM_ATTRIBUTES", jdbcType = JdbcType.BLOB,
|
||||
javaType = Map.class, typeHandler = MapTypeHandler.class),
|
||||
@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"),
|
||||
@Result(property = "custom9", column = "CUSTOM_9"),
|
||||
@Result(property = "custom10", column = "CUSTOM_10")
|
||||
})
|
||||
Task findById(@Param("id") String id);
|
||||
|
||||
@Select("<script>"
|
||||
+ "SELECT STATE, COUNT (STATE) as counter "
|
||||
+ "FROM TASK "
|
||||
+ "WHERE STATE IN (<foreach collection='status' item='state' separator=','>#{state}</foreach>) "
|
||||
+ "GROUP BY STATE"
|
||||
+ "</script>")
|
||||
@Results({ @Result(column = "STATE", property = "state"), @Result(column = "counter", property = "counter") })
|
||||
List<TaskStateCounter> getTaskCountForState(@Param("status") List<TaskState> status);
|
||||
|
||||
@Select("<script>"
|
||||
+ "SELECT COUNT (*) "
|
||||
+ "FROM TASK "
|
||||
+ "WHERE WORKBASKETID = #{workbasketId} "
|
||||
+ "AND DUE >= #{fromDate} "
|
||||
+ "AND STATE IN (<foreach collection='status' item='state' separator=','>#{state}</foreach>)"
|
||||
+ "</script>")
|
||||
long getTaskCountForWorkbasketByDaysInPastAndState(@Param("workbasketId") String workbasketId, @Param("fromDate") Date fromDate, @Param("status") List<TaskState> states);
|
||||
|
||||
@Select("<script>"
|
||||
+ "SELECT CAST(DUE AS DATE) as DUE_DATE, WORKBASKETID, COUNT (*) as counter "
|
||||
+ "FROM TASK "
|
||||
+ "WHERE DUE >= #{fromDate} "
|
||||
+ "AND STATE IN (<foreach collection='status' item='state' separator=','>#{state}</foreach>) "
|
||||
+ "GROUP BY DUE_DATE, WORKBASKETID"
|
||||
+ "</script>")
|
||||
@Results({ @Result(column = "DUE_DATE", property = "due"),
|
||||
@Result(column = "WORKBASKETID", property = "workbasketId"),
|
||||
@Result(column = "counter", property = "taskCounter") })
|
||||
List<DueWorkbasketCounter> getTaskCountByWorkbasketIdAndDaysInPastAndState(@Param("fromDate") Date fromDate, @Param("status") List<TaskState> states);
|
||||
|
||||
@Insert("INSERT INTO TASK(ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, DUE, NAME, DESCRIPTION, PRIORITY, STATE, CLASSIFICATION_KEY, WORKBASKETID, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, OWNER, PRIMARY_OBJ_REF_ID, IS_READ, IS_TRANSFERRED, CUSTOM_ATTRIBUTES, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, CUSTOM_5, CUSTOM_6, CUSTOM_7, CUSTOM_8, CUSTOM_9, CUSTOM_10) "
|
||||
+ "VALUES(#{id}, #{created}, #{claimed}, #{completed}, #{modified}, #{planned}, #{due}, #{name}, #{description}, #{priority}, #{state}, #{classification.key}, #{workbasketId}, #{businessProcessId}, #{parentBusinessProcessId}, #{owner}, #{primaryObjRef.id}, #{isRead}, #{isTransferred}, #{customAttributes,jdbcType=BLOB,javaType=java.util.Map,typeHandler=pro.taskana.impl.persistence.MapTypeHandler}, #{custom1}, #{custom2}, #{custom3}, #{custom4}, #{custom5}, #{custom6}, #{custom7}, #{custom8}, #{custom9}, #{custom10})")
|
||||
+ "VALUES(#{id}, #{created}, #{claimed}, #{completed}, #{modified}, #{planned}, #{due}, #{name}, #{description}, #{priority}, #{state}, #{classification.key}, #{workbasketId}, #{businessProcessId}, #{parentBusinessProcessId}, #{owner}, #{primaryObjRef.id}, #{isRead}, #{isTransferred}, #{customAttributes,jdbcType=BLOB,javaType=java.util.Map,typeHandler=pro.taskana.impl.persistence.MapTypeHandler}, #{custom1}, #{custom2}, #{custom3}, #{custom4}, #{custom5}, #{custom6}, #{custom7}, #{custom8}, #{custom9}, #{custom10})")
|
||||
@Options(keyProperty = "id", keyColumn = "ID")
|
||||
void insert(Task task);
|
||||
|
||||
@Update("UPDATE TASK SET CLAIMED = #{claimed}, COMPLETED = #{completed}, MODIFIED = #{modified}, PLANNED = #{planned}, DUE = #{due}, NAME = #{name}, DESCRIPTION = #{description}, PRIORITY = #{priority}, STATE = #{state}, CLASSIFICATION_KEY = #{classification.key}, WORKBASKETID = #{workbasketId}, BUSINESS_PROCESS_ID = #{businessProcessId}, PARENT_BUSINESS_PROCESS_ID = #{parentBusinessProcessId}, OWNER = #{owner}, PRIMARY_OBJ_REF_ID = #{primaryObjRef.id}, IS_READ = #{isRead}, IS_TRANSFERRED = #{isTransferred}, CUSTOM_ATTRIBUTES = #{customAttributes,jdbcType=BLOB,javaType=java.util.Map,typeHandler=pro.taskana.impl.persistence.MapTypeHandler}, CUSTOM_1 = #{custom1}, CUSTOM_2 = #{custom2}, CUSTOM_3 = #{custom3}, CUSTOM_4 = #{custom4}, CUSTOM_5 = #{custom5}, CUSTOM_6 = #{custom6}, CUSTOM_7 = #{custom7}, CUSTOM_8 = #{custom8}, CUSTOM_9 = #{custom9}, CUSTOM_10 = #{custom10} "
|
||||
+ "WHERE ID = #{id}")
|
||||
+ "WHERE ID = #{id}")
|
||||
void update(Task task);
|
||||
|
||||
@Delete("DELETE FROM TASK WHERE ID = #{id}")
|
||||
void delete(String id);
|
||||
|
||||
@Select("SELECT ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, DUE, NAME, DESCRIPTION, PRIORITY, STATE, CLASSIFICATION_KEY, WORKBASKETID, OWNER, PRIMARY_OBJ_REF_ID, IS_READ, IS_TRANSFERRED, CUSTOM_ATTRIBUTES, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, CUSTOM_5, CUSTOM_6, CUSTOM_7, CUSTOM_8, CUSTOM_9, CUSTOM_10 "
|
||||
+ "FROM TASK "
|
||||
+ "WHERE WORKBASKETID = #{workbasketId} "
|
||||
+ "AND STATE = #{taskState}")
|
||||
+ "FROM TASK "
|
||||
+ "WHERE WORKBASKETID = #{workbasketId} "
|
||||
+ "AND STATE = #{taskState}")
|
||||
@Results(value = {
|
||||
@Result(property = "id", column = "ID"),
|
||||
@Result(property = "created", column = "CREATED"),
|
||||
@Result(property = "claimed", column = "CLAIMED"),
|
||||
@Result(property = "completed", column = "COMPLETED"),
|
||||
@Result(property = "modified", column = "MODIFIED"),
|
||||
@Result(property = "planned", column = "PLANNED"),
|
||||
@Result(property = "due", column = "DUE"),
|
||||
@Result(property = "name", column = "NAME"),
|
||||
@Result(property = "description", column = "DESCRIPTION"),
|
||||
@Result(property = "priority", column = "PRIORITY"),
|
||||
@Result(property = "state", column = "STATE"),
|
||||
@Result(property = "classification", column = "CLASSIFICATION_KEY", javaType = Classification.class, one = @One(select = CLASSIFICATION_FINDBYKEYROOTDOMAIN)),
|
||||
@Result(property = "workbasketId", column = "WORKBASKETID"),
|
||||
@Result(property = "owner", column = "OWNER"),
|
||||
@Result(property = "primaryObjRef", column = "PRIMARY_OBJ_REF_ID", javaType = ObjectReference.class, one = @One(select = OBJECTREFERENCEMAPPER_FINDBYID)),
|
||||
@Result(property = "isRead", column = "IS_READ"),
|
||||
@Result(property = "isTransferred", column = "IS_TRANSFERRED"),
|
||||
@Result(property = "customAttributes", column = "CUSTOM_ATTRIBUTES", jdbcType = JdbcType.BLOB, javaType = Map.class, typeHandler = MapTypeHandler.class),
|
||||
@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"),
|
||||
@Result(property = "custom9", column = "CUSTOM_9"),
|
||||
@Result(property = "custom10", column = "CUSTOM_10")
|
||||
@Result(property = "id", column = "ID"),
|
||||
@Result(property = "created", column = "CREATED"),
|
||||
@Result(property = "claimed", column = "CLAIMED"),
|
||||
@Result(property = "completed", column = "COMPLETED"),
|
||||
@Result(property = "modified", column = "MODIFIED"),
|
||||
@Result(property = "planned", column = "PLANNED"),
|
||||
@Result(property = "due", column = "DUE"),
|
||||
@Result(property = "name", column = "NAME"),
|
||||
@Result(property = "description", column = "DESCRIPTION"),
|
||||
@Result(property = "priority", column = "PRIORITY"),
|
||||
@Result(property = "state", column = "STATE"),
|
||||
@Result(property = "classification", column = "CLASSIFICATION_KEY", javaType = Classification.class,
|
||||
one = @One(select = CLASSIFICATION_FINDBYKEYROOTDOMAIN)),
|
||||
@Result(property = "workbasketId", column = "WORKBASKETID"),
|
||||
@Result(property = "owner", column = "OWNER"),
|
||||
@Result(property = "primaryObjRef", column = "PRIMARY_OBJ_REF_ID", javaType = ObjectReference.class,
|
||||
one = @One(select = OBJECTREFERENCEMAPPER_FINDBYID)),
|
||||
@Result(property = "isRead", column = "IS_READ"),
|
||||
@Result(property = "isTransferred", column = "IS_TRANSFERRED"),
|
||||
@Result(property = "customAttributes", column = "CUSTOM_ATTRIBUTES", jdbcType = JdbcType.BLOB,
|
||||
javaType = Map.class, typeHandler = MapTypeHandler.class),
|
||||
@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"),
|
||||
@Result(property = "custom9", column = "CUSTOM_9"),
|
||||
@Result(property = "custom10", column = "CUSTOM_10")
|
||||
})
|
||||
List<Task> findTasksByWorkbasketIdAndState(@Param("workbasketId") String workbasketId, @Param("taskState") TaskState taskState);
|
||||
List<Task> findTasksByWorkbasketIdAndState(@Param("workbasketId") String workbasketId,
|
||||
@Param("taskState") TaskState taskState);
|
||||
|
||||
@Select("SELECT TASK.ID AS taskId, TASK.NAME AS taskName, TASK.WORKBASKETID AS workId, TASK.CLASSIFICATION_KEY AS classificationKey, "
|
||||
+ "WORKBASKET.NAME AS workName, CLASSIFICATION.NAME AS classificationName "
|
||||
+ "FROM TASK "
|
||||
+ "LEFT JOIN WORKBASKET ON WORKBASKET.ID = TASK.WORKBASKETID "
|
||||
+ "LEFT JOIN CLASSIFICATION ON CLASSIFICATION.KEY = TASK.CLASSIFICATION_KEY "
|
||||
+ "WHERE TASK.WORKBASKETID = #{workbasketId}")
|
||||
+ "WORKBASKET.NAME AS workName, CLASSIFICATION.NAME AS classificationName "
|
||||
+ "FROM TASK "
|
||||
+ "LEFT JOIN WORKBASKET ON WORKBASKET.ID = TASK.WORKBASKETID "
|
||||
+ "LEFT JOIN CLASSIFICATION ON CLASSIFICATION.KEY = TASK.CLASSIFICATION_KEY "
|
||||
+ "WHERE TASK.WORKBASKETID = #{workbasketId}")
|
||||
@Results({
|
||||
@Result(property = "taskId", column = "taskId"),
|
||||
@Result(property = "taskName", column = "taskName"),
|
||||
@Result(property = "workbasketId", column = "workId"),
|
||||
@Result(property = "workbasketName", column = "workName"),
|
||||
@Result(property = "classificationKey", column = "classificationKey"),
|
||||
@Result(property = "classificationName", column = "classificationName")
|
||||
@Result(property = "taskId", column = "taskId"),
|
||||
@Result(property = "taskName", column = "taskName"),
|
||||
@Result(property = "workbasketId", column = "workId"),
|
||||
@Result(property = "workbasketName", column = "workName"),
|
||||
@Result(property = "classificationKey", column = "classificationKey"),
|
||||
@Result(property = "classificationName", column = "classificationName")
|
||||
})
|
||||
List<TaskSummary> findTaskSummariesByWorkbasketId(@Param("workbasketId") String workbasketId);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
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("<script>"
|
||||
+ "SELECT STATE, COUNT (STATE) as counter "
|
||||
+ "FROM TASK "
|
||||
+ "WHERE STATE IN (<foreach collection='status' item='state' separator=','>#{state}</foreach>) "
|
||||
+ "GROUP BY STATE"
|
||||
+ "</script>")
|
||||
@Results({ @Result(column = "STATE", property = "state"), @Result(column = "counter", property = "counter") })
|
||||
List<TaskStateCounter> getTaskCountForState(@Param("status") List<TaskState> status);
|
||||
|
||||
@Select("<script>"
|
||||
+ "SELECT COUNT (*) "
|
||||
+ "FROM TASK "
|
||||
+ "WHERE WORKBASKETID = #{workbasketId} "
|
||||
+ "AND DUE >= #{fromDate} "
|
||||
+ "AND STATE IN (<foreach collection='status' item='state' separator=','>#{state}</foreach>)"
|
||||
+ "</script>")
|
||||
long getTaskCountForWorkbasketByDaysInPastAndState(@Param("workbasketId") String workbasketId,
|
||||
@Param("fromDate") Date fromDate, @Param("status") List<TaskState> states);
|
||||
|
||||
@Select("<script>"
|
||||
+ "SELECT CAST(DUE AS DATE) as DUE_DATE, WORKBASKETID, COUNT (*) as counter "
|
||||
+ "FROM TASK "
|
||||
+ "WHERE DUE >= #{fromDate} "
|
||||
+ "AND STATE IN (<foreach collection='status' item='state' separator=','>#{state}</foreach>) "
|
||||
+ "GROUP BY DUE_DATE, WORKBASKETID"
|
||||
+ "</script>")
|
||||
@Results({ @Result(column = "DUE_DATE", property = "due"),
|
||||
@Result(column = "WORKBASKETID", property = "workbasketId"),
|
||||
@Result(column = "counter", property = "taskCounter") })
|
||||
List<DueWorkbasketCounter> getTaskCountByWorkbasketIdAndDaysInPastAndState(@Param("fromDate") Date fromDate,
|
||||
@Param("status") List<TaskState> states);
|
||||
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
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<TaskState> taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED);
|
||||
List<TaskStateCounter> expectedResult = new ArrayList<>();
|
||||
doReturn(expectedResult).when(taskMonitorMapperMock).getTaskCountForState(taskStates);
|
||||
|
||||
List<TaskStateCounter> 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<TaskState> 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<TaskState> taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED);
|
||||
List<DueWorkbasketCounter> expectedResult = new ArrayList<>();
|
||||
doReturn(expectedResult).when(taskMonitorMapperMock).getTaskCountByWorkbasketIdAndDaysInPastAndState(
|
||||
any(Date.class),
|
||||
any());
|
||||
|
||||
List<DueWorkbasketCounter> 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));
|
||||
}
|
||||
|
||||
}
|
|
@ -13,7 +13,6 @@ import static org.mockito.Mockito.times;
|
|||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
|
@ -44,11 +43,9 @@ import pro.taskana.exceptions.NotAuthorizedException;
|
|||
import pro.taskana.exceptions.TaskNotFoundException;
|
||||
import pro.taskana.exceptions.WorkbasketNotFoundException;
|
||||
import pro.taskana.model.ClassificationImpl;
|
||||
import pro.taskana.model.DueWorkbasketCounter;
|
||||
import pro.taskana.model.ObjectReference;
|
||||
import pro.taskana.model.Task;
|
||||
import pro.taskana.model.TaskState;
|
||||
import pro.taskana.model.TaskStateCounter;
|
||||
import pro.taskana.model.TaskSummary;
|
||||
import pro.taskana.model.Workbasket;
|
||||
import pro.taskana.model.WorkbasketAuthorization;
|
||||
|
@ -232,7 +229,7 @@ public class TaskServiceImplTest {
|
|||
expectedObjectReference.setId("1");
|
||||
expectedObjectReference.setType("DUMMY");
|
||||
|
||||
Classification classification = (Classification) new ClassificationImpl();
|
||||
Classification classification = new ClassificationImpl();
|
||||
classification.setName("Name");
|
||||
classification.setCategory("MANUAL");
|
||||
Workbasket wb = new Workbasket();
|
||||
|
@ -378,7 +375,8 @@ public class TaskServiceImplTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteTaskDefault() throws TaskNotFoundException, InvalidOwnerException, InvalidStateException, InterruptedException {
|
||||
public void testCompleteTaskDefault()
|
||||
throws TaskNotFoundException, InvalidOwnerException, InvalidStateException, InterruptedException {
|
||||
TaskServiceImpl cutSpy = Mockito.spy(cut);
|
||||
final long sleepTime = 100L;
|
||||
final boolean isForced = false;
|
||||
|
@ -394,11 +392,12 @@ public class TaskServiceImplTest {
|
|||
// Just Verify unforced call of complex-complete()
|
||||
verify(cutSpy, times(1)).completeTask(task.getId(), isForced);
|
||||
verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl,
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteTaskNotForcedWorking() throws TaskNotFoundException, InvalidStateException, InvalidOwnerException, InterruptedException {
|
||||
public void testCompleteTaskNotForcedWorking()
|
||||
throws TaskNotFoundException, InvalidStateException, InvalidOwnerException, InterruptedException {
|
||||
TaskServiceImpl cutSpy = Mockito.spy(cut);
|
||||
final long sleepTime = 100L;
|
||||
final boolean isForced = false;
|
||||
|
@ -427,7 +426,8 @@ public class TaskServiceImplTest {
|
|||
}
|
||||
|
||||
@Test(expected = InvalidStateException.class)
|
||||
public void testCompleteTaskNotForcedNotClaimedBefore() throws TaskNotFoundException, InvalidStateException, InvalidOwnerException {
|
||||
public void testCompleteTaskNotForcedNotClaimedBefore()
|
||||
throws TaskNotFoundException, InvalidStateException, InvalidOwnerException {
|
||||
final boolean isForced = false;
|
||||
TaskServiceImpl cutSpy = Mockito.spy(cut);
|
||||
Task task = createUnitTestTask("1", "Unit Test Task 1", "1");
|
||||
|
@ -442,13 +442,14 @@ public class TaskServiceImplTest {
|
|||
verify(cutSpy, times(1)).getTaskById(task.getId());
|
||||
verify(taskanaEngineImpl, times(1)).returnConnection();
|
||||
verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl,
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = InvalidOwnerException.class)
|
||||
public void testCompleteTaskNotForcedInvalidOwnerException() throws TaskNotFoundException, InvalidStateException, InvalidOwnerException {
|
||||
public void testCompleteTaskNotForcedInvalidOwnerException()
|
||||
throws TaskNotFoundException, InvalidStateException, InvalidOwnerException {
|
||||
final boolean isForced = false;
|
||||
TaskServiceImpl cutSpy = Mockito.spy(cut);
|
||||
Task task = createUnitTestTask("1", "Unit Test Task 1", "1");
|
||||
|
@ -470,25 +471,27 @@ public class TaskServiceImplTest {
|
|||
}
|
||||
|
||||
@Test(expected = TaskNotFoundException.class)
|
||||
public void testCompleteTaskTaskNotFound() throws TaskNotFoundException, InvalidStateException, InvalidOwnerException {
|
||||
public void testCompleteTaskTaskNotFound()
|
||||
throws TaskNotFoundException, InvalidStateException, InvalidOwnerException {
|
||||
TaskServiceImpl cutSpy = Mockito.spy(cut);
|
||||
final boolean isForced = false;
|
||||
String taskId = "1";
|
||||
doThrow(TaskNotFoundException.class).when(cutSpy).getTaskById(taskId);
|
||||
try {
|
||||
try {
|
||||
cutSpy.completeTask(taskId, isForced);
|
||||
} catch (InvalidOwnerException e) {
|
||||
verify(taskanaEngineImpl, times(1)).openConnection();
|
||||
verify(cutSpy, times(1)).getTaskById(taskId);
|
||||
verify(taskanaEngineImpl, times(1)).returnConnection();
|
||||
verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl,
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
throw e;
|
||||
verify(taskanaEngineImpl, times(1)).returnConnection();
|
||||
verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl,
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteForcedAndAlreadyClaimed() throws TaskNotFoundException, InvalidStateException, InvalidOwnerException, InterruptedException {
|
||||
public void testCompleteForcedAndAlreadyClaimed()
|
||||
throws TaskNotFoundException, InvalidStateException, InvalidOwnerException, InterruptedException {
|
||||
final boolean isForced = true;
|
||||
final long sleepTime = 100L;
|
||||
TaskServiceImpl cutSpy = Mockito.spy(cut);
|
||||
|
@ -507,7 +510,7 @@ public class TaskServiceImplTest {
|
|||
verify(taskMapperMock, times(1)).update(task);
|
||||
verify(taskanaEngineImpl, times(1)).returnConnection();
|
||||
verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl,
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
|
||||
assertThat(actualTask.getState(), equalTo(TaskState.COMPLETED));
|
||||
assertThat(actualTask.getCreated(), not(equalTo(task.getModified())));
|
||||
|
@ -516,7 +519,8 @@ public class TaskServiceImplTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testCompleteForcedNotClaimed() throws TaskNotFoundException, InvalidStateException, InvalidOwnerException, InterruptedException {
|
||||
public void testCompleteForcedNotClaimed()
|
||||
throws TaskNotFoundException, InvalidStateException, InvalidOwnerException, InterruptedException {
|
||||
TaskServiceImpl cutSpy = Mockito.spy(cut);
|
||||
final boolean isForced = true;
|
||||
final long sleepTime = 100L;
|
||||
|
@ -540,7 +544,7 @@ public class TaskServiceImplTest {
|
|||
verify(taskMapperMock, times(1)).update(claimedTask);
|
||||
verify(taskanaEngineImpl, times(1)).returnConnection();
|
||||
verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl,
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
assertThat(actualTask.getState(), equalTo(TaskState.COMPLETED));
|
||||
assertThat(actualTask.getCreated(), not(equalTo(claimedTask.getModified())));
|
||||
assertThat(actualTask.getCompleted(), not(equalTo(null)));
|
||||
|
@ -713,61 +717,6 @@ public class TaskServiceImplTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTaskCountForState() {
|
||||
TaskServiceImpl cutSpy = Mockito.spy(cut);
|
||||
List<TaskState> taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED);
|
||||
List<TaskStateCounter> expectedResult = new ArrayList<>();
|
||||
doReturn(expectedResult).when(taskMapperMock).getTaskCountForState(taskStates);
|
||||
|
||||
List<TaskStateCounter> actualResult = cutSpy.getTaskCountForState(taskStates);
|
||||
|
||||
verify(taskanaEngineImpl, times(1)).openConnection();
|
||||
verify(taskMapperMock, times(1)).getTaskCountForState(taskStates);
|
||||
verify(taskanaEngineImpl, times(1)).returnConnection();
|
||||
verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl,
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
assertThat(actualResult, equalTo(expectedResult));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTaskCountForWorkbasketByDaysInPastAndState() {
|
||||
List<TaskState> taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED);
|
||||
final long daysInPast = 10L;
|
||||
final long expectedResult = 5L;
|
||||
String workbasketId = "1";
|
||||
doReturn(expectedResult).when(taskMapperMock).getTaskCountForWorkbasketByDaysInPastAndState(any(), any(),
|
||||
any());
|
||||
|
||||
long actualResult = cut.getTaskCountForWorkbasketByDaysInPastAndState(workbasketId, daysInPast, taskStates);
|
||||
|
||||
verify(taskanaEngineImpl, times(1)).openConnection();
|
||||
verify(taskMapperMock, times(1)).getTaskCountForWorkbasketByDaysInPastAndState(any(), any(), any());
|
||||
verify(taskanaEngineImpl, times(1)).returnConnection();
|
||||
verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl,
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
assertThat(actualResult, equalTo(expectedResult));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTaskCountByWorkbasketAndDaysInPastAndState() {
|
||||
final long daysInPast = 10L;
|
||||
List<TaskState> taskStates = Arrays.asList(TaskState.CLAIMED, TaskState.COMPLETED);
|
||||
List<DueWorkbasketCounter> expectedResult = new ArrayList<>();
|
||||
doReturn(expectedResult).when(taskMapperMock).getTaskCountByWorkbasketIdAndDaysInPastAndState(any(Date.class),
|
||||
any());
|
||||
|
||||
List<DueWorkbasketCounter> actualResult = cut.getTaskCountByWorkbasketAndDaysInPastAndState(daysInPast,
|
||||
taskStates);
|
||||
|
||||
verify(taskanaEngineImpl, times(1)).openConnection();
|
||||
verify(taskMapperMock, times(1)).getTaskCountByWorkbasketIdAndDaysInPastAndState(any(Date.class), any());
|
||||
verify(taskanaEngineImpl, times(1)).returnConnection();
|
||||
verifyNoMoreInteractions(taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl,
|
||||
taskMapperMock, objectReferenceMapperMock, workbasketServiceMock);
|
||||
assertThat(actualResult, equalTo(expectedResult));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetTaskReadWIthExistingTask() throws TaskNotFoundException, ClassificationAlreadyExistException {
|
||||
TaskServiceImpl cutSpy = Mockito.spy(cut);
|
||||
|
@ -910,7 +859,7 @@ public class TaskServiceImplTest {
|
|||
Timestamp now = new Timestamp(System.currentTimeMillis());
|
||||
task.setCreated(now);
|
||||
task.setModified(now);
|
||||
Classification classification = (Classification) new ClassificationImpl();
|
||||
Classification classification = new ClassificationImpl();
|
||||
task.setClassification(classification);
|
||||
return task;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ import org.springframework.http.ResponseEntity;
|
|||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import pro.taskana.TaskService;
|
||||
|
||||
import pro.taskana.TaskMonitorService;
|
||||
import pro.taskana.WorkbasketService;
|
||||
import pro.taskana.model.DueWorkbasketCounter;
|
||||
import pro.taskana.model.TaskState;
|
||||
|
@ -25,76 +26,78 @@ import pro.taskana.rest.model.WorkbasketCounterDto;
|
|||
@RequestMapping(path = "/v1/monitor", produces = { MediaType.APPLICATION_JSON_VALUE })
|
||||
public class MonitorController {
|
||||
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
@Autowired
|
||||
private TaskMonitorService taskMonitorService;
|
||||
|
||||
@Autowired
|
||||
private WorkbasketService workbasketService;
|
||||
@Autowired
|
||||
private WorkbasketService workbasketService;
|
||||
|
||||
@RequestMapping(value = "/countByState")
|
||||
public ResponseEntity<List<TaskStateCounter>> getTaskcountForState(
|
||||
@RequestParam(value = "states") List<TaskState> taskStates) {
|
||||
try {
|
||||
List<TaskStateCounter> taskCount = taskService.getTaskCountForState(taskStates);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(taskCount);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
@RequestMapping(value = "/countByState")
|
||||
public ResponseEntity<List<TaskStateCounter>> getTaskcountForState(
|
||||
@RequestParam(value = "states") List<TaskState> taskStates) {
|
||||
try {
|
||||
List<TaskStateCounter> taskCount = taskMonitorService.getTaskCountForState(taskStates);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(taskCount);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/taskcountByWorkbasketDaysAndState")
|
||||
public ResponseEntity<?> getTaskCountByWorkbasketAndDaysInPastAndState(
|
||||
@RequestParam(value = "daysInPast") Long daysInPast,
|
||||
@RequestParam(value = "states") List<TaskState> states) {
|
||||
try {
|
||||
WorkbasketCounterDto WorkbasketCounterDto = new WorkbasketCounterDto();
|
||||
@RequestMapping(value = "/taskcountByWorkbasketDaysAndState")
|
||||
public ResponseEntity<?> getTaskCountByWorkbasketAndDaysInPastAndState(
|
||||
@RequestParam(value = "daysInPast") Long daysInPast,
|
||||
@RequestParam(value = "states") List<TaskState> states) {
|
||||
try {
|
||||
WorkbasketCounterDto WorkbasketCounterDto = new WorkbasketCounterDto();
|
||||
|
||||
LocalDate date = LocalDate.now();
|
||||
date = date.minusDays(daysInPast);
|
||||
List<String> dates = new ArrayList<>();
|
||||
LocalDate date = LocalDate.now();
|
||||
date = date.minusDays(daysInPast);
|
||||
List<String> dates = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < (daysInPast * 2 + 1); i++) {
|
||||
dates.add(date.format(new DateTimeFormatterBuilder().appendPattern("dd.MM.yyyy").toFormatter()));
|
||||
date = date.plusDays(1);
|
||||
}
|
||||
WorkbasketCounterDto.setDates(dates);
|
||||
for (int i = 0; i < (daysInPast * 2 + 1); i++) {
|
||||
dates.add(date.format(new DateTimeFormatterBuilder().appendPattern("dd.MM.yyyy").toFormatter()));
|
||||
date = date.plusDays(1);
|
||||
}
|
||||
WorkbasketCounterDto.setDates(dates);
|
||||
|
||||
List<WorkbasketCounterDataDto> data = new ArrayList<>();
|
||||
List<WorkbasketCounterDataDto> data = new ArrayList<>();
|
||||
|
||||
for (Workbasket workbasket : workbasketService.getWorkbaskets()) {
|
||||
WorkbasketCounterDataDto counterDto = new WorkbasketCounterDataDto();
|
||||
counterDto.setLabel(workbasket.getName());
|
||||
List<Integer> zeroData = new ArrayList<>();
|
||||
for (int i = 0; i < dates.size(); i++) {
|
||||
zeroData.add(0);
|
||||
}
|
||||
counterDto.setData(zeroData);
|
||||
data.add(counterDto);
|
||||
}
|
||||
for (Workbasket workbasket : workbasketService.getWorkbaskets()) {
|
||||
WorkbasketCounterDataDto counterDto = new WorkbasketCounterDataDto();
|
||||
counterDto.setLabel(workbasket.getName());
|
||||
List<Integer> zeroData = new ArrayList<>();
|
||||
for (int i = 0; i < dates.size(); i++) {
|
||||
zeroData.add(0);
|
||||
}
|
||||
counterDto.setData(zeroData);
|
||||
data.add(counterDto);
|
||||
}
|
||||
|
||||
List<DueWorkbasketCounter> dwcList = taskService.getTaskCountByWorkbasketAndDaysInPastAndState(daysInPast,
|
||||
states);
|
||||
List<DueWorkbasketCounter> dwcList = taskMonitorService.getTaskCountByWorkbasketAndDaysInPastAndState(
|
||||
daysInPast,
|
||||
states);
|
||||
|
||||
for (DueWorkbasketCounter item : dwcList) {
|
||||
String formattedDate = item.getDue().toLocalDate()
|
||||
.format(new DateTimeFormatterBuilder().appendPattern("dd.MM.yyyy").toFormatter());
|
||||
for (int i = 0; i < dates.size(); i++) {
|
||||
if (formattedDate.equalsIgnoreCase(dates.get(i))) {
|
||||
for (int j = 0; j < data.size(); j++) {
|
||||
if (data.get(j).getLabel().equalsIgnoreCase(
|
||||
workbasketService.getWorkbasket(item.getWorkbasketId()).getName())) {
|
||||
data.get(j).getData().set(i, (int) item.getTaskCounter());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (DueWorkbasketCounter item : dwcList) {
|
||||
String formattedDate = item.getDue()
|
||||
.toLocalDate()
|
||||
.format(new DateTimeFormatterBuilder().appendPattern("dd.MM.yyyy").toFormatter());
|
||||
for (int i = 0; i < dates.size(); i++) {
|
||||
if (formattedDate.equalsIgnoreCase(dates.get(i))) {
|
||||
for (int j = 0; j < data.size(); j++) {
|
||||
if (data.get(j).getLabel().equalsIgnoreCase(
|
||||
workbasketService.getWorkbasket(item.getWorkbasketId()).getName())) {
|
||||
data.get(j).getData().set(i, (int) item.getTaskCounter());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WorkbasketCounterDto.setData(data);
|
||||
WorkbasketCounterDto.setData(data);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.OK).body(WorkbasketCounterDto);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.OK).body(WorkbasketCounterDto);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.springframework.http.converter.json.SpringHandlerInstantiator;
|
|||
import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
|
||||
|
||||
import pro.taskana.ClassificationService;
|
||||
import pro.taskana.TaskMonitorService;
|
||||
import pro.taskana.TaskService;
|
||||
import pro.taskana.TaskanaEngine;
|
||||
import pro.taskana.WorkbasketService;
|
||||
|
@ -29,72 +30,77 @@ import pro.taskana.sampledata.SampleDataGenerator;
|
|||
@SpringBootApplication
|
||||
public class RestApplication {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(RestApplication.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(RestApplication.class);
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(RestApplication.class, args);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(RestApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ClassificationService getClassificationService() throws Exception {
|
||||
return getTaskanaEngine().getClassificationService();
|
||||
}
|
||||
@Bean
|
||||
public ClassificationService getClassificationService() throws Exception {
|
||||
return getTaskanaEngine().getClassificationService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TaskService getTaskService() throws Exception {
|
||||
return getTaskanaEngine().getTaskService();
|
||||
}
|
||||
@Bean
|
||||
public TaskService getTaskService() throws Exception {
|
||||
return getTaskanaEngine().getTaskService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WorkbasketService getWorkbasketService() throws Exception {
|
||||
return getTaskanaEngine().getWorkbasketService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||
public TaskanaEngine getTaskanaEngine() throws SQLException {
|
||||
return getTaskanaEngineConfiguration().buildTaskanaEngine();
|
||||
}
|
||||
@Bean
|
||||
public TaskMonitorService getTaskMonitorService() throws Exception {
|
||||
return getTaskanaEngine().getTaskMonitorService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||
public TaskanaEngineConfiguration getTaskanaEngineConfiguration() throws SQLException {
|
||||
TaskanaEngineConfiguration taskanaEngineConfiguration = new TaskanaEngineConfiguration(null, true);
|
||||
return taskanaEngineConfiguration;
|
||||
}
|
||||
@Bean
|
||||
public WorkbasketService getWorkbasketService() throws Exception {
|
||||
return getTaskanaEngine().getWorkbasketService();
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void createSampleData() {
|
||||
try {
|
||||
new SampleDataGenerator(getTaskanaEngineConfiguration().createDefaultDataSource()).generateSampleData();
|
||||
} catch (SQLException e) {
|
||||
logger.error("Could not create sample data.", e);
|
||||
}
|
||||
}
|
||||
@Bean
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||
public TaskanaEngine getTaskanaEngine() throws SQLException {
|
||||
return getTaskanaEngineConfiguration().buildTaskanaEngine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed to override JSON De-/Serializer in Jackson.
|
||||
*
|
||||
* @param handlerInstantiator
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilder jacksonBuilder(HandlerInstantiator handlerInstantiator) {
|
||||
Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
|
||||
b.indentOutput(true).mixIn(Workbasket.class, WorkbasketMixIn.class);
|
||||
b.handlerInstantiator(handlerInstantiator);
|
||||
return b;
|
||||
}
|
||||
@Bean
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||
public TaskanaEngineConfiguration getTaskanaEngineConfiguration() throws SQLException {
|
||||
TaskanaEngineConfiguration taskanaEngineConfiguration = new TaskanaEngineConfiguration(null, true);
|
||||
return taskanaEngineConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed for injection into jackson deserilizer.
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public HandlerInstantiator handlerInstantiator(ApplicationContext context) {
|
||||
return new SpringHandlerInstantiator(context.getAutowireCapableBeanFactory());
|
||||
}
|
||||
@PostConstruct
|
||||
public void createSampleData() {
|
||||
try {
|
||||
new SampleDataGenerator(getTaskanaEngineConfiguration().createDefaultDataSource()).generateSampleData();
|
||||
} catch (SQLException e) {
|
||||
logger.error("Could not create sample data.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed to override JSON De-/Serializer in Jackson.
|
||||
*
|
||||
* @param handlerInstantiator
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilder jacksonBuilder(HandlerInstantiator handlerInstantiator) {
|
||||
Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
|
||||
b.indentOutput(true).mixIn(Workbasket.class, WorkbasketMixIn.class);
|
||||
b.handlerInstantiator(handlerInstantiator);
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed for injection into jackson deserilizer.
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public HandlerInstantiator handlerInstantiator(ApplicationContext context) {
|
||||
return new SpringHandlerInstantiator(context.getAutowireCapableBeanFactory());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue