TSK-1538: Added transfer method with control setTransferFlag (#1513)

* TSK-1538: Added transfer method with control setTransferFlag

* TSK-1538: Improvements after review

Co-authored-by: Mustapha Zorgati <15628173+mustaphazorgati@users.noreply.github.com>
This commit is contained in:
tge20 2021-03-09 18:58:51 +01:00 committed by GitHub
parent bbbb657c7a
commit 0119999380
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 349 additions and 113 deletions

View File

@ -149,7 +149,7 @@ public interface TaskService {
TaskAlreadyExistException, InvalidArgumentException;
/**
* Get the details of a task by Id without checking permissions.
* Gets the details of a task by Id without checking permissions.
*
* @param taskId the id of the task
* @return the Task
@ -160,39 +160,83 @@ public interface TaskService {
Task getTask(String taskId) throws TaskNotFoundException, NotAuthorizedException;
/**
* Transfer a Task to another work basket. The transfer sets the transferred flag and resets the
* read flag.
* Transfers a {@linkplain Task} to another {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket} while always setting the {@linkplain
* Task#isTransferred transfer} flag.
*
* @param taskId The id of the {@link Task} to be transferred
* @param destinationWorkbasketId The Id of the target work basket
* @return the transferred task
* @throws TaskNotFoundException Thrown if the {@link Task} with taskId was not found.
* @throws WorkbasketNotFoundException Thrown if the target work basket was not found.
* @throws NotAuthorizedException Thrown if the current user is not authorized to transfer this
* {@link Task} to the target work basket
* @throws InvalidStateException Thrown if the task is in a state which does not allow
* transferring
* @see #transfer(String, String, boolean)
*/
Task transfer(String taskId, String destinationWorkbasketId)
@SuppressWarnings("checkstyle:JavadocMethod")
default Task transfer(String taskId, String destinationWorkbasketId)
throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException,
InvalidStateException {
return transfer(taskId, destinationWorkbasketId, true);
}
/**
* Transfers a {@linkplain Task} to another {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket}.
*
* <p>The transfer resets the read flag and sets the transfer flag if {@code setTransferFlag} is
* {@code true}.
*
* @param taskId the id of the {@linkplain Task} which should be transferred
* @param destinationWorkbasketId the id of the target {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket}
* @param setTransferFlag the control about whether to set the {@linkplain Task#isTransferred()}
* flag or not
* @return the transferred {@linkplain Task}
* @throws TaskNotFoundException Thrown if the {@linkplain Task} with taskId was not found.
* @throws WorkbasketNotFoundException Thrown if the target {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket} was not found.
* @throws NotAuthorizedException Thrown if the current user is not authorized to transfer this
* {@linkplain Task} to the target {@linkplain pro.taskana.workbasket.api.models.Workbasket
* Workbasket}
* @throws InvalidStateException Thrown if the {@linkplain Task} is in a state which does not
* allow transferring
*/
Task transfer(String taskId, String destinationWorkbasketId, boolean setTransferFlag)
throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException,
InvalidStateException;
/**
* Transfer a task to another work basket. The transfer sets the transferred flag and resets the
* read flag.
* Transfers a {@linkplain Task} to another {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket} while always setting the {@linkplain
* Task#isTransferred transfer} flag.
*
* @param taskId The id of the {@link Task} to be transferred
* @param workbasketKey The key of the target work basket
* @param domain The domain of the target work basket
* @return the transferred task
* @throws TaskNotFoundException Thrown if the {@link Task} with taskId was not found.
* @throws WorkbasketNotFoundException Thrown if the target work basket was not found.
* @throws NotAuthorizedException Thrown if the current user is not authorized to transfer this
* {@link Task} to the target work basket
* @throws InvalidStateException Thrown if the task is in a state which does not allow
* transferring
* @see #transfer(String, String, String, boolean)
*/
Task transfer(String taskId, String workbasketKey, String domain)
@SuppressWarnings("checkstyle:JavadocMethod")
default Task transfer(String taskId, String workbasketKey, String domain)
throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException,
InvalidStateException {
return transfer(taskId, workbasketKey, domain, true);
}
/**
* Transfers a {@linkplain Task} to another {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket}.
*
* <p>The transfer resets the read flag and sets the transfer flag if {@code setTransferFlag} is
* {@code true}.
*
* @param taskId the id of the {@linkplain Task} which should be transferred
* @param workbasketKey the key of the target {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket}
* @param domain the domain of the target {@linkplain pro.taskana.workbasket.api.models.Workbasket
* Workbasket}
* @param setTransferFlag the control about whether to set the {@linkplain Task#isTransferred()}
* flag or not
* @return the transferred {@linkplain Task}
* @throws TaskNotFoundException Thrown if the {@link Task} with taskId was not found.
* @throws WorkbasketNotFoundException Thrown if the target {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket} was not found.
* @throws NotAuthorizedException Thrown if the current user is not authorized to transfer this
* {@linkplain Task} to the target Workbasket
* @throws InvalidStateException Thrown if the {@linkplain Task} is in a state which does not
* allow transferring
*/
Task transfer(String taskId, String workbasketKey, String domain, boolean setTransferFlag)
throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException,
InvalidStateException;
@ -282,36 +326,84 @@ public interface TaskService {
InvalidStateException;
/**
* Transfers a list of tasks to an other workbasket. Exceptions will be thrown if the caller got
* no permissions on the target or it doesn´t exist. Other Exceptions will be stored and returned
* in the end.
* Transfers a list of {@linkplain Task Tasks} to another {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket} while always setting the {@linkplain
* Task#isTransferred transfer} flag.
*
* @param destinationWorkbasketId target workbasket id
* @param taskIds source task which will be moved
* @see #transferTasks(String, List, boolean)
*/
@SuppressWarnings("checkstyle:JavadocMethod")
default BulkOperationResults<String, TaskanaException> transferTasks(
String destinationWorkbasketId, List<String> taskIds)
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException {
return transferTasks(destinationWorkbasketId, taskIds, true);
}
/**
* Transfers a list of {@linkplain Task Tasks} to another {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket}.
*
* <p>The transfer resets the read flag and sets the transfer flag if {@code setTransferFlag} is
* {@code true}. Exceptions will be thrown if the caller got no permissions on the target or it
* does not exist. Other Exceptions will be stored and returned in the end.
*
* @param destinationWorkbasketId target {@linkplain pro.taskana.workbasket.api.models.Workbasket
* Workbasket} id
* @param taskIds list of source {@linkplain Task Tasks} which will be moved
* @param setTransferFlag the control about whether to set the {@linkplain Task#isTransferred()}
* flag or not
* @return Bulkresult with ID and Error in it for failed transactions.
* @throws NotAuthorizedException if the caller hasn´t permissions on tarket WB.
* @throws InvalidArgumentException if the method paramesters are EMPTY or NULL.
* @throws WorkbasketNotFoundException if the target WB can´t be found.
* @throws NotAuthorizedException if the caller has no permissions on target {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket}.
* @throws InvalidArgumentException if the method parameters are EMPTY or NULL.
* @throws WorkbasketNotFoundException if the target {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket} can not be found.
*/
BulkOperationResults<String, TaskanaException> transferTasks(
String destinationWorkbasketId, List<String> taskIds)
String destinationWorkbasketId, List<String> taskIds, boolean setTransferFlag)
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException;
/**
* Transfers a list of tasks to an other workbasket. Exceptions will be thrown if the caller got
* no permissions on the target or it doesn´t exist. Other Exceptions will be stored and returned
* in the end.
* Transfers a list of {@linkplain Task Tasks} to another {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket} while always setting the {@linkplain
* Task#isTransferred} flag.
*
* @param destinationWorkbasketKey target workbasket key
* @param destinationWorkbasketDomain target workbasket domain
* @param taskIds source task which will be moved
* @see #transferTasks(String, String, List, boolean)
*/
@SuppressWarnings("checkstyle:JavadocMethod")
default BulkOperationResults<String, TaskanaException> transferTasks(
String destinationWorkbasketKey, String destinationWorkbasketDomain, List<String> taskIds)
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException {
return transferTasks(destinationWorkbasketKey, destinationWorkbasketDomain, taskIds, true);
}
/**
* Transfers a list of {@linkplain Task Tasks} to another {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket}.
*
* <p>The transfer resets the read flag and sets the transfer flag if {@code setTransferFlag} is
* {@code true}. Exceptions will be thrown if the caller got no permissions on the target or it
* does not exist. Other Exceptions will be stored and returned in the end.
*
* @param destinationWorkbasketKey target {@linkplain pro.taskana.workbasket.api.models.Workbasket
* Workbasket} key
* @param destinationWorkbasketDomain target {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket} domain
* @param taskIds list of source {@linkplain Task Tasks} which will be moved
* @param setTransferFlag the control about whether to set the {@linkplain Task#isTransferred()}
* flag or not
* @return Bulkresult with ID and Error in it for failed transactions.
* @throws NotAuthorizedException if the caller hasn´t permissions on tarket WB.
* @throws InvalidArgumentException if the method paramesters are EMPTY or NULL.
* @throws WorkbasketNotFoundException if the target WB can´t be found.
* @throws NotAuthorizedException if the caller has no permissions on target {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket}.
* @throws InvalidArgumentException if the method parameters are EMPTY or NULL.
* @throws WorkbasketNotFoundException if the target {@linkplain
* pro.taskana.workbasket.api.models.Workbasket Workbasket} can not be found.
*/
BulkOperationResults<String, TaskanaException> transferTasks(
String destinationWorkbasketKey, String destinationWorkbasketDomain, List<String> taskIds)
String destinationWorkbasketKey,
String destinationWorkbasketDomain,
List<String> taskIds,
boolean setTransferFlag)
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException;
/**

View File

@ -330,17 +330,17 @@ public class TaskServiceImpl implements TaskService {
}
@Override
public Task transfer(String taskId, String destinationWorkbasketId)
public Task transfer(String taskId, String destinationWorkbasketId, boolean setTransferFlag)
throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException,
InvalidStateException {
return taskTransferrer.transfer(taskId, destinationWorkbasketId);
return taskTransferrer.transfer(taskId, destinationWorkbasketId, setTransferFlag);
}
@Override
public Task transfer(String taskId, String workbasketKey, String domain)
public Task transfer(String taskId, String workbasketKey, String domain, boolean setTransferFlag)
throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException,
InvalidStateException {
return taskTransferrer.transfer(taskId, workbasketKey, domain);
return taskTransferrer.transfer(taskId, workbasketKey, domain, setTransferFlag);
}
@Override
@ -450,17 +450,20 @@ public class TaskServiceImpl implements TaskService {
@Override
public BulkOperationResults<String, TaskanaException> transferTasks(
String destinationWorkbasketId, List<String> taskIds)
String destinationWorkbasketId, List<String> taskIds, boolean setTransferFlag)
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException {
return taskTransferrer.transferTasks(destinationWorkbasketId, taskIds);
return taskTransferrer.transferTasks(destinationWorkbasketId, taskIds, setTransferFlag);
}
@Override
public BulkOperationResults<String, TaskanaException> transferTasks(
String destinationWorkbasketKey, String destinationWorkbasketDomain, List<String> taskIds)
String destinationWorkbasketKey,
String destinationWorkbasketDomain,
List<String> taskIds,
boolean setTransferFlag)
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException {
return taskTransferrer.transferTasks(
destinationWorkbasketKey, destinationWorkbasketDomain, taskIds);
destinationWorkbasketKey, destinationWorkbasketDomain, taskIds, setTransferFlag);
}
@Override

View File

@ -57,7 +57,8 @@ class TaskTransferrer {
this.historyEventManager = taskanaEngine.getHistoryEventManager();
}
Task transfer(String taskId, String destinationWorkbasketKey, String domain)
Task transfer(
String taskId, String destinationWorkbasketKey, String domain, boolean setTransferFlag)
throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException,
InvalidStateException {
LOGGER.debug(
@ -88,9 +89,8 @@ class TaskTransferrer {
Workbasket destinationWorkbasket =
workbasketService.getWorkbasket(destinationWorkbasketKey, domain);
// reset read flag and set transferred flag
task.setRead(false);
task.setTransferred(true);
task.setTransferred(setTransferFlag);
// transfer task from source to destination workbasket
if (!destinationWorkbasket.isMarkedForDeletion()) {
@ -120,7 +120,7 @@ class TaskTransferrer {
}
}
Task transfer(String taskId, String destinationWorkbasketId)
Task transfer(String taskId, String destinationWorkbasketId, boolean setTransferFlag)
throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException,
InvalidStateException {
LOGGER.debug(
@ -146,9 +146,8 @@ class TaskTransferrer {
Workbasket destinationWorkbasket = workbasketService.getWorkbasket(destinationWorkbasketId);
// reset read flag and set transferred flag
task.setRead(false);
task.setTransferred(true);
task.setTransferred(setTransferFlag);
// transfer task from source to destination workbasket
if (!destinationWorkbasket.isMarkedForDeletion()) {
@ -178,7 +177,10 @@ class TaskTransferrer {
}
BulkOperationResults<String, TaskanaException> transferTasks(
String destinationWorkbasketKey, String destinationWorkbasketDomain, List<String> taskIds)
String destinationWorkbasketKey,
String destinationWorkbasketDomain,
List<String> taskIds,
boolean setTransferFlag)
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException {
try {
taskanaEngine.openConnection();
@ -198,7 +200,7 @@ class TaskTransferrer {
Workbasket destinationWorkbasket =
workbasketService.getWorkbasket(destinationWorkbasketKey, destinationWorkbasketDomain);
return transferTasks(taskIds, destinationWorkbasket);
return transferTasks(taskIds, destinationWorkbasket, setTransferFlag);
} finally {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
@ -214,7 +216,7 @@ class TaskTransferrer {
}
BulkOperationResults<String, TaskanaException> transferTasks(
String destinationWorkbasketId, List<String> taskIds)
String destinationWorkbasketId, List<String> taskIds, boolean setTransferFlag)
throws NotAuthorizedException, InvalidArgumentException, WorkbasketNotFoundException {
try {
taskanaEngine.openConnection();
@ -231,7 +233,7 @@ class TaskTransferrer {
}
Workbasket destinationWorkbasket = workbasketService.getWorkbasket(destinationWorkbasketId);
return transferTasks(taskIds, destinationWorkbasket);
return transferTasks(taskIds, destinationWorkbasket, setTransferFlag);
} finally {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
@ -245,7 +247,9 @@ class TaskTransferrer {
}
private BulkOperationResults<String, TaskanaException> transferTasks(
List<String> taskIdsToBeTransferred, Workbasket destinationWorkbasket)
List<String> taskIdsToBeTransferred,
Workbasket destinationWorkbasket,
boolean setTransferFlag)
throws InvalidArgumentException, WorkbasketNotFoundException, NotAuthorizedException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
@ -271,7 +275,7 @@ class TaskTransferrer {
List<MinimalTaskSummary> taskSummaries;
taskSummaries = taskMapper.findExistingTasks(taskIds, null);
checkIfTransferConditionsAreFulfilled(taskIds, taskSummaries, bulkLog);
updateTasksToBeTransferred(taskIds, taskSummaries, destinationWorkbasket);
updateTasksToBeTransferred(taskIds, taskSummaries, destinationWorkbasket, setTransferFlag);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("exit from transferTasks(), returning {}", bulkLog);
}
@ -372,7 +376,8 @@ class TaskTransferrer {
private void updateTasksToBeTransferred(
List<String> taskIds,
List<MinimalTaskSummary> taskSummaries,
Workbasket destinationWorkbasket) {
Workbasket destinationWorkbasket,
boolean setTransferFlag) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(
"entry to updateTasksToBeTransferred(taskIds = {}, taskSummaries = {}, "
@ -390,7 +395,7 @@ class TaskTransferrer {
Instant now = Instant.now();
TaskSummaryImpl updateObject = new TaskSummaryImpl();
updateObject.setRead(false);
updateObject.setTransferred(true);
updateObject.setTransferred(setTransferFlag);
updateObject.setWorkbasketSummary(destinationWorkbasket.asSummary());
updateObject.setDomain(destinationWorkbasket.getDomain());
updateObject.setModified(now);

View File

@ -26,6 +26,7 @@ import pro.taskana.task.api.TaskState;
import pro.taskana.task.api.exceptions.InvalidStateException;
import pro.taskana.task.api.exceptions.TaskNotFoundException;
import pro.taskana.task.api.models.Task;
import pro.taskana.task.api.models.TaskSummary;
import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException;
import pro.taskana.workbasket.api.models.Workbasket;
@ -397,4 +398,43 @@ class TransferTaskAccTest extends AbstractAccTest {
assertThat(transferredTask.getModified().isBefore(before)).isFalse();
assertThat(transferredTask.getOwner()).isNull();
}
@WithAccessId(user = "admin")
@Test
void should_NotSetTheTransferFlag_When_SetTransferFlagNotRequested() throws Exception {
TaskService taskService = taskanaEngine.getTaskService();
taskService.transfer(
"TKI:000000000000000000000000000000000003",
"WBI:100000000000000000000000000000000006",
false);
Task transferredTask = taskService.getTask("TKI:000000000000000000000000000000000003");
assertThat(transferredTask).isNotNull();
assertThat(transferredTask.isTransferred()).isFalse();
}
@WithAccessId(user = "admin")
@Test
void should_NotSetTheTransferFlagWithinBulkTransfer_When_SetTransferFlagNotRequested()
throws Exception {
TaskService taskService = taskanaEngine.getTaskService();
taskService.transferTasks(
"WBI:100000000000000000000000000000000006",
List.of(
"TKI:000000000000000000000000000000000003",
"TKI:000000000000000000000000000000000004",
"TKI:000000000000000000000000000000000005"),
false);
List<TaskSummary> transferredTasks =
taskService
.createTaskQuery()
.idIn(
"TKI:000000000000000000000000000000000004",
"TKI:000000000000000000000000000000000005",
"TKI:000000000000000000000000000000000003")
.list();
assertThat(transferredTasks).extracting(TaskSummary::isTransferred).containsOnly(false);
}
}

View File

@ -16,34 +16,34 @@
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name="Checker">
<module name = "Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<property name="severity" value="warning"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Excludes all 'module-info.java' files -->
<!-- See https://checkstyle.org/config_filefilters.html -->
<module name="BeforeExecutionExclusionFileFilter">
<property name="fileNamePattern" value="module\-info\.java$"/>
</module>
<!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
<module name="SuppressionFilter">
<property default="checkstyle-suppressions.xml" name="file"
value="${org.checkstyle.google.suppressionfilter.config}"/>
<property name="file" value="${org.checkstyle.google.suppressionfilter.config}"
default="checkstyle-suppressions.xml" />
<property name="optional" value="true"/>
</module>
<!-- Checks for whitespace -->
<!-- Checks for whitespace -->
<!-- See http://checkstyle.org/config_whitespace.html -->
<module name="FileTabCharacter">
<property name="eachLine" value="true"/>
</module>
<module name="LineLength">
<property name="fileExtensions" value="java"/>
<property name="max" value="100"/>
<property name="ignorePattern"
value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
</module>
<module name="NewlineAtEndOfFile"/>
<module name="SuppressWarningsFilter"/>
@ -81,11 +81,12 @@
value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE"/>
</module>
<module name="LeftCurly">
<property name="tokens" value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
OBJBLOCK, STATIC_INIT"/>
<property name="tokens"
value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
OBJBLOCK, STATIC_INIT, RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="RightCurly">
<property name="id" value="RightCurlySame"/>
@ -96,18 +97,21 @@
<module name="RightCurly">
<property name="id" value="RightCurlyAlone"/>
<property name="option" value="alone"/>
<property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF"/>
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/>
</module>
<module name="SuppressionXpathSingleFilter">
<!-- suppresion is required till https://github.com/checkstyle/checkstyle/issues/7541 -->
<property name="id" value="RightCurlyAlone"/>
<property name="query" value="//RCURLY[parent::SLIST[count(./*)=1]
or preceding-sibling::*[last()][self::LCURLY]]"/>
or preceding-sibling::*[last()][self::LCURLY]]"/>
</module>
<module name="WhitespaceAfter">
<property name="tokens" value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, DO_WHILE"/>
<property name="tokens"
value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE,
LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, DO_WHILE"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
@ -115,13 +119,15 @@
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<property name="tokens" value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
<property name="ignoreEnhancedForColon" value="false"/>
<property name="tokens"
value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
@ -135,8 +141,10 @@
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
<property name="tokens"
value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF"/>
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
@ -172,7 +180,8 @@
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF"/>
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
ANNOTATION_DEF, RECORD_DEF"/>
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
@ -201,11 +210,26 @@
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="PatternVariableName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Pattern variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordComponentName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Record component name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="RecordTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Record type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
@ -229,7 +253,7 @@
</module>
<module name="Indentation">
<property name="basicOffset" value="2"/>
<property name="braceAdjustment" value="0"/>
<property name="braceAdjustment" value="2"/>
<property name="caseIndent" value="2"/>
<property name="throwsIndent" value="4"/>
<property name="lineWrappingIndentation" value="4"/>
@ -239,8 +263,10 @@
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="1"/>
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, PATTERN_VARIABLE_DEF, RECORD_DEF,
RECORD_COMPONENT_DEF"/>
</module>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
@ -255,18 +281,21 @@
<module name="MethodParamPad">
<property name="tokens"
value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF"/>
SUPER_CTOR_CALL, ENUM_CONSTANT_DEF, RECORD_DEF"/>
</module>
<module name="NoWhitespaceBefore">
<property name="tokens" value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
LABELED_STAT, METHOD_REF"/>
<property name="tokens"
value="COMMA, SEMI, POST_INC, POST_DEC, DOT,
LABELED_STAT, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad">
<property name="tokens" value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA"/>
<property name="tokens"
value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA,
RECORD_DEF"/>
</module>
<module name="OperatorWrap">
<property name="option" value="NL"/>
@ -277,7 +306,8 @@
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens"
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF,
RECORD_DEF, COMPACT_CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
@ -293,6 +323,7 @@
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
</module>
<module name="JavadocParagraph"/>
<module name="RequireEmptyLineBeforeBlockTagGroup"/>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target"
@ -303,20 +334,29 @@
<module name="JavadocMethod">
<property name="validateThrows" value="true"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF"/>
<property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF, COMPACT_CTOR_DEF"/>
</module>
<!-- Team not ready for this -->
<!-- <module name="MissingJavadocMethod">-->
<!-- <property name="scope" value="public"/>-->
<!-- <property name="minLineCount" value="2"/>-->
<!-- <property name="allowedAnnotations" value="Override, Test"/>-->
<!-- <property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF"/>-->
<!-- <property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF,-->
<!-- COMPACT_CTOR_DEF"/>-->
<!-- </module>-->
<!-- <module name="MissingJavadocType">-->
<!-- <property name="scope" value="protected"/>-->
<!-- <property name="tokens"-->
<!-- value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF,-->
<!-- RECORD_DEF, ANNOTATION_DEF"/>-->
<!-- <property name="excludeScope" value="nothing"/>-->
<!-- </module>-->
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc"/>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
@ -325,8 +365,8 @@
</module>
<!-- https://checkstyle.org/config_filters.html#SuppressionXpathFilter -->
<module name="SuppressionXpathFilter">
<property default="checkstyle-xpath-suppressions.xml" name="file"
value="${org.checkstyle.google.suppressionxpathfilter.config}"/>
<property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}"
default="checkstyle-xpath-suppressions.xml" />
<property name="optional" value="true"/>
</module>
</module>

View File

@ -396,6 +396,7 @@ public class TaskController {
* @title Transfer a Task to another Workbasket
* @param taskId the Id of the Task which should be transferred
* @param workbasketId the Id of the destination Workbasket
* @param setTransferFlag sets the tansfer flag of the task (default: true)
* @return the successfully transferred Task.
* @throws TaskNotFoundException if the requested Task does not exist
* @throws WorkbasketNotFoundException if the requested Workbasket does not exist
@ -405,11 +406,15 @@ public class TaskController {
@PostMapping(path = RestEndpoints.URL_TASKS_ID_TRANSFER_WORKBASKET_ID)
@Transactional(rollbackFor = Exception.class)
public ResponseEntity<TaskRepresentationModel> transferTask(
@PathVariable String taskId, @PathVariable String workbasketId)
@PathVariable String taskId,
@PathVariable String workbasketId,
@RequestBody(required = false) Boolean setTransferFlag)
throws TaskNotFoundException, WorkbasketNotFoundException, NotAuthorizedException,
InvalidStateException {
LOGGER.debug("Entry to transferTask(taskId= {}, workbasketId= {})", taskId, workbasketId);
Task updatedTask = taskService.transfer(taskId, workbasketId);
Task updatedTask =
taskService.transfer(taskId, workbasketId, setTransferFlag == null || setTransferFlag);
ResponseEntity<TaskRepresentationModel> result =
ResponseEntity.ok(taskRepresentationModelAssembler.toModel(updatedTask));
if (LOGGER.isDebugEnabled()) {

View File

@ -12,11 +12,17 @@ import java.net.URL;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import javax.sql.DataSource;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.function.ThrowingConsumer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
@ -945,6 +951,51 @@ class TaskControllerIntTest {
.isEqualTo(HttpStatus.BAD_REQUEST);
}
@TestFactory
Stream<DynamicTest> should_SetTransferFlagDependentOnRequestBody_When_TransferringTask() {
Iterator<Boolean> iterator = Arrays.asList(true, false).iterator();
ThrowingConsumer<Boolean> test =
setTransferFlag -> {
ResponseEntity<TaskRepresentationModel> response =
TEMPLATE.exchange(
restHelper.toUrl(
RestEndpoints.URL_TASKS_ID_TRANSFER_WORKBASKET_ID,
"TKI:000000000000000000000000000000000003",
"WBI:100000000000000000000000000000000006"),
HttpMethod.POST,
new HttpEntity<>(setTransferFlag.toString(), restHelper.getHeadersAdmin()),
TASK_MODEL_TYPE);
TaskRepresentationModel task = response.getBody();
assertThat(task).isNotNull();
assertThat(task.getWorkbasketSummary().getWorkbasketId())
.isEqualTo("WBI:100000000000000000000000000000000006");
assertThat(task.isTransferred()).isEqualTo(setTransferFlag);
};
return DynamicTest.stream(iterator, c -> "for setTransferFlag: " + c, test);
}
@Test
void should_SetTransferFlagToTrue_When_TransferringWithoutRequestBody() {
ResponseEntity<TaskRepresentationModel> response =
TEMPLATE.exchange(
restHelper.toUrl(
RestEndpoints.URL_TASKS_ID_TRANSFER_WORKBASKET_ID,
"TKI:000000000000000000000000000000000003",
"WBI:100000000000000000000000000000000006"),
HttpMethod.POST,
new HttpEntity<>(restHelper.getHeadersAdmin()),
TASK_MODEL_TYPE);
TaskRepresentationModel task = response.getBody();
assertThat(task).isNotNull();
assertThat(task.getWorkbasketSummary().getWorkbasketId())
.isEqualTo("WBI:100000000000000000000000000000000006");
assertThat(task.isTransferred()).isTrue();
}
private TaskRepresentationModel getTaskResourceSample() {
ClassificationSummaryRepresentationModel classificationResource =
new ClassificationSummaryRepresentationModel();