Skip to content

Commit 00ce680

Browse files
"Not In" query for task definition keys (#4972)
related to /issues/4968 --------- Co-authored-by: Gergely Juhasz <25517896+venetrius@users.noreply.github.com>
1 parent 8e9a68a commit 00ce680

File tree

10 files changed

+193
-0
lines changed

10 files changed

+193
-0
lines changed

engine-rest/engine-rest-openapi/src/main/templates/lib/commons/task-query-params.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,12 @@
271271
type = "string"
272272
desc = "Restrict to tasks that have one of the given keys. The keys need to be in a
273273
comma-separated list." />
274+
275+
<@lib.parameter name = "taskDefinitionKeyNotIn"
276+
location = "query"
277+
type = "string"
278+
desc = "Exclude instances by a list of task definition keys. The keys need to be in a
279+
comma-separated list." />
274280

275281
<@lib.parameter name = "taskDefinitionKeyLike"
276282
location = "query"

engine-rest/engine-rest-openapi/src/main/templates/models/org/camunda/bpm/engine/rest/dto/runtime/task/TaskQueryDto.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,12 @@
281281
itemType = "string"
282282
desc = "Restrict to tasks that have one of the given keys. The keys need to be in a comma-separated list." />
283283

284+
<@lib.property
285+
name = "taskDefinitionKeyNotIn"
286+
type = "array"
287+
itemType = "string"
288+
desc = "Exclude instances by a list of task definition keys. The keys need to be in a comma-separated list." />
289+
284290
<@lib.property
285291
name = "taskDefinitionKeyLike"
286292
type = "string"

engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/task/TaskQueryDto.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ public class TaskQueryDto extends AbstractQueryDto<TaskQuery> {
137137
private Boolean includeAssignedTasks;
138138
private String taskDefinitionKey;
139139
private String[] taskDefinitionKeyIn;
140+
private String[] taskDefinitionKeyNotIn;
140141
private String taskDefinitionKeyLike;
141142
private String taskId;
142143
private String[] taskIdIn;
@@ -408,6 +409,11 @@ public void setTaskDefinitionKeyIn(String[] taskDefinitionKeyIn) {
408409
this.taskDefinitionKeyIn = taskDefinitionKeyIn;
409410
}
410411

412+
@CamundaQueryParam(value = "taskDefinitionKeyNotIn", converter= StringArrayConverter.class)
413+
public void setTaskDefinitionKeyNotIn(String[] taskDefinitionKeyNotIn) {
414+
this.taskDefinitionKeyNotIn = taskDefinitionKeyNotIn;
415+
}
416+
411417
@CamundaQueryParam("taskDefinitionKeyLike")
412418
public void setTaskDefinitionKeyLike(String taskDefinitionKeyLike) {
413419
this.taskDefinitionKeyLike = taskDefinitionKeyLike;
@@ -855,6 +861,10 @@ public String[] getTaskDefinitionKeyIn() {
855861
return taskDefinitionKeyIn;
856862
}
857863

864+
public String[] getTaskDefinitionKeyNotIn() {
865+
return taskDefinitionKeyNotIn;
866+
}
867+
858868
public String getTaskDefinitionKey() {
859869
return taskDefinitionKey;
860870
}
@@ -1209,6 +1219,9 @@ protected void applyFilters(TaskQuery query) {
12091219
if (taskDefinitionKeyIn != null && taskDefinitionKeyIn.length > 0) {
12101220
query.taskDefinitionKeyIn(taskDefinitionKeyIn);
12111221
}
1222+
if (taskDefinitionKeyNotIn != null && taskDefinitionKeyNotIn.length > 0) {
1223+
query.taskDefinitionKeyNotIn(taskDefinitionKeyNotIn);
1224+
}
12121225
if (taskDefinitionKey != null) {
12131226
query.taskDefinitionKey(taskDefinitionKey);
12141227
}
@@ -1615,6 +1628,7 @@ public static TaskQueryDto fromQuery(Query<?, ?> query, boolean isOrQueryActive)
16151628
dto.assigneeLike = taskQuery.getAssigneeLike();
16161629
dto.taskDefinitionKey = taskQuery.getKey();
16171630
dto.taskDefinitionKeyIn = taskQuery.getKeys();
1631+
dto.taskDefinitionKeyNotIn = taskQuery.getKeyNotIn();
16181632
dto.taskDefinitionKeyLike = taskQuery.getKeyLike();
16191633
dto.description = taskQuery.getDescription();
16201634
dto.descriptionLike = taskQuery.getDescriptionLike();

engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/TaskRestServiceQueryTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ public void testAdditionalParametersExcludingVariables() {
430430
.queryParams(booleanQueryParameters)
431431
.queryParam("activityInstanceIdIn", arrayAsCommaSeperatedList(arrayQueryParameters.get("activityInstanceIdIn")))
432432
.queryParam("taskDefinitionKeyIn", arrayAsCommaSeperatedList(arrayQueryParameters.get("taskDefinitionKeyIn")))
433+
.queryParam("taskDefinitionKeyNotIn", arrayAsCommaSeperatedList(arrayQueryParameters.get("taskDefinitionKeyNotIn")))
433434
.queryParam("taskIdIn", arrayAsCommaSeperatedList(arrayQueryParameters.get("taskIdIn")))
434435
.queryParam("processDefinitionKeyIn", arrayAsCommaSeperatedList(arrayQueryParameters.get("processDefinitionKeyIn")))
435436
.queryParam("processInstanceBusinessKeyIn", arrayAsCommaSeperatedList(arrayQueryParameters.get("processInstanceBusinessKeyIn")))
@@ -472,6 +473,7 @@ private Map<String, String[]> getCompleteStringArrayQueryParameters() {
472473

473474
String[] activityInstanceIds = { "anActivityInstanceId", "anotherActivityInstanceId" };
474475
String[] taskDefinitionKeys = { "aTaskDefinitionKey", "anotherTaskDefinitionKey" };
476+
String[] taskDefinitionKeyNotIn = { "anUnwantedTaskDefinitionKey", "anotherUnwantedTaskDefinitionKey" };
475477
String[] processDefinitionKeys = { "aProcessDefinitionKey", "anotherProcessDefinitionKey" };
476478
String[] processInstanceBusinessKeys = { "aBusinessKey", "anotherBusinessKey" };
477479
String[] tenantIds = { MockProvider.EXAMPLE_TENANT_ID, MockProvider.ANOTHER_EXAMPLE_TENANT_ID };
@@ -483,6 +485,7 @@ private Map<String, String[]> getCompleteStringArrayQueryParameters() {
483485

484486
parameters.put("activityInstanceIdIn", activityInstanceIds);
485487
parameters.put("taskDefinitionKeyIn", taskDefinitionKeys);
488+
parameters.put("taskDefinitionKeyNotIn", taskDefinitionKeyNotIn);
486489
parameters.put("taskIdIn", taskId);
487490
parameters.put("processDefinitionKeyIn", processDefinitionKeys);
488491
parameters.put("processInstanceBusinessKeyIn", processInstanceBusinessKeys);
@@ -596,6 +599,7 @@ private void verifyStringArrayParametersInvocations() {
596599

597600
verify(mockQuery).activityInstanceIdIn(stringArrayParameters.get("activityInstanceIdIn"));
598601
verify(mockQuery).taskDefinitionKeyIn(stringArrayParameters.get("taskDefinitionKeyIn"));
602+
verify(mockQuery).taskDefinitionKeyNotIn(stringArrayParameters.get("taskDefinitionKeyNotIn"));
599603
verify(mockQuery).processDefinitionKeyIn(stringArrayParameters.get("processDefinitionKeyIn"));
600604
verify(mockQuery).processInstanceBusinessKeyIn(stringArrayParameters.get("processInstanceBusinessKeyIn"));
601605
verify(mockQuery).tenantIdIn(stringArrayParameters.get("tenantIdIn"));

engine/src/main/java/org/camunda/bpm/engine/impl/TaskQueryImpl.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ public class TaskQueryImpl extends AbstractQuery<TaskQuery, Task> implements Tas
132132
protected String key;
133133
protected String keyLike;
134134
protected String[] taskDefinitionKeys;
135+
protected String[] taskDefinitionKeyNotIn;
135136
protected String processDefinitionKey;
136137
protected String[] processDefinitionKeys;
137138
protected String processDefinitionId;
@@ -669,6 +670,12 @@ public TaskQuery taskDefinitionKeyIn(String... taskDefinitionKeys) {
669670
this.taskDefinitionKeys = taskDefinitionKeys;
670671
return this;
671672
}
673+
674+
@Override
675+
public TaskQuery taskDefinitionKeyNotIn(String... taskDefinitionKeyNotIn) {
676+
this.taskDefinitionKeyNotIn = taskDefinitionKeyNotIn;
677+
return this;
678+
}
672679

673680
@Override
674681
public TaskQuery taskParentTaskId(String taskParentTaskId) {
@@ -1100,6 +1107,7 @@ protected boolean hasExcludingConditions() {
11001107
|| CompareUtil.areNotInAscendingOrder(followUpAfter, followUpDate, followUpBefore)
11011108
|| CompareUtil.areNotInAscendingOrder(createTimeAfter, createTime, createTimeBefore)
11021109
|| CompareUtil.elementIsNotContainedInArray(key, taskDefinitionKeys)
1110+
|| CompareUtil.elementIsContainedInArray(key, taskDefinitionKeyNotIn)
11031111
|| CompareUtil.elementIsNotContainedInArray(processDefinitionKey, processDefinitionKeys)
11041112
|| CompareUtil.elementIsNotContainedInArray(processInstanceBusinessKey, processInstanceBusinessKeys);
11051113
}
@@ -1675,6 +1683,10 @@ public String getKey() {
16751683
public String[] getKeys() {
16761684
return taskDefinitionKeys;
16771685
}
1686+
1687+
public String[] getKeyNotIn() {
1688+
return taskDefinitionKeyNotIn;
1689+
}
16781690

16791691
public String getKeyLike() {
16801692
return keyLike;
@@ -1804,6 +1816,10 @@ public String[] getTaskDefinitionKeys() {
18041816
return taskDefinitionKeys;
18051817
}
18061818

1819+
public String[] getTaskDefinitionKeyNotIn() {
1820+
return taskDefinitionKeyNotIn;
1821+
}
1822+
18071823
public boolean getIsTenantIdSet() {
18081824
return isWithoutTenantId;
18091825
}
@@ -2100,6 +2116,13 @@ else if (this.getKeyLike() != null) {
21002116
else if (this.getKeys() != null) {
21012117
extendedQuery.taskDefinitionKeyIn(this.getKeys());
21022118
}
2119+
2120+
if (extendingQuery.getKeyNotIn() != null) {
2121+
extendedQuery.taskDefinitionKeyNotIn(extendingQuery.getKeyNotIn());
2122+
}
2123+
else if (this.getKeyNotIn() != null) {
2124+
extendedQuery.taskDefinitionKeyNotIn(this.getKeyNotIn());
2125+
}
21032126

21042127
if (extendingQuery.getParentTaskId() != null) {
21052128
extendedQuery.taskParentTaskId(extendingQuery.getParentTaskId());

engine/src/main/java/org/camunda/bpm/engine/impl/json/JsonTaskQueryConverter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public class JsonTaskQueryConverter extends JsonObjectConverter<TaskQuery> {
8080
public static final String UPDATED_AFTER = "updatedAfter";
8181
public static final String KEY = "key";
8282
public static final String KEYS = "keys";
83+
public static final String KEY_NOT_IN = "keyNotIn";
8384
public static final String KEY_LIKE = "keyLike";
8485
public static final String PARENT_TASK_ID = "parentTaskId";
8586
public static final String PROCESS_DEFINITION_KEY = "processDefinitionKey";
@@ -186,6 +187,7 @@ public JsonObject toJsonObject(TaskQuery taskQuery, boolean isOrQueryActive) {
186187
JsonUtil.addDateField(json, UPDATED_AFTER, query.getUpdatedAfter());
187188
JsonUtil.addField(json, KEY, query.getKey());
188189
JsonUtil.addArrayField(json, KEYS, query.getKeys());
190+
JsonUtil.addArrayField(json, KEY_NOT_IN, query.getKeyNotIn());
189191
JsonUtil.addField(json, KEY_LIKE, query.getKeyLike());
190192
JsonUtil.addField(json, PARENT_TASK_ID, query.getParentTaskId());
191193
JsonUtil.addField(json, PROCESS_DEFINITION_KEY, query.getProcessDefinitionKey());
@@ -416,6 +418,9 @@ protected TaskQuery toObject(JsonObject json, boolean isOrQuery) {
416418
if (json.has(KEYS)) {
417419
query.taskDefinitionKeyIn(getArray(JsonUtil.getArray(json, KEYS)));
418420
}
421+
if (json.has(KEY_NOT_IN)) {
422+
query.taskDefinitionKeyNotIn(getArray(JsonUtil.getArray(json, KEY_NOT_IN)));
423+
}
419424
if (json.has(KEY_LIKE)) {
420425
query.taskDefinitionKeyLike(JsonUtil.getString(json, KEY_LIKE));
421426
}

engine/src/main/java/org/camunda/bpm/engine/task/TaskQuery.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,11 @@ public interface TaskQuery extends Query<TaskQuery, Task> {
494494
**/
495495
TaskQuery taskDefinitionKeyIn(String... taskDefinitionKeys);
496496

497+
/**
498+
* Only select tasks which do not have one of the taskDefinitionKeys.
499+
**/
500+
TaskQuery taskDefinitionKeyNotIn(String... taskDefinitionKeys);
501+
497502
/**
498503
* Select the tasks which are sub tasks of the given parent task.
499504
*/

engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/Task.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,13 @@
486486
#{item}
487487
</foreach>
488488
</if>
489+
<if test="query.taskDefinitionKeyNotIn != null &amp;&amp; query.taskDefinitionKeyNotIn.length > 0">
490+
${queryType} RES.TASK_DEF_KEY_ not in
491+
<foreach item="item" index="index" collection="query.taskDefinitionKeyNotIn"
492+
open="(" separator="," close=")">
493+
#{item}
494+
</foreach>
495+
</if>
489496
<if test="query.processDefinitionId != null">
490497
${queryType} RES.PROC_DEF_ID_ = #{query.processDefinitionId}
491498
</if>

engine/src/test/java/org/camunda/bpm/engine/test/api/filter/FilterTaskQueryTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ public void testTaskQuery() {
206206
query.taskUpdatedAfterExpression(testString);
207207
query.taskDefinitionKey(testString);
208208
query.taskDefinitionKeyIn(testKeys);
209+
query.taskDefinitionKeyNotIn(testKeys);
209210
query.taskDefinitionKeyLike(testString);
210211
query.processDefinitionKey(testString);
211212
query.processDefinitionKeyIn(testKeys);
@@ -321,6 +322,10 @@ public void testTaskQuery() {
321322
for (int i = 0; i < query.getKeys().length; i++) {
322323
assertEquals(testKeys[i], query.getKeys()[i]);
323324
}
325+
assertEquals(testKeys.length, query.getKeyNotIn().length);
326+
for (int i = 0; i < query.getKeyNotIn().length; i++) {
327+
assertEquals(testKeys[i], query.getKeyNotIn()[i]);
328+
}
324329
assertEquals(testString, query.getKeyLike());
325330
assertEquals(testString, query.getProcessDefinitionKey());
326331
for (int i = 0; i < query.getProcessDefinitionKeys().length; i++) {

engine/src/test/java/org/camunda/bpm/engine/test/api/task/TaskQueryTest.java

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,89 @@ public void testTaskDefinitionKeyIn() throws Exception {
11161116
assertEquals(0l, count.longValue());
11171117
}
11181118

1119+
@Test
1120+
@Deployment(resources="org/camunda/bpm/engine/test/api/task/taskDefinitionProcess.bpmn20.xml")
1121+
public void testTaskDefinitionKeyNotInNoKeysProvided() {
1122+
1123+
// Given
1124+
// Start process instance, 2 tasks will be available with:
1125+
// - process definition key "taskDefinitionKeyProcess"
1126+
// - task definition keys "taskKey_1" & "taskKey_123"
1127+
runtimeService.startProcessInstanceByKey("taskDefinitionKeyProcess");
1128+
1129+
// When
1130+
var tasks = taskService.createTaskQuery()
1131+
.processDefinitionKey("taskDefinitionKeyProcess")
1132+
.taskDefinitionKeyNotIn()
1133+
.list();
1134+
// Then
1135+
assertThat(tasks)
1136+
.extracting(Task::getTaskDefinitionKey)
1137+
.containsExactly("taskKey_1", "taskKey_123");
1138+
}
1139+
1140+
@Test
1141+
@Deployment(resources="org/camunda/bpm/engine/test/api/task/taskDefinitionProcess.bpmn20.xml")
1142+
public void testTaskDefinitionKeyNotInOneKeyProvided() {
1143+
1144+
// Given
1145+
// Start process instance, 2 tasks will be available with:
1146+
// - process definition key "taskDefinitionKeyProcess"
1147+
// - task definition keys "taskKey_1" & "taskKey_123"
1148+
runtimeService.startProcessInstanceByKey("taskDefinitionKeyProcess");
1149+
1150+
// When
1151+
var tasks = taskService.createTaskQuery()
1152+
.processDefinitionKey("taskDefinitionKeyProcess")
1153+
.taskDefinitionKeyNotIn("taskKey_1")
1154+
.list();
1155+
// Then
1156+
assertThat(tasks)
1157+
.extracting(Task::getTaskDefinitionKey)
1158+
.containsExactly("taskKey_123");
1159+
}
1160+
1161+
@Test
1162+
@Deployment(resources="org/camunda/bpm/engine/test/api/task/taskDefinitionProcess.bpmn20.xml")
1163+
public void testTaskDefinitionKeyNotInAllKeysProvided() {
1164+
1165+
// Given
1166+
// Start process instance, 2 tasks will be available with:
1167+
// - process definition key "taskDefinitionKeyProcess"
1168+
// - task definition keys "taskKey_1" & "taskKey_123"
1169+
runtimeService.startProcessInstanceByKey("taskDefinitionKeyProcess");
1170+
1171+
// When
1172+
var tasks = taskService.createTaskQuery()
1173+
.processDefinitionKey("taskDefinitionKeyProcess")
1174+
.taskDefinitionKeyNotIn("taskKey_1", "taskKey_123")
1175+
.list();
1176+
// Then
1177+
assertThat(tasks)
1178+
.isEmpty();
1179+
}
1180+
1181+
@Test
1182+
@Deployment(resources="org/camunda/bpm/engine/test/api/task/taskDefinitionProcess.bpmn20.xml")
1183+
public void testTaskDefinitionKeyNotInInvalidKeyProvided() {
1184+
1185+
// Given
1186+
// Start process instance, 2 tasks will be available with:
1187+
// - process definition key "taskDefinitionKeyProcess"
1188+
// - task definition keys "taskKey_1" & "taskKey_123"
1189+
runtimeService.startProcessInstanceByKey("taskDefinitionKeyProcess");
1190+
1191+
// When
1192+
var tasks = taskService.createTaskQuery()
1193+
.processDefinitionKey("taskDefinitionKeyProcess")
1194+
.taskDefinitionKeyNotIn("I do not exist", "I don't exist either")
1195+
.list();
1196+
// Then
1197+
assertThat(tasks)
1198+
.extracting(Task::getTaskDefinitionKey)
1199+
.containsExactly("taskKey_1", "taskKey_123");
1200+
}
1201+
11191202
@Deployment(resources="org/camunda/bpm/engine/test/api/oneTaskProcess.bpmn20.xml")
11201203
@Test
11211204
public void testTaskVariableNameEqualsIgnoreCase() throws Exception {
@@ -5372,6 +5455,41 @@ public void testExtendingTaskQueryList_TaskDefinitionKeyIn() {
53725455
assertEquals(taskDefinitionKey, key[0]);
53735456
}
53745457

5458+
@Test
5459+
public void testExtendTaskQueryList_TaskDefinitionKeyNotIn() {
5460+
// given
5461+
var taskDefinitionKey = "someKey";
5462+
var query = taskService.createTaskQuery()
5463+
.taskDefinitionKeyNotIn(taskDefinitionKey);
5464+
5465+
var extendingQuery = taskService.createTaskQuery();
5466+
5467+
// when
5468+
var result = ((TaskQueryImpl)query).extend(extendingQuery);
5469+
5470+
// then
5471+
assertThat(((TaskQueryImpl) result).getKeyNotIn())
5472+
.containsExactly(taskDefinitionKey);
5473+
}
5474+
5475+
@Test
5476+
public void testExtendingTaskQueryList_TaskDefinitionKeyNotIn() {
5477+
// given
5478+
var taskDefinitionKey = "someKey";
5479+
var query = taskService.createTaskQuery();
5480+
5481+
var extendingQuery = taskService
5482+
.createTaskQuery()
5483+
.taskDefinitionKeyNotIn(taskDefinitionKey);
5484+
5485+
// when
5486+
var result = ((TaskQueryImpl)query).extend(extendingQuery);
5487+
5488+
// then
5489+
assertThat(((TaskQueryImpl) result).getKeyNotIn())
5490+
.containsExactly(taskDefinitionKey);
5491+
}
5492+
53755493
@Test
53765494
public void testQueryWithCandidateUsers() {
53775495
BpmnModelInstance process = Bpmn.createExecutableProcess("process")

0 commit comments

Comments
 (0)