Comments from Holger Hagen

This commit is contained in:
Jörg Heffner 2020-04-20 15:31:04 +02:00
parent 101072d3e9
commit c36933b450
7 changed files with 78 additions and 44 deletions

View File

@ -614,6 +614,7 @@ public interface TaskQuery extends BaseQuery<TaskSummary, TaskQueryColumnName> {
/** /**
* Add your wildcard search value for pattern matching to your query. It will be compared in SQL * Add your wildcard search value for pattern matching to your query. It will be compared in SQL
* with the LIKE operator. You may use a wildcard like % to specify the pattern. * with the LIKE operator. You may use a wildcard like % to specify the pattern.
* Must be used in combination with the wilcardSearchFieldIn parameter
* *
* @param wildcardSearchValue the wildcard search value * @param wildcardSearchValue the wildcard search value
* @return the query * @return the query
@ -622,11 +623,12 @@ public interface TaskQuery extends BaseQuery<TaskSummary, TaskQueryColumnName> {
/** /**
* Add the values of the wildcard search fields for exact matching to your query. * Add the values of the wildcard search fields for exact matching to your query.
* Must be used in combination with the wildcardSearchValueLike parameter
* *
* @param wildcardSearchFields the values of your wildcard search fields * @param wildcardSearchFields the values of your wildcard search fields
* @return the query * @return the query
*/ */
TaskQuery wildcardSearchFieldsIn(WildcardSearchFields... wildcardSearchFields); TaskQuery wildcardSearchFieldsIn(WildcardSearchField... wildcardSearchFields);
/** /**
* This method sorts the query result according to the completed timestamp. * This method sorts the query result according to the completed timestamp.

View File

@ -5,7 +5,7 @@ import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public enum WildcardSearchFields { public enum WildcardSearchField {
NAME("NAME"), NAME("NAME"),
DESCRIPTION("DESCRIPTION"), DESCRIPTION("DESCRIPTION"),
CUSTOM_1("CUSTOM_1"), CUSTOM_1("CUSTOM_1"),
@ -25,21 +25,21 @@ public enum WildcardSearchFields {
CUSTOM_15("CUSTOM_15"), CUSTOM_15("CUSTOM_15"),
CUSTOM_16("CUSTOM_16"); CUSTOM_16("CUSTOM_16");
WildcardSearchFields(String name) { WildcardSearchField(String name) {
this.name = name; this.name = name;
} }
private static final Map<String, WildcardSearchFields> STRING_TO_ENUM = private static final Map<String, WildcardSearchField> STRING_TO_ENUM =
Arrays.stream(values()) Arrays.stream(values())
.collect( .collect(
Collectors.toMap( Collectors.toMap(
WildcardSearchFields::toString, WildcardSearchField::toString,
e -> e, e -> e,
(first, second) -> first, (first, second) -> first,
() -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER))); () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER)));
private String name; private String name;
public static WildcardSearchFields fromString(String name) { public static WildcardSearchField fromString(String name) {
return STRING_TO_ENUM.get(name); return STRING_TO_ENUM.get(name);
} }

View File

@ -24,7 +24,7 @@ import pro.taskana.task.api.ObjectReferenceQuery;
import pro.taskana.task.api.TaskQuery; import pro.taskana.task.api.TaskQuery;
import pro.taskana.task.api.TaskQueryColumnName; import pro.taskana.task.api.TaskQueryColumnName;
import pro.taskana.task.api.TaskState; import pro.taskana.task.api.TaskState;
import pro.taskana.task.api.WildcardSearchFields; import pro.taskana.task.api.WildcardSearchField;
import pro.taskana.task.api.models.TaskSummary; import pro.taskana.task.api.models.TaskSummary;
import pro.taskana.task.internal.models.TaskSummaryImpl; import pro.taskana.task.internal.models.TaskSummaryImpl;
import pro.taskana.workbasket.api.WorkbasketPermission; import pro.taskana.workbasket.api.WorkbasketPermission;
@ -148,7 +148,7 @@ public class TaskQueryImpl implements TaskQuery {
private TimeInterval[] dueIn; private TimeInterval[] dueIn;
private List<String> orderBy; private List<String> orderBy;
private List<String> orderColumns; private List<String> orderColumns;
private WildcardSearchFields[] wildcardSearchFieldsIn; private WildcardSearchField[] wildcardSearchFieldIn;
private String wildcardSearchValueLike; private String wildcardSearchValueLike;
private boolean useDistinctKeyword = false; private boolean useDistinctKeyword = false;
@ -747,8 +747,8 @@ public class TaskQueryImpl implements TaskQuery {
} }
@Override @Override
public TaskQuery wildcardSearchFieldsIn(WildcardSearchFields... wildcardSearchFields) { public TaskQuery wildcardSearchFieldsIn(WildcardSearchField... wildcardSearchFields) {
this.wildcardSearchFieldsIn = wildcardSearchFields; this.wildcardSearchFieldIn = wildcardSearchFields;
return this; return this;
} }
@ -970,6 +970,7 @@ public class TaskQueryImpl implements TaskQuery {
try { try {
LOGGER.debug("entry to list(), this = {}", this); LOGGER.debug("entry to list(), this = {}", this);
taskanaEngine.openConnection(); taskanaEngine.openConnection();
checkForIllegalParamCombinations();
checkOpenAndReadPermissionForSpecifiedWorkbaskets(); checkOpenAndReadPermissionForSpecifiedWorkbaskets();
setupJoinAndOrderParameters(); setupJoinAndOrderParameters();
setupAccessIds(); setupAccessIds();
@ -1000,6 +1001,7 @@ public class TaskQueryImpl implements TaskQuery {
List<TaskSummary> result = new ArrayList<>(); List<TaskSummary> result = new ArrayList<>();
try { try {
taskanaEngine.openConnection(); taskanaEngine.openConnection();
checkForIllegalParamCombinations();
checkOpenAndReadPermissionForSpecifiedWorkbaskets(); checkOpenAndReadPermissionForSpecifiedWorkbaskets();
setupAccessIds(); setupAccessIds();
setupJoinAndOrderParameters(); setupJoinAndOrderParameters();
@ -1037,6 +1039,7 @@ public class TaskQueryImpl implements TaskQuery {
this.columnName = columnName; this.columnName = columnName;
this.orderBy.clear(); this.orderBy.clear();
this.addOrderCriteria(columnName.toString(), sortDirection); this.addOrderCriteria(columnName.toString(), sortDirection);
checkForIllegalParamCombinations();
checkOpenAndReadPermissionForSpecifiedWorkbaskets(); checkOpenAndReadPermissionForSpecifiedWorkbaskets();
setupAccessIds(); setupAccessIds();
@ -1603,14 +1606,24 @@ public class TaskQueryImpl implements TaskQuery {
addAttachmentClassificationNameToSelectClauseForOrdering; addAttachmentClassificationNameToSelectClauseForOrdering;
} }
public WildcardSearchFields[] getWildcardSearchFieldIn() { public WildcardSearchField[] getWildcardSearchFieldIn() {
return wildcardSearchFieldsIn; return wildcardSearchFieldIn;
} }
public String getWildcardSearchValueLike() { public String getWildcardSearchValueLike() {
return wildcardSearchValueLike; return wildcardSearchValueLike;
} }
private void checkForIllegalParamCombinations() {
if ((wildcardSearchValueLike != null && wildcardSearchFieldIn == null)
|| (wildcardSearchValueLike == null && wildcardSearchFieldIn != null)) {
throw new IllegalArgumentException(
"The params \"wildcardSearchFieldIn\" and \"wildcardSearchValueLike\""
+ " must be used together!");
}
}
private String getDatabaseId() { private String getDatabaseId() {
return this.taskanaEngine.getSqlSession().getConfiguration().getDatabaseId(); return this.taskanaEngine.getSqlSession().getConfiguration().getDatabaseId();
} }
@ -1922,7 +1935,7 @@ public class TaskQueryImpl implements TaskQuery {
+ ", addAttachmentClassificationNameToSelectClauseForOrdering=" + ", addAttachmentClassificationNameToSelectClauseForOrdering="
+ addAttachmentClassificationNameToSelectClauseForOrdering + addAttachmentClassificationNameToSelectClauseForOrdering
+ ", wildcardSearchFieldsIn=" + ", wildcardSearchFieldsIn="
+ wildcardSearchFieldsIn + wildcardSearchFieldIn
+ ", wildcardSearchValueLike=" + ", wildcardSearchValueLike="
+ wildcardSearchValueLike + wildcardSearchValueLike
+ "]"; + "]";

View File

@ -133,7 +133,7 @@ public interface TaskQueryMapper {
+ "<if test='attachmentReferenceIn != null'>AND a.REF_VALUE IN(<foreach item='item' collection='attachmentReferenceIn' separator=',' >#{item}</foreach>)</if> " + "<if test='attachmentReferenceIn != null'>AND a.REF_VALUE IN(<foreach item='item' collection='attachmentReferenceIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='attachmentReferenceLike != null'>AND (<foreach item='item' collection='attachmentReferenceLike' separator=' OR '>UPPER(a.REF_VALUE) LIKE #{item}</foreach>)</if> " + "<if test='attachmentReferenceLike != null'>AND (<foreach item='item' collection='attachmentReferenceLike' separator=' OR '>UPPER(a.REF_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='attachmentReceivedIn !=null'> AND ( <foreach item='item' collection='attachmentReceivedIn' separator=' OR ' > ( <if test='item.begin!=null'> a.RECEIVED &gt;= #{item.begin} </if> <if test='item.begin!=null and item.end!=null'> AND </if><if test='item.end!=null'> a.RECEIVED &lt;=#{item.end} </if>)</foreach>)</if> " + "<if test='attachmentReceivedIn !=null'> AND ( <foreach item='item' collection='attachmentReceivedIn' separator=' OR ' > ( <if test='item.begin!=null'> a.RECEIVED &gt;= #{item.begin} </if> <if test='item.begin!=null and item.end!=null'> AND </if><if test='item.end!=null'> a.RECEIVED &lt;=#{item.end} </if>)</foreach>)</if> "
+ "<if test='wildcardSearchValueLike != null and wildcardSearchFieldsIn != null'>AND (<foreach item='item' collection='wildcardSearchFieldsIn' separator=' OR '>t.${item} LIKE #{wildcardSearchValueLike}</foreach>)</if> " + "<if test='wildcardSearchValueLike != null and wildcardSearchFieldIn != null'>AND (<foreach item='item' collection='wildcardSearchFieldIn' separator=' OR '>t.${item} LIKE #{wildcardSearchValueLike}</foreach>)</if> "
+ "</where>" + "</where>"
+ "<if test='!orderBy.isEmpty()'>ORDER BY <foreach item='item' collection='orderBy' separator=',' >${item}</foreach></if> " + "<if test='!orderBy.isEmpty()'>ORDER BY <foreach item='item' collection='orderBy' separator=',' >${item}</foreach></if> "
+ "</script>") + "</script>")
@ -320,7 +320,7 @@ public interface TaskQueryMapper {
+ "<if test='attachmentReferenceIn != null'>AND a.REF_VALUE IN(<foreach item='item' collection='attachmentReferenceIn' separator=',' >#{item}</foreach>)</if> " + "<if test='attachmentReferenceIn != null'>AND a.REF_VALUE IN(<foreach item='item' collection='attachmentReferenceIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='attachmentReferenceLike != null'>AND (<foreach item='item' collection='attachmentReferenceLike' separator=' OR '>UPPER(a.REF_VALUE) LIKE #{item}</foreach>)</if> " + "<if test='attachmentReferenceLike != null'>AND (<foreach item='item' collection='attachmentReferenceLike' separator=' OR '>UPPER(a.REF_VALUE) LIKE #{item}</foreach>)</if> "
+ "<if test='attachmentReceivedIn !=null'> AND ( <foreach item='item' collection='attachmentReceivedIn' separator=' OR ' > ( <if test='item.begin!=null'> a.RECEIVED &gt;= #{item.begin} </if> <if test='item.begin!=null and item.end!=null'> AND </if><if test='item.end!=null'> a.RECEIVED &lt;=#{item.end} </if>)</foreach>)</if> " + "<if test='attachmentReceivedIn !=null'> AND ( <foreach item='item' collection='attachmentReceivedIn' separator=' OR ' > ( <if test='item.begin!=null'> a.RECEIVED &gt;= #{item.begin} </if> <if test='item.begin!=null and item.end!=null'> AND </if><if test='item.end!=null'> a.RECEIVED &lt;=#{item.end} </if>)</foreach>)</if> "
+ "<if test='wildcardSearchValueLike != null and wildcardSearchFieldsIn != null'>AND (<foreach item='item' collection='wildcardSearchFieldsIn' separator=' OR '>t.${item} LIKE #{wildcardSearchValueLike}</foreach>)</if> " + "<if test='wildcardSearchValueLike != null and wildcardSearchFieldIn != null'>AND (<foreach item='item' collection='wildcardSearchFieldIn' separator=' OR '>t.${item} LIKE #{wildcardSearchValueLike}</foreach>)</if> "
+ "</where> " + "</where> "
+ "), Y (ID, EXTERNAL_ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, DUE, NAME, CREATOR, DESCRIPTION, NOTE, PRIORITY, STATE, TCLASSIFICATION_KEY, " + "), Y (ID, EXTERNAL_ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, DUE, NAME, CREATOR, DESCRIPTION, NOTE, PRIORITY, STATE, TCLASSIFICATION_KEY, "
+ " CLASSIFICATION_CATEGORY, CLASSIFICATION_ID, WORKBASKET_ID, DOMAIN, WORKBASKET_KEY, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, OWNER, " + " CLASSIFICATION_CATEGORY, CLASSIFICATION_ID, WORKBASKET_ID, DOMAIN, WORKBASKET_KEY, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, OWNER, "

View File

@ -642,8 +642,6 @@ class QueryTasksAccTest extends AbstractAccTest {
void testQueryForOrderByWorkbasketIdDesc() { void testQueryForOrderByWorkbasketIdDesc() {
List<TaskSummary> results = List<TaskSummary> results =
taskService.createTaskQuery().orderByWorkbasketId(DESCENDING).list(); taskService.createTaskQuery().orderByWorkbasketId(DESCENDING).list();
.orderByCustomAttribute("4", DESCENDING)
assertEquals("99rty", results.get(0).getCustomAttribute("4"));
assertThat(results) assertThat(results)
.hasSizeGreaterThan(2) .hasSizeGreaterThan(2)

View File

@ -1,9 +1,11 @@
package acceptance.task; package acceptance.task;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import acceptance.AbstractAccTest; import acceptance.AbstractAccTest;
import java.util.List; import java.util.List;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -11,7 +13,7 @@ import pro.taskana.common.api.BaseQuery.SortDirection;
import pro.taskana.security.JaasExtension; import pro.taskana.security.JaasExtension;
import pro.taskana.security.WithAccessId; import pro.taskana.security.WithAccessId;
import pro.taskana.task.api.TaskService; import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.WildcardSearchFields; import pro.taskana.task.api.WildcardSearchField;
import pro.taskana.task.api.models.TaskSummary; import pro.taskana.task.api.models.TaskSummary;
@ExtendWith(JaasExtension.class) @ExtendWith(JaasExtension.class)
@ -24,8 +26,8 @@ public class QueryTasksByWildcardSearchAccTest extends AbstractAccTest {
void should_ReturnAllTasksByWildcardSearch_For_ProvidedSearchValue() { void should_ReturnAllTasksByWildcardSearch_For_ProvidedSearchValue() {
TaskService taskService = taskanaEngine.getTaskService(); TaskService taskService = taskanaEngine.getTaskService();
WildcardSearchFields[] wildcards = { WildcardSearchField[] wildcards = {
WildcardSearchFields.CUSTOM_3, WildcardSearchFields.CUSTOM_4, WildcardSearchFields.NAME WildcardSearchField.CUSTOM_3, WildcardSearchField.CUSTOM_4, WildcardSearchField.NAME
}; };
List<TaskSummary> foundTasks = List<TaskSummary> foundTasks =
@ -43,30 +45,53 @@ public class QueryTasksByWildcardSearchAccTest extends AbstractAccTest {
userName = "teamlead_1", userName = "teamlead_1",
groupNames = {"group_1", "group_2"}) groupNames = {"group_1", "group_2"})
@Test @Test
void should_ReturnAllTasks_When_ProvidingNoSearchFieldsOrValue() { void should_ReturnAllTasks_For_ProvidedSearchValueAndAdditionalParameters() {
TaskService taskService = taskanaEngine.getTaskService(); TaskService taskService = taskanaEngine.getTaskService();
WildcardSearchFields[] wildcards = { WildcardSearchField[] wildcards = {
WildcardSearchFields.CUSTOM_3, WildcardSearchFields.CUSTOM_4, WildcardSearchFields.NAME WildcardSearchField.CUSTOM_3, WildcardSearchField.CUSTOM_4, WildcardSearchField.NAME
}; };
List<TaskSummary> foundTasks = List<TaskSummary> foundTasks =
taskService taskService
.createTaskQuery() .createTaskQuery()
.wildcardSearchFieldsIn(wildcards) .wildcardSearchFieldsIn(wildcards)
.wildcardSearchValueLike("%99%")
.ownerIn("user_1_1")
.businessProcessIdLike("%PI2%")
.orderByName(SortDirection.ASCENDING) .orderByName(SortDirection.ASCENDING)
.list(); .list();
assertThat(foundTasks).hasSize(83); assertThat(foundTasks).hasSize(1);
}
foundTasks = @WithAccessId(
userName = "teamlead_1",
groupNames = {"group_1", "group_2"})
@Test
void should_ThrowException_When_NotUsingSearchFieldsAndValueParamsTogether() {
TaskService taskService = taskanaEngine.getTaskService();
ThrowingCallable queryAttempt =
() ->
taskService taskService
.createTaskQuery() .createTaskQuery()
.wildcardSearchValueLike("%99%") .wildcardSearchValueLike("%99%")
.orderByName(SortDirection.ASCENDING) .orderByName(SortDirection.ASCENDING)
.list(); .list();
assertThat(foundTasks).hasSize(83); assertThatThrownBy(queryAttempt).isInstanceOf(IllegalArgumentException.class);
queryAttempt =
() ->
taskService
.createTaskQuery()
.wildcardSearchFieldsIn(
WildcardSearchField.CUSTOM_1, WildcardSearchField.DESCRIPTION)
.orderByName(SortDirection.ASCENDING)
.list();
assertThatThrownBy(queryAttempt).isInstanceOf(IllegalArgumentException.class);
} }
} }

View File

@ -37,7 +37,7 @@ import pro.taskana.rest.resource.TaskSummaryResourceAssembler;
import pro.taskana.task.api.TaskQuery; import pro.taskana.task.api.TaskQuery;
import pro.taskana.task.api.TaskService; import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.TaskState; import pro.taskana.task.api.TaskState;
import pro.taskana.task.api.WildcardSearchFields; import pro.taskana.task.api.WildcardSearchField;
import pro.taskana.task.api.exceptions.AttachmentPersistenceException; import pro.taskana.task.api.exceptions.AttachmentPersistenceException;
import pro.taskana.task.api.exceptions.InvalidOwnerException; import pro.taskana.task.api.exceptions.InvalidOwnerException;
import pro.taskana.task.api.exceptions.InvalidStateException; import pro.taskana.task.api.exceptions.InvalidStateException;
@ -413,12 +413,12 @@ public class TaskController extends AbstractPagingController {
return taskQuery; return taskQuery;
} }
private WildcardSearchFields[] createWildcardSearchFields(String[] wildcardFields) { private WildcardSearchField[] createWildcardSearchFields(String[] wildcardFields) {
return Stream.of(wildcardFields) return Stream.of(wildcardFields)
.map(WildcardSearchFields::fromString) .map(WildcardSearchField::fromString)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.toArray(WildcardSearchFields[]::new); .toArray(WildcardSearchField[]::new);
} }
private void updateTaskQueryWithWorkbasketKey( private void updateTaskQueryWithWorkbasketKey(
@ -474,15 +474,11 @@ public class TaskController extends AbstractPagingController {
&& params.containsKey(WILDCARD_SEARCH_VALUE)) { && params.containsKey(WILDCARD_SEARCH_VALUE)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"It is prohibited to use the params " "The params "
+ "\""
+ WILDCARD_SEARCH_FIELDS + WILDCARD_SEARCH_FIELDS
+ "\"" + " and "
+ " or "
+ "\""
+ WILDCARD_SEARCH_VALUE + WILDCARD_SEARCH_VALUE
+ "\"" + " must be used together!");
+ " without one another. If one is provided you must provide the other one as well");
} }
} }