TSK-167 Implement Workbasket query extensions

This commit is contained in:
BerndBreier 2018-01-29 13:15:14 +01:00 committed by Holger Hagen
parent 5db29f647b
commit 01cee64673
9 changed files with 143 additions and 55 deletions

View File

@ -12,7 +12,8 @@ import pro.taskana.model.WorkbasketType;
public interface WorkbasketQuery extends BaseQuery<WorkbasketSummary> {
/**
* Add your keys to your query.
* Add your keys to your query. The keys are compared case-insensitively to the keys of workbaskets with the IN
* operator.
*
* @param key
* the keys as Strings
@ -21,7 +22,18 @@ public interface WorkbasketQuery extends BaseQuery<WorkbasketSummary> {
WorkbasketQuery keyIn(String... key);
/**
* Add your names to your query.
* Add keys to your query. The keys are compared case-insensitively to the keys of workbaskets with the SQL LIKE
* operator. You may add a wildcard like '%' to search generically. If you specify multiple keys they are connected
* with an OR operator, this is, the query searches workbaskets whose keys are like key1 or like key2, etc.
*
* @param key
* the keys as Strings
* @return the query
*/
BaseQuery<WorkbasketSummary> keyLike(String... key);
/**
* Add your names to your query. The names are compared case-insensitively to the names of workbaskets
*
* @param name
* the names as Strings
@ -29,6 +41,30 @@ public interface WorkbasketQuery extends BaseQuery<WorkbasketSummary> {
*/
WorkbasketQuery nameIn(String... name);
/**
* Add names to your query. The names are compared case-insensitively to the names of workbaskets with the SQL LIKE
* operator. You may add a wildcard like '%' to search generically. If you specify multiple names, they are
* connected with an OR operator, this is, the query searches workbaskets whose names are like name1 or like name2,
* etc.
*
* @param name
* the names as Strings
* @return the query
*/
BaseQuery<WorkbasketSummary> nameLike(String... name);
/**
* Add search strings to your query that are searched case-insensitively in the key and name fields of workbaskets.
* You may add a wildcard like '%' to search generically. If you specify multiple keys they are connected with an OR
* operator, this is, the query searches workbaskets whose keys are like string1 or whose names are like string1 or
* whose keys are like string2 or whose names are like string2, etc...
*
* @param searchString
* the seach strings
* @return the query
*/
BaseQuery<WorkbasketSummary> keyOrNameLike(String... searchString);
/**
* Add your domains to your query.
*
@ -84,8 +120,8 @@ public interface WorkbasketQuery extends BaseQuery<WorkbasketSummary> {
WorkbasketQuery modifiedBefore(Instant modifiedBefore);
/**
* Add your description to your query. It will be compared in SQL with an LIKE. If you use a wildcard like % tehn it
* will be transmitted to the database.
* Add your description to your query. It will be compared case-insensitively to the descriptions of workbaskets.
* You may use a wildcard like '%' to search generically.
*
* @param description
* your description
@ -130,4 +166,5 @@ public interface WorkbasketQuery extends BaseQuery<WorkbasketSummary> {
* when permission OR accessIds of the userContext are NULL.
*/
WorkbasketQuery callerHasPermission(WorkbasketAuthorization permission) throws InvalidArgumentException;
}

View File

@ -171,6 +171,7 @@ public interface WorkbasketService {
* Returns a set with all permissions of the current user at this workbasket.
*
* @param workbasketKey
* The key of the referenced workbasket
* @return a Set with all permissions
*/
List<WorkbasketAuthorization> getPermissionsForWorkbasket(String workbasketKey);

View File

@ -237,9 +237,9 @@ public class WorkbasketImpl implements Workbasket {
builder.append(", key=");
builder.append(key);
builder.append(", created=");
builder.append(created.toString());
builder.append(created);
builder.append(", modified=");
builder.append(modified.toString());
builder.append(modified);
builder.append(", name=");
builder.append(name);
builder.append(", description=");

View File

@ -8,6 +8,7 @@ import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.BaseQuery;
import pro.taskana.TaskanaEngine;
import pro.taskana.WorkbasketQuery;
import pro.taskana.WorkbasketSummary;
@ -30,15 +31,18 @@ public class WorkbasketQueryImpl implements WorkbasketQuery {
private static final Logger LOGGER = LoggerFactory.getLogger(WorkbasketQueryImpl.class);
private String[] accessId;
private WorkbasketAuthorization authorization;
private String[] name;
private String[] key;
private String[] nameIn;
private String[] nameLike;
private String[] keyIn;
private String[] keyLike;
private String[] keyOrNameLike;
private String[] domain;
private WorkbasketType[] type;
private Instant createdAfter;
private Instant createdBefore;
private Instant modifiedAfter;
private Instant modifiedBefore;
private String description;
private String descriptionLike;
private String[] owner;
private TaskanaEngineImpl taskanaEngineImpl;
@ -48,7 +52,7 @@ public class WorkbasketQueryImpl implements WorkbasketQuery {
@Override
public WorkbasketQuery keyIn(String... key) {
this.key = key;
this.keyIn = toUpperCopy(key);
return this;
}
@ -66,7 +70,25 @@ public class WorkbasketQueryImpl implements WorkbasketQuery {
@Override
public WorkbasketQuery nameIn(String... names) {
this.name = names;
this.nameIn = toUpperCopy(names);
return this;
}
@Override
public BaseQuery<WorkbasketSummary> nameLike(String... names) {
this.nameLike = toUpperCopy(names);
return this;
}
@Override
public BaseQuery<WorkbasketSummary> keyLike(String... keys) {
this.keyLike = toUpperCopy(keys);
return this;
}
@Override
public BaseQuery<WorkbasketSummary> keyOrNameLike(String... keysOrNames) {
this.keyOrNameLike = toUpperCopy(keysOrNames);
return this;
}
@ -96,7 +118,7 @@ public class WorkbasketQueryImpl implements WorkbasketQuery {
@Override
public WorkbasketQuery descriptionLike(String description) {
this.description = description;
this.descriptionLike = description.toUpperCase();
return this;
}
@ -207,12 +229,24 @@ public class WorkbasketQueryImpl implements WorkbasketQuery {
return authorization;
}
public String[] getName() {
return name;
public String[] getNameIn() {
return nameIn;
}
public String[] getKey() {
return key;
public String[] getNameLike() {
return nameLike;
}
public String[] getKeyIn() {
return keyIn;
}
public String[] getKeyLike() {
return keyLike;
}
public String[] getKeyOrNameLike() {
return keyOrNameLike;
}
public String[] getDomain() {
@ -239,8 +273,8 @@ public class WorkbasketQueryImpl implements WorkbasketQuery {
return modifiedBefore;
}
public String getDescription() {
return description;
public String getDescriptionLike() {
return descriptionLike;
}
public String[] getOwner() {
@ -254,10 +288,16 @@ public class WorkbasketQueryImpl implements WorkbasketQuery {
builder.append(Arrays.toString(accessId));
builder.append(", authorization=");
builder.append(authorization);
builder.append(", name=");
builder.append(Arrays.toString(name));
builder.append(", key=");
builder.append(Arrays.toString(key));
builder.append(", nameIn=");
builder.append(Arrays.toString(nameIn));
builder.append(", nameLike=");
builder.append(Arrays.toString(nameLike));
builder.append(", keyIn=");
builder.append(Arrays.toString(keyIn));
builder.append(", keyLike=");
builder.append(Arrays.toString(keyLike));
builder.append(", keyOrNameLike=");
builder.append(Arrays.toString(keyOrNameLike));
builder.append(", domain=");
builder.append(Arrays.toString(domain));
builder.append(", type=");
@ -270,10 +310,12 @@ public class WorkbasketQueryImpl implements WorkbasketQuery {
builder.append(modifiedAfter);
builder.append(", modifiedBefore=");
builder.append(modifiedBefore);
builder.append(", description=");
builder.append(description);
builder.append(", descriptionLike=");
builder.append(descriptionLike);
builder.append(", owner=");
builder.append(Arrays.toString(owner));
builder.append(", taskanaEngineImpl=");
builder.append(taskanaEngineImpl);
builder.append("]");
return builder.toString();
}
@ -288,4 +330,13 @@ public class WorkbasketQueryImpl implements WorkbasketQuery {
}
}
}
private String[] toUpperCopy(String... source) {
String[] target = new String[source.length];
for (int i = 0; i < source.length; i++) {
target[i] = source[i].toUpperCase();
}
return target;
}
}

View File

@ -52,7 +52,7 @@ public interface QueryMapper {
+ "<if test='customFields != null'>AND (t.CUSTOM_1 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR t.CUSTOM_2 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR t.CUSTOM_3 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR t.CUSTOM_4 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR t.CUSTOM_5 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR t.CUSTOM_6 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR t.CUSTOM_7 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR t.CUSTOM_8 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR t.CUSTOM_9 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR t.CUSTOM_10 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>))</if> "
+ "</where>"
+ "</script>")
@Results(value = { @Result(property = "taskId", column = "ID"),
@Results(value = {@Result(property = "taskId", column = "ID"),
@Result(property = "created", column = "CREATED"),
@Result(property = "claimed", column = "CLAIMED"),
@Result(property = "completed", column = "COMPLETED"),
@ -86,7 +86,7 @@ public interface QueryMapper {
@Result(property = "custom7", column = "CUSTOM_7"),
@Result(property = "custom8", column = "CUSTOM_8"),
@Result(property = "custom9", column = "CUSTOM_9"),
@Result(property = "custom10", column = "CUSTOM_10") })
@Result(property = "custom10", column = "CUSTOM_10")})
List<TaskSummaryImpl> queryTasks(TaskQueryImpl taskQuery);
@Select("<script>SELECT ID, KEY, PARENT_CLASSIFICATION_KEY, CATEGORY, TYPE, DOMAIN, VALID_IN_DOMAIN, CREATED, NAME, DESCRIPTION, PRIORITY, SERVICE_LEVEL, APPLICATION_ENTRY_POINT, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, CUSTOM_5, CUSTOM_6, CUSTOM_7, CUSTOM_8 "
@ -107,12 +107,12 @@ public interface QueryMapper {
+ "<if test='customFields != null'>AND (CUSTOM_1 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR CUSTOM_2 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR CUSTOM_3 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR CUSTOM_4 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR CUSTOM_5 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR CUSTOM_6 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR CUSTOM_7 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>) OR CUSTOM_8 IN(<foreach item='item' collection='customFields' separator=',' >#{item}</foreach>))</if> "
+ "</where>"
+ "</script>")
@Results({ @Result(property = "id", column = "ID"),
@Results({@Result(property = "id", column = "ID"),
@Result(property = "key", column = "KEY"),
@Result(property = "category", column = "CATEGORY"),
@Result(property = "type", column = "TYPE"),
@Result(property = "domain", column = "DOMAIN"),
@Result(property = "name", column = "NAME") })
@Result(property = "name", column = "NAME")})
List<ClassificationSummaryImpl> queryClassification(ClassificationQueryImpl classificationQuery);
@Select("<script>SELECT ID, COMPANY, SYSTEM, SYSTEM_INSTANCE, TYPE, VALUE "
@ -131,22 +131,25 @@ public interface QueryMapper {
@Result(property = "system", column = "SYSTEM"),
@Result(property = "systemInstance", column = "SYSTEM_INSTANCE"),
@Result(property = "type", column = "TYPE"),
@Result(property = "value", column = "VALUE") })
@Result(property = "value", column = "VALUE")})
List<ObjectReference> queryObjectReference(ObjectReferenceQueryImpl objectReference);
@Select("<script>SELECT w.ID, w.KEY, w.NAME, w.DOMAIN, W.TYPE, w.DESCRIPTION, w.OWNER, w.ORG_LEVEL_1, w.ORG_LEVEL_2, w.ORG_LEVEL_3, w.ORG_LEVEL_4 from WORKBASKET w "
+ "<if test='accessId != null'>LEFT OUTER JOIN WORKBASKET_ACCESS_LIST a on w.KEY = a.WORKBASKET_KEY</if> "
+ "<where>"
+ "<if test='owner != null'>AND w.OWNER IN(<foreach item='item' collection='owner' separator=',' >#{item}</foreach>)</if> "
+ "<if test='key != null'>AND w.KEY IN(<foreach item='item' collection='key' separator=',' >#{item}</foreach>)</if> "
+ "<if test='name != null'>AND w.NAME IN(<foreach item='item' collection='name' separator=',' >#{item}</foreach>)</if> "
+ "<if test='keyIn != null'>AND UPPER(w.KEY) IN(<foreach item='item' collection='keyIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='keyLike != null'>AND (<foreach item='item' collection='keyLike' separator=' OR ' >UPPER(w.KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='nameIn != null'>AND UPPER(w.NAME) IN(<foreach item='item' collection='nameIn' separator=',' >#{item}</foreach>)</if> "
+ "<if test='nameLike != null'>AND (<foreach item='item' collection='nameLike' separator=' OR ' >UPPER(w.NAME) LIKE #{item}</foreach>)</if> "
+ "<if test='keyOrNameLike != null'>AND (<foreach item='item' collection='keyOrNameLike' separator=' OR ' >UPPER(w.NAME) LIKE #{item} OR UPPER(w.KEY) LIKE #{item}</foreach>)</if> "
+ "<if test='domain != null'>AND w.DOMAIN IN(<foreach item='item' collection='domain' separator=',' >#{item}</foreach>)</if> "
+ "<if test='type!= null'>AND w.TYPE IN(<foreach item='item' collection='type' separator=',' >#{item}</foreach>)</if> "
+ "<if test='createdAfter != null'>AND w.CREATED &gt; #{createdAfter}</if> "
+ "<if test='createdBefore != null'>AND w.CREATED &lt; #{createdBefore}</if> "
+ "<if test='modifiedAfter != null'>AND w.MODIFIED &gt; #{modifiedAfter}</if> "
+ "<if test='modifiedBefore != null'>AND w.MODIFIED &lt; #{modifiedBefore}</if> "
+ "<if test='description != null'>AND w.DESCRIPTION like #{description}</if> "
+ "<if test='descriptionLike != null'>AND UPPER(w.DESCRIPTION) like #{descriptionLike}</if> "
+ "<if test='accessId != null'>AND a.ACCESS_ID IN(<foreach item='item' collection='accessId' separator=',' >#{item}</foreach>) AND PERM_READ = 1 </if> "
+ "<if test='authorization != null'>AND "
+ "<if test=\"authorization.name().equals('OPEN')\">PERM_OPEN</if> "
@ -176,6 +179,6 @@ public interface QueryMapper {
@Result(property = "orgLevel1", column = "ORG_LEVEL_1"),
@Result(property = "orgLevel2", column = "ORG_LEVEL_2"),
@Result(property = "orgLevel3", column = "ORG_LEVEL_3"),
@Result(property = "orgLevel4", column = "ORG_LEVEL_4") })
@Result(property = "orgLevel4", column = "ORG_LEVEL_4")})
List<WorkbasketSummaryImpl> queryWorkbasket(WorkbasketQueryImpl workbasketQuery);
}

View File

@ -6,7 +6,6 @@ import java.util.List;
import org.h2.store.fs.FileUtils;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -60,35 +59,32 @@ public class QueryWorkbasketAccTest extends AbstractAccTest {
Assert.assertEquals("GPK_KSC", results.get(0).getKey());
}
@Ignore
@Test
public void testQueryWorkbasketByNameStartsWith()
throws SQLException, NotAuthorizedException, InvalidArgumentException {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
List<WorkbasketSummary> results = workbasketService.createWorkbasketQuery()
// .nameLike("%Gruppenpostkorb KSC%")
.nameLike("%Gruppenpostkorb KSC%")
.list();
Assert.assertEquals(6L, results.size());
}
@Ignore
@Test
public void testQueryWorkbasketByNameContains()
throws SQLException, NotAuthorizedException, InvalidArgumentException {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
List<WorkbasketSummary> results = workbasketService.createWorkbasketQuery()
// .nameLike("%Teamlead%")
.nameLike("%Teamlead%", "%Gruppenpostkorb KSC%")
.list();
Assert.assertEquals(2L, results.size());
Assert.assertEquals(8L, results.size());
}
@Ignore
@Test
public void testQueryWorkbasketByNameContainsCaseInsensitive()
throws SQLException, NotAuthorizedException, InvalidArgumentException {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
List<WorkbasketSummary> results = workbasketService.createWorkbasketQuery()
// .nameLike("%TEAMLEAD%")
.nameLike("%TEAMLEAD%")
.list();
Assert.assertEquals(2L, results.size());
}
@ -118,40 +114,37 @@ public class QueryWorkbasketAccTest extends AbstractAccTest {
throws SQLException, NotAuthorizedException, InvalidArgumentException {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
List<WorkbasketSummary> results = workbasketService.createWorkbasketQuery()
.keyIn("GPK_KSC_1", "GPK_KSC_2", "GPK_KSC_3")
.keyIn("GPK_KSC_1", "GPK_Ksc_2", "GPK_KSC_3")
.list();
Assert.assertEquals(2L, results.size());
}
@Ignore
@Test
public void testQueryWorkbasketByKeyContains()
throws SQLException, NotAuthorizedException, InvalidArgumentException {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
List<WorkbasketSummary> results = workbasketService.createWorkbasketQuery()
// .keyLike("%KSC%")
.keyLike("%KSC%")
.list();
Assert.assertEquals(6L, results.size());
}
@Ignore
@Test
public void testQueryWorkbasketByKeyContainsIgnoreCase()
throws SQLException, NotAuthorizedException, InvalidArgumentException {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
List<WorkbasketSummary> results = workbasketService.createWorkbasketQuery()
// .keyLike("%kSc%")
.keyLike("%kSc%")
.list();
Assert.assertEquals(6L, results.size());
}
@Ignore
@Test
public void testQueryWorkbasketByKeyOrNameContainsIgnoreCase()
throws SQLException, NotAuthorizedException, InvalidArgumentException {
WorkbasketService workbasketService = taskanaEngine.getWorkbasketService();
List<WorkbasketSummary> results = workbasketService.createWorkbasketQuery()
// .keyOrNameLike("%kSc%")
.keyOrNameLike("%kSc%")
.list();
Assert.assertEquals(12L, results.size());
}

View File

@ -1,6 +1,7 @@
package pro.taskana.impl;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@ -119,7 +120,7 @@ public class ClassificationServiceImplTest {
verify(taskanaEngineImplMock, times(2)).returnConnection();
verifyNoMoreInteractions(classificationMapperMock, taskanaEngineImplMock, classificationQueryImplMock);
assertThat(classification.getCreated().toString().substring(0, 10), equalTo(todaysDate));
assertTrue(classification.getCreated().isBefore(Instant.now()));
assertFalse(classification.getCreated().isAfter(Instant.now()));
assertTrue(classification.getCreated().isAfter(beforeTimestamp));
assertThat(classification.getDomain(), equalTo(domain));
assertThat(classification.getKey(), equalTo(key));

View File

@ -83,6 +83,7 @@ public class TaskServiceImplIntExplicitTest {
DataSource ds = TaskanaEngineConfigurationTest.getDataSource();
DBCleaner cleaner = new DBCleaner();
cleaner.clearDb(ds, true);
FileUtils.deleteRecursive("~/data", true);
}
@Before
@ -325,7 +326,7 @@ public class TaskServiceImplIntExplicitTest {
taskServiceImpl.createTask(task);
}
@WithAccessId(userName = "Elena", groupNames = { "DummyGroup" })
@WithAccessId(userName = "Elena", groupNames = {"DummyGroup"})
@Test
public void should_ReturnList_when_BuilderIsUsed() throws SQLException, NotAuthorizedException,
WorkbasketNotFoundException, ClassificationNotFoundException, ClassificationAlreadyExistException,

View File

@ -258,7 +258,7 @@ public class WorkbasketServiceImplIntAutocommitTest {
}
}
@WithAccessId(userName = "Bernd", groupNames = { "group1", "group2", "group3", "group4" })
@WithAccessId(userName = "Bernd", groupNames = {"group1", "group2", "group3", "group4"})
@Test
public void testWorkbasketQuery()
throws NotAuthorizedException, InvalidArgumentException, InvalidWorkbasketException,
@ -313,13 +313,14 @@ public class WorkbasketServiceImplIntAutocommitTest {
}
WorkbasketQuery query5 = workBasketService.createWorkbasketQuery()
.modifiedAfter(thirtyDaysAgo)
.modifiedBefore(tenDaysAgo);
.modifiedAfter(now.minus(Duration.ofDays(31L)))
.modifiedBefore(now.minus(Duration.ofDays(9)));
List<WorkbasketSummary> result5 = query5.list();
assertTrue(result5.size() == THREE);
assertTrue(result5.size() == 4);
for (WorkbasketSummary workbasket : result5) {
String name = workbasket.getName();
assertTrue("Basket1".equals(name) || "Basket2".equals(name) || "Basket4".equals(name));
assertTrue(
"Basket1".equals(name) || "Basket2".equals(name) || "Basket3".equals(name) || "Basket4".equals(name));
}
WorkbasketQuery query6 = workBasketService.createWorkbasketQuery()