TSK-1837: Add within and notWithin filter criteria

This commit is contained in:
ryzheboka 2022-06-22 14:53:24 +02:00 committed by Mustapha Zorgati
parent 18ee26ba80
commit 803b4b20a2
10 changed files with 863 additions and 69 deletions

View File

@ -0,0 +1,64 @@
package pro.taskana.common.api;
import java.util.Objects;
/**
* IntInterval captures an Integer interval. A fixed interval has defined begin and end. An open
* ended interval has either begin == null or end ==null.
*/
public class IntInterval {
private Integer begin;
private Integer end;
public IntInterval(Integer begin, Integer end) {
this.begin = begin;
this.end = end;
}
public boolean isValid() {
boolean isValid = begin != null || end != null;
if (begin != null && end != null && begin > end) {
isValid = false;
}
return isValid;
}
public Integer getBegin() {
return begin;
}
public void setBegin(Integer begin) {
this.begin = begin;
}
public Integer getEnd() {
return end;
}
public void setEnd(Integer end) {
this.end = end;
}
@Override
public int hashCode() {
return Objects.hash(begin, end);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof IntInterval)) {
return false;
}
IntInterval other = (IntInterval) obj;
return Objects.equals(begin, other.begin) && Objects.equals(end, other.end);
}
@Override
public String toString() {
return "IntInterval [" + "begin=" + this.begin + ", end=" + this.end + "]";
}
}

View File

@ -59,7 +59,7 @@ public class SqlProviderUtil {
return whereNotIn(collection, column, new StringBuilder());
}
public static StringBuilder whereInTime(String collection, String column, StringBuilder sb) {
public static StringBuilder whereInInterval(String collection, String column, StringBuilder sb) {
return sb.append("<if test='")
.append(collection)
.append(" !=null'> AND (<foreach item='item' collection='")
@ -73,11 +73,12 @@ public class SqlProviderUtil {
.append(" &lt;=#{item.end} </if>)</foreach>)</if> ");
}
public static StringBuilder whereInTime(String collection, String column) {
return whereInTime(collection, column, new StringBuilder());
public static StringBuilder whereInInterval(String collection, String column) {
return whereInInterval(collection, column, new StringBuilder());
}
public static StringBuilder whereNotInTime(String collection, String column, StringBuilder sb) {
public static StringBuilder whereNotInInterval(
String collection, String column, StringBuilder sb) {
return sb.append("<if test='")
.append(collection)
.append(" !=null'> AND (<foreach item='item' collection='")
@ -91,8 +92,8 @@ public class SqlProviderUtil {
.append(" &gt; #{item.end} </if>)</foreach>)</if> ");
}
public static StringBuilder whereNotInTime(String collection, String column) {
return whereNotInTime(collection, column, new StringBuilder());
public static StringBuilder whereNotInInterval(String collection, String column) {
return whereNotInInterval(collection, column, new StringBuilder());
}
public static StringBuilder whereLike(String collection, String column, StringBuilder sb) {
@ -150,6 +151,8 @@ public class SqlProviderUtil {
String column = baseColumn + "_" + x;
whereIn(baseCollection + x + "In", column, sb);
whereNotIn(baseCollection + x + "NotIn", column, sb);
whereInInterval(baseCollection + x + "Within", column, sb);
whereNotInInterval(baseCollection + x + "NotWithin", column, sb);
});
return sb;
}

View File

@ -13,6 +13,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Nested;
@ -24,10 +25,12 @@ import org.junit.jupiter.api.function.ThrowingConsumer;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.common.api.IntInterval;
import pro.taskana.common.api.KeyDomain;
import pro.taskana.common.api.TimeInterval;
import pro.taskana.common.api.security.CurrentUserContext;
import pro.taskana.common.internal.util.Pair;
import pro.taskana.common.internal.util.Quadruple;
import pro.taskana.common.internal.util.Triplet;
import pro.taskana.task.api.CallbackState;
import pro.taskana.task.api.TaskCustomField;
@ -235,7 +238,7 @@ class TaskQueryImplAccTest {
.customAttribute(TaskCustomField.CUSTOM_14, "custom14")
.customAttribute(TaskCustomField.CUSTOM_15, "custom15")
.customAttribute(TaskCustomField.CUSTOM_16, "custom16")
.customIntField(TaskCustomIntField.CUSTOM_INT_1, (Integer) 1)
.customIntField(TaskCustomIntField.CUSTOM_INT_1, 1)
.customIntField(TaskCustomIntField.CUSTOM_INT_2, 2)
.customIntField(TaskCustomIntField.CUSTOM_INT_3, 3)
.customIntField(TaskCustomIntField.CUSTOM_INT_4, 4)
@ -3295,6 +3298,69 @@ class TaskQueryImplAccTest {
taskSummary3 = taskInWorkbasket(wb).buildAndStoreAsSummary(taskService);
}
@WithAccessId(user = "user-1-1")
@TestFactory
Stream<DynamicTest> should_ThrowException_When_QueryingForCustomIntWithinInvalidInterval() {
List<Quadruple<String, TaskCustomIntField, IntInterval, IntInterval>> testCases =
List.of(
Quadruple.of(
"CustomInt1",
TaskCustomIntField.CUSTOM_INT_1,
new IntInterval(4, 1),
new IntInterval(-10, -8)),
Quadruple.of(
"CustomInt2",
TaskCustomIntField.CUSTOM_INT_2,
new IntInterval(null, null),
new IntInterval(0, null)),
Quadruple.of(
"CustomInt3",
TaskCustomIntField.CUSTOM_INT_3,
new IntInterval(-1, 5),
new IntInterval(null, null)),
Quadruple.of(
"CustomInt4",
TaskCustomIntField.CUSTOM_INT_4,
new IntInterval(0, -5),
new IntInterval(-2, -10)),
Quadruple.of(
"CustomInt5",
TaskCustomIntField.CUSTOM_INT_5,
new IntInterval(null, null),
new IntInterval(0, -50)),
Quadruple.of(
"CustomInt6",
TaskCustomIntField.CUSTOM_INT_6,
new IntInterval(4, 9),
new IntInterval(0, -5)),
Quadruple.of(
"CustomInt7",
TaskCustomIntField.CUSTOM_INT_7,
new IntInterval(null, null),
new IntInterval(null, null)),
Quadruple.of(
"CustomInt8",
TaskCustomIntField.CUSTOM_INT_8,
new IntInterval(123, 122),
new IntInterval(1, 0)));
ThrowingConsumer<Quadruple<String, TaskCustomIntField, IntInterval, IntInterval>> test =
q -> {
ThrowingCallable result =
() ->
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.customIntAttributeWithin(q.getSecond(), q.getThird(), q.getFourth())
.list();
assertThatThrownBy(result)
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("IntInterval");
};
return DynamicTest.stream(testCases.iterator(), Quadruple::getFirst, test);
}
@WithAccessId(user = "user-1-1")
@TestFactory
Stream<DynamicTest> should_ApplyFilter_When_QueryingForCustomIntIn() {
@ -3350,6 +3416,126 @@ class TaskQueryImplAccTest {
return DynamicTest.stream(testCases.iterator(), Triplet::getLeft, test);
}
@WithAccessId(user = "user-1-1")
@TestFactory
Stream<DynamicTest> should_ApplyFilter_When_QueryingForCustomIntWithin() {
List<Quadruple<String, TaskCustomIntField, IntInterval, IntInterval>> testCases =
List.of(
Quadruple.of(
"CustomInt1",
TaskCustomIntField.CUSTOM_INT_1,
new IntInterval(1, 1),
new IntInterval(-10, -8)),
Quadruple.of(
"CustomInt2",
TaskCustomIntField.CUSTOM_INT_2,
new IntInterval(0, null),
new IntInterval(0, null)),
Quadruple.of(
"CustomInt3",
TaskCustomIntField.CUSTOM_INT_3,
new IntInterval(-1, 5),
new IntInterval(0, null)),
Quadruple.of(
"CustomInt4",
TaskCustomIntField.CUSTOM_INT_4,
new IntInterval(0, 1),
new IntInterval(-2, 22)),
Quadruple.of(
"CustomInt5",
TaskCustomIntField.CUSTOM_INT_5,
new IntInterval(3, 9),
new IntInterval(-1000, -50)),
Quadruple.of(
"CustomInt6",
TaskCustomIntField.CUSTOM_INT_6,
new IntInterval(4, 9),
new IntInterval(0, null)),
Quadruple.of(
"CustomInt7",
TaskCustomIntField.CUSTOM_INT_7,
new IntInterval(4, 9),
new IntInterval(11, 22)),
Quadruple.of(
"CustomInt8",
TaskCustomIntField.CUSTOM_INT_8,
new IntInterval(123, 124),
new IntInterval(1, null)));
ThrowingConsumer<Quadruple<String, TaskCustomIntField, IntInterval, IntInterval>> test =
q -> {
List<TaskSummary> result =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.customIntAttributeWithin(q.getSecond(), q.getThird(), q.getFourth())
.list();
assertThat(result).containsExactly(taskSummary1);
};
return DynamicTest.stream(testCases.iterator(), Quadruple::getFirst, test);
}
@WithAccessId(user = "user-1-1")
@TestFactory
Stream<DynamicTest> should_ApplyFilter_When_QueryingForCustomIntNotWithin() {
List<Quadruple<String, TaskCustomIntField, IntInterval, IntInterval>> testCases =
List.of(
Quadruple.of(
"CustomInt1",
TaskCustomIntField.CUSTOM_INT_1,
new IntInterval(1, 1),
new IntInterval(0, 10)),
Quadruple.of(
"CustomInt2",
TaskCustomIntField.CUSTOM_INT_2,
new IntInterval(0, null),
new IntInterval(0, null)),
Quadruple.of(
"CustomInt3",
TaskCustomIntField.CUSTOM_INT_3,
new IntInterval(-1, 5),
new IntInterval(2, 25)),
Quadruple.of(
"CustomInt4",
TaskCustomIntField.CUSTOM_INT_4,
new IntInterval(-3, 9),
new IntInterval(-2, 22)),
Quadruple.of(
"CustomInt5",
TaskCustomIntField.CUSTOM_INT_5,
new IntInterval(3, 9),
new IntInterval(-1000, 1000)),
Quadruple.of(
"CustomInt6",
TaskCustomIntField.CUSTOM_INT_6,
new IntInterval(4, 9),
new IntInterval(0, null)),
Quadruple.of(
"CustomInt7",
TaskCustomIntField.CUSTOM_INT_7,
new IntInterval(4, 9),
new IntInterval(null, 22)),
Quadruple.of(
"CustomInt8",
TaskCustomIntField.CUSTOM_INT_8,
new IntInterval(0, 124),
new IntInterval(1, null)));
ThrowingConsumer<Quadruple<String, TaskCustomIntField, IntInterval, IntInterval>> test =
q -> {
List<TaskSummary> result =
taskService
.createTaskQuery()
.workbasketIdIn(wb.getId())
.customIntAttributeNotWithin(q.getSecond(), q.getThird(), q.getFourth())
.list();
assertThat(result).containsExactly(taskSummary2);
};
return DynamicTest.stream(testCases.iterator(), Quadruple::getFirst, test);
}
}
@Nested

View File

@ -1,6 +1,7 @@
package pro.taskana.task.api;
import pro.taskana.common.api.BaseQuery;
import pro.taskana.common.api.IntInterval;
import pro.taskana.common.api.KeyDomain;
import pro.taskana.common.api.TimeInterval;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
@ -1706,6 +1707,33 @@ public interface TaskQuery extends BaseQuery<TaskSummary, TaskQueryColumnName> {
TaskQuery customIntAttributeNotIn(TaskCustomIntField customIntField, Integer... searchArguments)
throws InvalidArgumentException;
/**
* Add the values of specified {@linkplain TaskCustomIntField} for a range matching to your query.
* If the lower bound is NULL, then all values smaller than the upper bound will be accepted. If
* the upper bound is NULL, then all values greater than the lower bound will be accepted.
*
* @param customIntField identifies which {@linkplain TaskCustomIntField} is affected
* @param values identify the intervals that are used for filtering
* @return the query
* @throws InvalidArgumentException if searchArguments are not given
*/
TaskQuery customIntAttributeWithin(TaskCustomIntField customIntField, IntInterval... values)
throws InvalidArgumentException;
/**
* Exclude the values of specified {@linkplain TaskCustomIntField} inside the given range from
* your query. If the lower bound is NULL, then all values smaller than the upper bound will be
* excluded. If the upper bound is NULL, then all values greater than the lower bound will be
* excluded.
*
* @param customIntField identifies which {@linkplain TaskCustomIntField} is affected
* @param values identify the intervals that are used for filtering
* @return the query
* @throws InvalidArgumentException if searchArguments are not given
*/
TaskQuery customIntAttributeNotWithin(TaskCustomIntField customIntField, IntInterval... values)
throws InvalidArgumentException;
/**
* This method sorts the query result according to the value of the specified {@linkplain
* TaskCustomIntField}.

View File

@ -6,15 +6,14 @@ import static pro.taskana.common.internal.util.SqlProviderUtil.DB2_WITH_UR;
import static pro.taskana.common.internal.util.SqlProviderUtil.OPENING_SCRIPT_TAG;
import static pro.taskana.common.internal.util.SqlProviderUtil.OPENING_WHERE_TAG;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereIn;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereInTime;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereLike;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereNotIn;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereNotInTime;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereNotLike;
import java.util.Arrays;
import java.util.stream.Collectors;
import pro.taskana.common.internal.util.SqlProviderUtil;
import pro.taskana.task.api.TaskCommentQueryColumnName;
public class TaskCommentQuerySqlProvider {
@ -95,10 +94,10 @@ public class TaskCommentQuerySqlProvider {
whereNotIn("creatorNotIn", "tc.CREATOR", sb);
whereLike("creatorLike", "tc.CREATOR", sb);
whereNotLike("creatorNotLike", "tc.CREATOR", sb);
whereInTime("createdIn", "tc.CREATED", sb);
whereNotInTime("createdNotIn", "tc.CREATED", sb);
whereInTime("modifiedIn", "tc.MODIFIED", sb);
whereNotInTime("modifiedNotIn", "tc.MODIFIED", sb);
SqlProviderUtil.whereInInterval("createdIn", "tc.CREATED", sb);
SqlProviderUtil.whereNotInInterval("createdNotIn", "tc.CREATED", sb);
SqlProviderUtil.whereInInterval("modifiedIn", "tc.MODIFIED", sb);
SqlProviderUtil.whereNotInInterval("modifiedNotIn", "tc.MODIFIED", sb);
return sb.toString();
}

View File

@ -8,6 +8,7 @@ import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.common.api.IntInterval;
import pro.taskana.common.api.KeyDomain;
import pro.taskana.common.api.TaskanaRole;
import pro.taskana.common.api.TimeInterval;
@ -290,20 +291,36 @@ public class TaskQueryImpl implements TaskQuery {
// region customIntAttributes
private Integer[] customInt1In;
private Integer[] customInt1NotIn;
private IntInterval[] customInt1Within;
private IntInterval[] customInt1NotWithin;
private Integer[] customInt2In;
private Integer[] customInt2NotIn;
private IntInterval[] customInt2Within;
private IntInterval[] customInt2NotWithin;
private Integer[] customInt3In;
private Integer[] customInt3NotIn;
private IntInterval[] customInt3Within;
private IntInterval[] customInt3NotWithin;
private Integer[] customInt4In;
private Integer[] customInt4NotIn;
private IntInterval[] customInt4Within;
private IntInterval[] customInt4NotWithin;
private Integer[] customInt5In;
private Integer[] customInt5NotIn;
private IntInterval[] customInt5Within;
private IntInterval[] customInt5NotWithin;
private Integer[] customInt6In;
private Integer[] customInt6NotIn;
private IntInterval[] customInt6Within;
private IntInterval[] customInt6NotWithin;
private Integer[] customInt7In;
private Integer[] customInt7NotIn;
private IntInterval[] customInt7Within;
private IntInterval[] customInt7NotWithin;
private Integer[] customInt8In;
private Integer[] customInt8NotIn;
private IntInterval[] customInt8Within;
private IntInterval[] customInt8NotWithin;
// endregion
// region callbackState
private CallbackState[] callbackStateIn;
@ -351,14 +368,14 @@ public class TaskQueryImpl implements TaskQuery {
@Override
public TaskQuery receivedWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.receivedWithin = intervals;
return this;
}
@Override
public TaskQuery receivedNotWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.receivedNotWithin = intervals;
return this;
}
@ -370,14 +387,14 @@ public class TaskQueryImpl implements TaskQuery {
@Override
public TaskQuery createdWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.createdWithin = intervals;
return this;
}
@Override
public TaskQuery createdNotWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.createdNotWithin = intervals;
return this;
}
@ -389,14 +406,14 @@ public class TaskQueryImpl implements TaskQuery {
@Override
public TaskQuery claimedWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.claimedWithin = intervals;
return this;
}
@Override
public TaskQuery claimedNotWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.claimedNotWithin = intervals;
return this;
}
@ -408,14 +425,14 @@ public class TaskQueryImpl implements TaskQuery {
@Override
public TaskQuery modifiedWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.modifiedWithin = intervals;
return this;
}
@Override
public TaskQuery modifiedNotWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.modifiedNotWithin = intervals;
return this;
}
@ -427,14 +444,14 @@ public class TaskQueryImpl implements TaskQuery {
@Override
public TaskQuery plannedWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.plannedWithin = intervals;
return this;
}
@Override
public TaskQuery plannedNotWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.plannedNotWithin = intervals;
return this;
}
@ -446,14 +463,14 @@ public class TaskQueryImpl implements TaskQuery {
@Override
public TaskQuery dueWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.dueWithin = intervals;
return this;
}
@Override
public TaskQuery dueNotWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.dueNotWithin = intervals;
return this;
}
@ -465,14 +482,14 @@ public class TaskQueryImpl implements TaskQuery {
@Override
public TaskQuery completedWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.completedWithin = intervals;
return this;
}
@Override
public TaskQuery completedNotWithin(TimeInterval... intervals) {
validateAllIntervals(intervals);
validateAllTimeIntervals(intervals);
this.completedNotWithin = intervals;
return this;
}
@ -1182,7 +1199,7 @@ public class TaskQueryImpl implements TaskQuery {
@Override
public TaskQuery attachmentReceivedWithin(TimeInterval... receivedIn) {
validateAllIntervals(receivedIn);
validateAllTimeIntervals(receivedIn);
joinWithAttachments = true;
this.attachmentReceivedWithin = receivedIn;
return this;
@ -1190,7 +1207,7 @@ public class TaskQueryImpl implements TaskQuery {
@Override
public TaskQuery attachmentNotReceivedWithin(TimeInterval... receivedNotIn) {
validateAllIntervals(receivedNotIn);
validateAllTimeIntervals(receivedNotIn);
joinWithAttachments = true;
this.attachmentReceivedNotWithin = receivedNotIn;
return this;
@ -1759,6 +1776,76 @@ public class TaskQueryImpl implements TaskQuery {
return addOrderCriteria(customIntField.name(), sortDirection);
}
@Override
public TaskQuery customIntAttributeWithin(
TaskCustomIntField customIntField, IntInterval... values) {
validateAllIntIntervals(values);
switch (customIntField) {
case CUSTOM_INT_1:
this.customInt1Within = values;
break;
case CUSTOM_INT_2:
this.customInt2Within = values;
break;
case CUSTOM_INT_3:
this.customInt3Within = values;
break;
case CUSTOM_INT_4:
this.customInt4Within = values;
break;
case CUSTOM_INT_5:
this.customInt5Within = values;
break;
case CUSTOM_INT_6:
this.customInt6Within = values;
break;
case CUSTOM_INT_7:
this.customInt7Within = values;
break;
case CUSTOM_INT_8:
this.customInt8Within = values;
break;
default:
throw new SystemException("Unknown custom int attribute '" + customIntField + "'");
}
return this;
}
@Override
public TaskQuery customIntAttributeNotWithin(
TaskCustomIntField customIntField, IntInterval... values) {
validateAllIntIntervals(values);
switch (customIntField) {
case CUSTOM_INT_1:
this.customInt1NotWithin = values;
break;
case CUSTOM_INT_2:
this.customInt2NotWithin = values;
break;
case CUSTOM_INT_3:
this.customInt3NotWithin = values;
break;
case CUSTOM_INT_4:
this.customInt4NotWithin = values;
break;
case CUSTOM_INT_5:
this.customInt5NotWithin = values;
break;
case CUSTOM_INT_6:
this.customInt6NotWithin = values;
break;
case CUSTOM_INT_7:
this.customInt7NotWithin = values;
break;
case CUSTOM_INT_8:
this.customInt8NotWithin = values;
break;
default:
throw new SystemException("Unknown custom int attribute '" + customIntField + "'");
}
return this;
}
@Override
public TaskQuery callbackStateIn(CallbackState... states) {
this.callbackStateIn = states;
@ -1956,7 +2043,7 @@ public class TaskQueryImpl implements TaskQuery {
return DB.isDb2(getDatabaseId()) ? LINK_TO_COUNTER_DB2 : LINK_TO_COUNTER;
}
private void validateAllIntervals(TimeInterval[] intervals) {
private void validateAllTimeIntervals(TimeInterval[] intervals) {
for (TimeInterval ti : intervals) {
if (!ti.isValid()) {
throw new IllegalArgumentException("TimeInterval " + ti + " is invalid.");
@ -1964,6 +2051,14 @@ public class TaskQueryImpl implements TaskQuery {
}
}
private void validateAllIntIntervals(IntInterval[] intervals) {
for (IntInterval ti : intervals) {
if (!ti.isValid()) {
throw new IllegalArgumentException("IntInterval " + ti + " is invalid.");
}
}
}
private void checkForIllegalParamCombinations() {
if (wildcardSearchValueLike != null ^ wildcardSearchFieldIn != null) {
throw new IllegalArgumentException(
@ -2522,38 +2617,66 @@ public class TaskQueryImpl implements TaskQuery {
+ Arrays.toString(customInt1In)
+ ", customInt1NotIn="
+ Arrays.toString(customInt1NotIn)
+ ", customInt1Within="
+ Arrays.toString(customInt1Within)
+ ", customInt1NotWithin="
+ Arrays.toString(customInt1NotWithin)
+ ", customInt2In="
+ Arrays.toString(customInt2In)
+ ", customInt2NotIn="
+ Arrays.toString(customInt2NotIn)
+ ", customInt2Within="
+ Arrays.toString(customInt2Within)
+ ", customInt2NotWithin="
+ Arrays.toString(customInt2NotWithin)
+ ", customInt3In="
+ Arrays.toString(customInt3In)
+ ", customInt3NotIn="
+ Arrays.toString(customInt3NotIn)
+ ", customInt3Within="
+ Arrays.toString(customInt3Within)
+ ", customInt3NotWithin="
+ Arrays.toString(customInt3NotWithin)
+ ", customInt4In="
+ Arrays.toString(customInt4In)
+ ", customInt4NotIn="
+ Arrays.toString(customInt4NotIn)
+ ", customInt4Within="
+ Arrays.toString(customInt4Within)
+ ", customInt4NotWithin="
+ Arrays.toString(customInt4NotWithin)
+ ", customInt5In="
+ Arrays.toString(customInt5In)
+ ", customInt5NotIn="
+ Arrays.toString(customInt5NotIn)
+ ", customInt5Within="
+ Arrays.toString(customInt5Within)
+ ", customInt5NotWithin="
+ Arrays.toString(customInt5NotWithin)
+ ", customInt6In="
+ Arrays.toString(customInt6In)
+ ", customInt6NotIn="
+ Arrays.toString(customInt6NotIn)
+ ", customInt6Within="
+ Arrays.toString(customInt6Within)
+ ", customInt6NotWithin="
+ Arrays.toString(customInt6NotWithin)
+ ", customInt7In="
+ Arrays.toString(customInt7In)
+ ", customInt7NotIn="
+ Arrays.toString(custom7NotIn)
+ ", custom7Like="
+ Arrays.toString(custom7Like)
+ ", custom7NotLike="
+ Arrays.toString(custom7NotLike)
+ ", custom8In="
+ Arrays.toString(custom8In)
+ ", custom8NotIn="
+ Arrays.toString(custom8NotIn)
+ Arrays.toString(customInt7NotIn)
+ ", customInt7Within="
+ Arrays.toString(customInt7Within)
+ ", customInt7NotWithin="
+ Arrays.toString(customInt7NotWithin)
+ ", customInt8In="
+ Arrays.toString(customInt8In)
+ ", customInt8NotIn="
+ Arrays.toString(customInt8NotIn)
+ ", customInt8Within="
+ Arrays.toString(customInt8Within)
+ ", customInt8NotWithin="
+ Arrays.toString(customInt8NotWithin)
+ ", callbackStateIn="
+ Arrays.toString(callbackStateIn)
+ ", callbackStateNotIn="

View File

@ -8,15 +8,14 @@ import static pro.taskana.common.internal.util.SqlProviderUtil.OPENING_WHERE_TAG
import static pro.taskana.common.internal.util.SqlProviderUtil.whereCustomIntStatements;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereCustomStatements;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereIn;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereInTime;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereLike;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereNotIn;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereNotInTime;
import static pro.taskana.common.internal.util.SqlProviderUtil.whereNotLike;
import java.util.Arrays;
import java.util.stream.Collectors;
import pro.taskana.common.internal.util.SqlProviderUtil;
import pro.taskana.task.api.TaskQueryColumnName;
public class TaskQuerySqlProvider {
@ -422,22 +421,22 @@ public class TaskQuerySqlProvider {
whereLike("noteLike", "t.NOTE", sb);
whereNotLike("noteNotLike", "t.NOTE", sb);
whereInTime("attachmentReceivedWithin", "a.RECEIVED", sb);
whereNotInTime("attachmentReceivedNotWithin", "a.RECEIVED", sb);
whereInTime("claimedWithin", "t.CLAIMED", sb);
whereNotInTime("claimedNotWithin", "t.CLAIMED", sb);
whereInTime("completedWithin", "t.COMPLETED", sb);
whereNotInTime("completedNotWithin", "t.COMPLETED", sb);
whereInTime("createdWithin", "t.CREATED", sb);
whereNotInTime("createdNotWithin", "t.CREATED", sb);
whereInTime("dueWithin", "t.DUE", sb);
whereNotInTime("dueNotWithin", "t.DUE", sb);
whereInTime("modifiedWithin", "t.MODIFIED", sb);
whereNotInTime("modifiedNotWithin", "t.MODIFIED", sb);
whereInTime("plannedWithin", "t.PLANNED", sb);
whereNotInTime("plannedNotWithin", "t.PLANNED", sb);
whereInTime("receivedWithin", "t.RECEIVED", sb);
whereNotInTime("receivedNotWithin", "t.RECEIVED", sb);
SqlProviderUtil.whereInInterval("attachmentReceivedWithin", "a.RECEIVED", sb);
SqlProviderUtil.whereNotInInterval("attachmentReceivedNotWithin", "a.RECEIVED", sb);
SqlProviderUtil.whereInInterval("claimedWithin", "t.CLAIMED", sb);
SqlProviderUtil.whereNotInInterval("claimedNotWithin", "t.CLAIMED", sb);
SqlProviderUtil.whereInInterval("completedWithin", "t.COMPLETED", sb);
SqlProviderUtil.whereNotInInterval("completedNotWithin", "t.COMPLETED", sb);
SqlProviderUtil.whereInInterval("createdWithin", "t.CREATED", sb);
SqlProviderUtil.whereNotInInterval("createdNotWithin", "t.CREATED", sb);
SqlProviderUtil.whereInInterval("dueWithin", "t.DUE", sb);
SqlProviderUtil.whereNotInInterval("dueNotWithin", "t.DUE", sb);
SqlProviderUtil.whereInInterval("modifiedWithin", "t.MODIFIED", sb);
SqlProviderUtil.whereNotInInterval("modifiedNotWithin", "t.MODIFIED", sb);
SqlProviderUtil.whereInInterval("plannedWithin", "t.PLANNED", sb);
SqlProviderUtil.whereNotInInterval("plannedNotWithin", "t.PLANNED", sb);
SqlProviderUtil.whereInInterval("receivedWithin", "t.RECEIVED", sb);
SqlProviderUtil.whereNotInInterval("receivedNotWithin", "t.RECEIVED", sb);
whereLike("ownerLongNameLike", "u.LONG_NAME", sb);
whereNotLike("ownerLongNameNotLike", "u.LONG_NAME", sb);

View File

@ -5,6 +5,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import pro.taskana.common.api.IntInterval;
import pro.taskana.common.api.TimeInterval;
public interface QueryParameter<E, R> {
@ -27,4 +28,16 @@ public interface QueryParameter<E, R> {
return timeIntervalsList.toArray(new TimeInterval[0]);
}
default IntInterval[] extractIntIntervals(Integer[] boundaries) {
List<IntInterval> intervalsList = new ArrayList<>();
for (int i = 0; i < boundaries.length - 1; i += 2) {
Integer left = boundaries[i];
Integer right = boundaries[i + 1];
if (left != null || right != null) {
intervalsList.add(new IntInterval(left, right));
}
}
return intervalsList.toArray(new IntInterval[0]);
}
}

View File

@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.beans.ConstructorProperties;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.Optional;
import java.util.stream.Stream;
@ -1493,6 +1494,12 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Exclude values of the field customInt1 of the Task. */
@JsonProperty("custom-int-1-not")
private final Integer[] customInt1NotIn;
/** Filter by the range of value of the field customInt1 of the Task. */
@JsonProperty("custom-int-1-within")
private final Integer[] customInt1Within;
/** Exclude range of values of the field customInt1 of the Task. */
@JsonProperty("custom-int-1-not-within")
private final Integer[] customInt1NotWithin;
/** Filter by the value of the field customInt2 of the Task. This is an exact match. */
@JsonProperty("custom-int-2")
private final Integer[] customInt2In;
@ -1500,6 +1507,12 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Exclude values of the field customInt2 of the Task. */
@JsonProperty("custom-int-2-not")
private final Integer[] customInt2NotIn;
/** Filter by the range of value of the field customInt2 of the Task. */
@JsonProperty("custom-int-2-within")
private final Integer[] customInt2Within;
/** Exclude range of values of the field customInt2 of the Task. */
@JsonProperty("custom-int-2-not-within")
private final Integer[] customInt2NotWithin;
/** Filter by the value of the field customInt3 of the Task. This is an exact match. */
@JsonProperty("custom-int-3")
private final Integer[] customInt3In;
@ -1507,6 +1520,12 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Exclude values of the field customInt3 of the Task. */
@JsonProperty("custom-int-3-not")
private final Integer[] customInt3NotIn;
/** Filter by the range of value of the field customInt3 of the Task. */
@JsonProperty("custom-int-3-within")
private final Integer[] customInt3Within;
/** Exclude range of values of the field customInt3 of the Task. */
@JsonProperty("custom-int-3-not-within")
private final Integer[] customInt3NotWithin;
/** Filter by the value of the field customInt4 of the Task. This is an exact match. */
@JsonProperty("custom-int-4")
private final Integer[] customInt4In;
@ -1514,6 +1533,12 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Exclude values of the field customInt4 of the Task. */
@JsonProperty("custom-int-4-not")
private final Integer[] customInt4NotIn;
/** Filter by the range of value of the field customInt4 of the Task. */
@JsonProperty("custom-int-4-within")
private final Integer[] customInt4Within;
/** Exclude range of values of the field customInt4 of the Task. */
@JsonProperty("custom-int-4-not-within")
private final Integer[] customInt4NotWithin;
/** Filter by the value of the field customInt5 of the Task. This is an exact match. */
@JsonProperty("custom-int-5")
private final Integer[] customInt5In;
@ -1521,6 +1546,12 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Exclude values of the field customInt5 of the Task. */
@JsonProperty("custom-int-5-not")
private final Integer[] customInt5NotIn;
/** Filter by the range of value of the field customInt5 of the Task. */
@JsonProperty("custom-int-5-within")
private final Integer[] customInt5Within;
/** Exclude range of values of the field customInt5 of the Task. */
@JsonProperty("custom-int-5-not-within")
private final Integer[] customInt5NotWithin;
/** Filter by the value of the field customInt6 of the Task. This is an exact match. */
@JsonProperty("custom-int-6")
private final Integer[] customInt6In;
@ -1528,6 +1559,12 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Exclude values of the field customInt6 of the Task. */
@JsonProperty("custom-int-6-not")
private final Integer[] customInt6NotIn;
/** Filter by the range of value of the field customInt6 of the Task. */
@JsonProperty("custom-int-6-within")
private final Integer[] customInt6Within;
/** Exclude range of values of the field customInt6 of the Task. */
@JsonProperty("custom-int-6-not-within")
private final Integer[] customInt6NotWithin;
/** Filter by the value of the field customInt7 of the Task. This is an exact match. */
@JsonProperty("custom-int-7")
private final Integer[] customInt7In;
@ -1535,6 +1572,12 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Exclude values of the field customInt7 of the Task. */
@JsonProperty("custom-int-7-not")
private final Integer[] customInt7NotIn;
/** Filter by the range of value of the field customInt7 of the Task. */
@JsonProperty("custom-int-7-within")
private final Integer[] customInt7Within;
/** Exclude range of values of the field customInt7 of the Task. */
@JsonProperty("custom-int-7-not-within")
private final Integer[] customInt7NotWithin;
/** Filter by the value of the field customInt8 of the Task. This is an exact match. */
@JsonProperty("custom-int-8")
private final Integer[] customInt8In;
@ -1542,6 +1585,12 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
/** Exclude values of the field customInt8 of the Task. */
@JsonProperty("custom-int-8-not")
private final Integer[] customInt8NotIn;
/** Filter by the range of value of the field customInt8 of the Task. */
@JsonProperty("custom-int-8-within")
private final Integer[] customInt8Within;
/** Exclude range of values of the field customInt8 of the Task. */
@JsonProperty("custom-int-8-not-within")
private final Integer[] customInt8NotWithin;
// endregion
// region callbackState
/** Filter by the callback state of the Task. This is an exact match. */
@ -1779,20 +1828,36 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
"custom-16-not-like",
"custom-int-1",
"custom-int-1-not",
"custom-int-1-within",
"custom-int-1-not-within",
"custom-int-2",
"custom-int-2-not",
"custom-int-2-within",
"custom-int-2-not-within",
"custom-int-3",
"custom-int-3-not",
"custom-int-3-within",
"custom-int-3-not-within",
"custom-int-4",
"custom-int-4-not",
"custom-int-4-within",
"custom-int-4-not-within",
"custom-int-5",
"custom-int-5-not",
"custom-int-5-within",
"custom-int-5-not-within",
"custom-int-6",
"custom-int-6-not",
"custom-int-6-within",
"custom-int-6-not-within",
"custom-int-7",
"custom-int-7-not",
"custom-int-7-within",
"custom-int-7-not-within",
"custom-int-8",
"custom-int-8-not",
"custom-int-8-within",
"custom-int-8-not-within",
"callback-state",
"callback-state-not",
"wildcard-search-fields",
@ -2005,20 +2070,36 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
String[] custom16NotLike,
Integer[] customInt1In,
Integer[] customInt1NotIn,
Integer[] customInt1Within,
Integer[] customInt1NotWithin,
Integer[] customInt2In,
Integer[] customInt2NotIn,
Integer[] customInt2Within,
Integer[] customInt2NotWithin,
Integer[] customInt3In,
Integer[] customInt3NotIn,
Integer[] customInt3Within,
Integer[] customInt3NotWithin,
Integer[] customInt4In,
Integer[] customInt4NotIn,
Integer[] customInt4Within,
Integer[] customInt4NotWithin,
Integer[] customInt5In,
Integer[] customInt5NotIn,
Integer[] customInt5Within,
Integer[] customInt5NotWithin,
Integer[] customInt6In,
Integer[] customInt6NotIn,
Integer[] customInt6Within,
Integer[] customInt6NotWithin,
Integer[] customInt7In,
Integer[] customInt7NotIn,
Integer[] customInt7Within,
Integer[] customInt7NotWithin,
Integer[] customInt8In,
Integer[] customInt8NotIn,
Integer[] customInt8Within,
Integer[] customInt8NotWithin,
CallbackState[] callbackStateIn,
CallbackState[] callbackStateNotIn,
WildcardSearchField[] wildcardSearchFieldIn,
@ -2230,20 +2311,36 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
this.custom16NotLike = custom16NotLike;
this.customInt1In = customInt1In;
this.customInt1NotIn = customInt1NotIn;
this.customInt1Within = customInt1Within;
this.customInt1NotWithin = customInt1NotWithin;
this.customInt2In = customInt2In;
this.customInt2NotIn = customInt2NotIn;
this.customInt2Within = customInt2Within;
this.customInt2NotWithin = customInt2NotWithin;
this.customInt3In = customInt3In;
this.customInt3NotIn = customInt3NotIn;
this.customInt3Within = customInt3Within;
this.customInt3NotWithin = customInt3NotWithin;
this.customInt4In = customInt4In;
this.customInt4NotIn = customInt4NotIn;
this.customInt4Within = customInt4Within;
this.customInt4NotWithin = customInt4NotWithin;
this.customInt5In = customInt5In;
this.customInt5NotIn = customInt5NotIn;
this.customInt5Within = customInt5Within;
this.customInt5NotWithin = customInt5NotWithin;
this.customInt6In = customInt6In;
this.customInt6NotIn = customInt6NotIn;
this.customInt6Within = customInt6Within;
this.customInt6NotWithin = customInt6NotWithin;
this.customInt7In = customInt7In;
this.customInt7NotIn = customInt7NotIn;
this.customInt7Within = customInt7Within;
this.customInt7NotWithin = customInt7NotWithin;
this.customInt8In = customInt8In;
this.customInt8NotIn = customInt8NotIn;
this.customInt8Within = customInt8Within;
this.customInt8NotWithin = customInt8NotWithin;
this.callbackStateIn = callbackStateIn;
this.callbackStateNotIn = callbackStateNotIn;
this.wildcardSearchFieldIn = wildcardSearchFieldIn;
@ -2614,20 +2711,42 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
});
Stream.of(
Pair.of(TaskCustomIntField.CUSTOM_INT_1, Pair.of(customInt1In, customInt1NotIn)),
Pair.of(TaskCustomIntField.CUSTOM_INT_2, Pair.of(customInt2In, customInt2NotIn)),
Pair.of(TaskCustomIntField.CUSTOM_INT_3, Pair.of(customInt3In, customInt3NotIn)),
Pair.of(TaskCustomIntField.CUSTOM_INT_4, Pair.of(customInt4In, customInt4NotIn)),
Pair.of(TaskCustomIntField.CUSTOM_INT_5, Pair.of(customInt5In, customInt5NotIn)),
Pair.of(TaskCustomIntField.CUSTOM_INT_6, Pair.of(customInt6In, customInt6NotIn)),
Pair.of(TaskCustomIntField.CUSTOM_INT_7, Pair.of(customInt7In, customInt7NotIn)),
Pair.of(TaskCustomIntField.CUSTOM_INT_8, Pair.of(customInt8In, customInt8NotIn)))
Pair.of(
TaskCustomIntField.CUSTOM_INT_1,
of(customInt1In, customInt1NotIn, customInt1Within, customInt1NotWithin)),
Pair.of(
TaskCustomIntField.CUSTOM_INT_2,
of(customInt2In, customInt2NotIn, customInt2Within, customInt2NotWithin)),
Pair.of(
TaskCustomIntField.CUSTOM_INT_3,
of(customInt3In, customInt3NotIn, customInt3Within, customInt3NotWithin)),
Pair.of(
TaskCustomIntField.CUSTOM_INT_4,
of(customInt4In, customInt4NotIn, customInt4Within, customInt4NotWithin)),
Pair.of(
TaskCustomIntField.CUSTOM_INT_5,
of(customInt5In, customInt5NotIn, customInt5Within, customInt5NotWithin)),
Pair.of(
TaskCustomIntField.CUSTOM_INT_6,
of(customInt6In, customInt6NotIn, customInt6Within, customInt6NotWithin)),
Pair.of(
TaskCustomIntField.CUSTOM_INT_7,
of(customInt7In, customInt7NotIn, customInt7Within, customInt7NotWithin)),
Pair.of(
TaskCustomIntField.CUSTOM_INT_8,
of(customInt8In, customInt8NotIn, customInt8Within, customInt8NotWithin)))
.forEach(
pair -> {
Optional.ofNullable(pair.getRight().getLeft())
Optional.ofNullable(pair.getRight().getFirst())
.ifPresent(wrap(l -> query.customIntAttributeIn(pair.getLeft(), l)));
Optional.ofNullable(pair.getRight().getRight())
Optional.ofNullable(pair.getRight().getSecond())
.ifPresent(wrap(l -> query.customIntAttributeNotIn(pair.getLeft(), l)));
Optional.ofNullable(pair.getRight().getThird())
.map(this::extractIntIntervals)
.ifPresent(wrap(l -> query.customIntAttributeWithin(pair.getLeft(), l)));
Optional.ofNullable(pair.getRight().getFourth())
.map(this::extractIntIntervals)
.ifPresent(wrap(l -> query.customIntAttributeNotWithin(pair.getLeft(), l)));
});
Optional.ofNullable(callbackStateIn).ifPresent(query::callbackStateIn);
@ -2795,9 +2914,202 @@ public class TaskQueryFilterParameter implements QueryParameter<TaskQuery, Void>
"provided length of the property 'claimed-not-in' is not dividable by 2");
}
if (attachmentReceivedNotWithin != null && attachmentReceivedNotWithin.length % 2 != 0) {
if (customInt1Within != null && customInt1Within.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'attachment-not-received' is not dividable by 2");
"provided length of the property 'custom-int-1-within' is not dividable by 2");
}
if (customInt1Within != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt1Within), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-1-within' shouldn't consist of two 'null' values");
}
if (customInt2Within != null && customInt2Within.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-2-within' is not dividable by 2");
}
if (customInt2Within != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt2Within), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-2-within' shouldn't consist of two 'null' values");
}
if (customInt3Within != null && customInt3Within.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-3-within' is not dividable by 2");
}
if (customInt3Within != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt3Within), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-3-within' shouldn't consist of two 'null' values");
}
if (customInt4Within != null && customInt4Within.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-4-within' is not dividable by 2");
}
if (customInt4Within != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt4Within), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-4-within' shouldn't consist of two 'null' values");
}
if (customInt5Within != null && customInt5Within.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-5-within' is not dividable by 2");
}
if (customInt5Within != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt5Within), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-5-within' shouldn't consist of two 'null' values");
}
if (customInt6Within != null && customInt6Within.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-6-within' is not dividable by 2");
}
if (customInt6Within != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt6Within), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-6-within' shouldn't consist of two 'null' values");
}
if (customInt7Within != null && customInt7Within.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-7-within' is not dividable by 2");
}
if (customInt7Within != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt7Within), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-7-within' shouldn't consist of two 'null' values");
}
if (customInt8Within != null && customInt8Within.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-8-within' is not dividable by 2");
}
if (customInt8Within != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt8Within), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-8-within' shouldn't consist of two 'null' values");
}
if (customInt1NotWithin != null && customInt1NotWithin.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-1-not-within' is not dividable by 2");
}
if (customInt1NotWithin != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt1NotWithin), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-1-not-within' shouldn't consist of two 'null' values");
}
if (customInt2NotWithin != null && customInt2NotWithin.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-2-not-within' is not dividable by 2");
}
if (customInt2NotWithin != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt2NotWithin), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-2-not-within' shouldn't consist of two 'null' values");
}
if (customInt3NotWithin != null && customInt3NotWithin.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-3-not-within' is not dividable by 2");
}
if (customInt3NotWithin != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt3NotWithin), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-3-not-within' shouldn't consist of two 'null' values");
}
if (customInt4NotWithin != null && customInt4NotWithin.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-4-not-within' is not dividable by 2");
}
if (customInt4NotWithin != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt4NotWithin), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-4-not-within' shouldn't consist of two 'null' values");
}
if (customInt5NotWithin != null && customInt5NotWithin.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-5-not-within' is not dividable by 2");
}
if (customInt5NotWithin != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt5NotWithin), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-5-not-within' shouldn't consist of two 'null' values");
}
if (customInt6NotWithin != null && customInt6NotWithin.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-6-not-within' is not dividable by 2");
}
if (customInt6NotWithin != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt6NotWithin), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-6-not-within' shouldn't consist of two 'null' values");
}
if (customInt7NotWithin != null && customInt7NotWithin.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-7-not-within' is not dividable by 2");
}
if (customInt7NotWithin != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt7NotWithin), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-7-not-within' shouldn't consist of two 'null' values");
}
if (customInt8NotWithin != null && customInt8NotWithin.length % 2 != 0) {
throw new InvalidArgumentException(
"provided length of the property 'custom-int-8-not-within' is not dividable by 2");
}
if (customInt8NotWithin != null
&& (Collections.indexOfSubList(
Arrays.asList(customInt8NotWithin), Collections.nCopies(2, (Integer) null))
% 2
== 0)) {
throw new InvalidArgumentException(
"Each interval in 'custom-int-8-not-within' shouldn't consist of two 'null' values");
}
if (withoutAttachment != null && !withoutAttachment) {

View File

@ -206,6 +206,73 @@ class TaskControllerIntTest {
return DynamicTest.stream(customIntValues.iterator(), c -> "customInt" + c, test);
}
@TestFactory
Stream<DynamicTest>
should_ThrowException_For_SpecifiedWorkbasketIdAndCustomIntFieldWithinIncorrectInterval() {
List<Integer> customIntValues = List.of(1, 2, 3, 4, 5, 6, 7, 8);
ThrowingConsumer<Integer> test =
i -> {
String url =
restHelper.toUrl(RestEndpoints.URL_TASKS)
+ String.format(
"?workbasket-id=WBI:100000000000000000000000000000000001"
+ "&custom-int-%s-within=%s"
+ "&custom-int-%s-within=23"
+ "&custom-int-%s-within=15",
i, i, i, i);
HttpEntity<Object> auth =
new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ThrowingCallable httpCall =
() -> TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThatThrownBy(httpCall)
.isInstanceOf(HttpStatusCodeException.class)
.hasMessageContaining(
"provided length of the property 'custom-int-"
+ i
+ "-within' is not dividable by 2")
.extracting(HttpStatusCodeException.class::cast)
.extracting(HttpStatusCodeException::getStatusCode)
.isEqualTo(HttpStatus.BAD_REQUEST);
};
return DynamicTest.stream(customIntValues.iterator(), c -> "customInt" + c, test);
}
@TestFactory
Stream<DynamicTest>
should_ThrowException_For_SpecifiedWorkbasketIdAndCustomIntFieldWithinNullInterval() {
List<Integer> customIntValues = List.of(1, 2, 3, 4, 5, 6, 7, 8);
ThrowingConsumer<Integer> test =
i -> {
String url =
restHelper.toUrl(RestEndpoints.URL_TASKS)
+ String.format(
"?workbasket-id=WBI:100000000000000000000000000000000001"
+ "&custom-int-%s-within="
+ "&custom-int-%s-within=",
i, i, i);
HttpEntity<Object> auth =
new HttpEntity<>(RestHelper.generateHeadersForUser("teamlead-1"));
ThrowingCallable httpCall =
() -> TEMPLATE.exchange(url, HttpMethod.GET, auth, TASK_SUMMARY_PAGE_MODEL_TYPE);
assertThatThrownBy(httpCall)
.isInstanceOf(HttpStatusCodeException.class)
.hasMessageContaining(
"Each interval in 'custom-int-"
+ i
+ "-within' shouldn't consist of two 'null' values")
.extracting(HttpStatusCodeException.class::cast)
.extracting(HttpStatusCodeException::getStatusCode)
.isEqualTo(HttpStatus.BAD_REQUEST);
};
return DynamicTest.stream(customIntValues.iterator(), c -> "customInt" + c, test);
}
@TestFactory
Stream<DynamicTest> should_GetAllTasks_For_SpecifiedWorkbasketIdAndCustomIntFieldWithin() {
List<Integer> customIntValues = List.of(1, 2, 3, 4, 5, 6, 7, 8);