Skip to content

Commit

Permalink
Add support for querying historic variables by case instance and proc…
Browse files Browse the repository at this point in the history
…ess isntance ids
  • Loading branch information
filiphr committed Oct 24, 2024
1 parent 7947515 commit 7095059
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package org.flowable.cmmn.api.history;

import java.util.Collection;
import java.util.Set;

import org.flowable.common.engine.api.query.Query;
Expand All @@ -27,6 +28,9 @@ public interface HistoricVariableInstanceQuery extends Query<HistoricVariableIns

/** Only select historic variables with the given case instance. */
HistoricVariableInstanceQuery caseInstanceId(String caseInstanceId);

/** Only select historic variables with the given case instances. */
HistoricVariableInstanceQuery caseInstanceIds(Collection<String> caseInstanceIds);

/** Only select historic variables with the given plan item instance id. */
HistoricVariableInstanceQuery planItemInstanceId(String planItemInstanceId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package org.flowable.cmmn.engine.impl.history;

import java.util.Collection;
import java.util.List;
import java.util.Set;

Expand Down Expand Up @@ -51,6 +52,13 @@ public HistoricVariableInstanceQuery caseInstanceId(String caseInstanceId) {
return this;
}

@Override
public HistoricVariableInstanceQuery caseInstanceIds(Collection<String> caseInstanceIds) {
wrappedHistoricVariableInstanceQuery.scopeIds(caseInstanceIds);
wrappedHistoricVariableInstanceQuery.scopeType(ScopeTypes.CMMN);
return this;
}

@Override
public HistoricVariableInstanceQuery planItemInstanceId(String planItemInstanceId) {
wrappedHistoricVariableInstanceQuery.subScopeId(planItemInstanceId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;
import static org.assertj.core.api.Assertions.tuple;

import java.io.Serializable;
import java.util.ArrayList;
Expand Down Expand Up @@ -358,6 +359,38 @@ public void testHistoricVariables() {
}
}

@Test
@CmmnDeployment(resources = "org/flowable/cmmn/test/task/CmmnTaskServiceTest.testOneHumanTaskCase.cmmn")
public void testVariableInstanceQueryByCaseInstanceIds() {
CaseInstance caseInstance1 = cmmnRuntimeService.createCaseInstanceBuilder()
.caseDefinitionKey("oneHumanTaskCase")
.variable("myVar", "test1")
.start();

cmmnRuntimeService.createCaseInstanceBuilder()
.caseDefinitionKey("oneHumanTaskCase")
.variable("myVar", "test2")
.start();

CaseInstance caseInstance3 = cmmnRuntimeService.createCaseInstanceBuilder()
.caseDefinitionKey("oneHumanTaskCase")
.variable("myVar", "test3")
.start();

if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.AUDIT, cmmnEngineConfiguration)) {
Set<String> ids = new HashSet<>();
ids.add(caseInstance1.getId());
ids.add(caseInstance3.getId());
assertThat(cmmnHistoryService.createHistoricVariableInstanceQuery().caseInstanceIds(ids).count()).isEqualTo(2);
assertThat(cmmnHistoryService.createHistoricVariableInstanceQuery().caseInstanceIds(ids).list())
.extracting(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue)
.containsExactlyInAnyOrder(
tuple("myVar", "test1"),
tuple("myVar", "test3")
);
}
}

@Test
@CmmnDeployment
public void testTransientVariables() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.flowable.common.engine.impl.query;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import org.flowable.common.engine.api.FlowableException;
Expand All @@ -21,10 +22,12 @@
import org.flowable.common.engine.api.query.QueryProperty;
import org.flowable.common.engine.impl.Direction;
import org.flowable.common.engine.impl.context.Context;
import org.flowable.common.engine.impl.db.AbstractDataManager;
import org.flowable.common.engine.impl.db.ListQueryParameterObject;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
import org.flowable.common.engine.impl.util.CollectionUtil;

/**
* Abstract superclass for all query types.
Expand Down Expand Up @@ -97,6 +100,10 @@ protected void checkQueryOk() {
}
}

protected <E> List<List<E>> getSafeList(Collection<E> collection) {
return CollectionUtil.partition(collection, AbstractDataManager.MAX_ENTRIES_IN_CLAUSE);
}

@Override
@SuppressWarnings("unchecked")
public U singleResult() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package org.flowable.engine.test.history;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;

import java.util.Arrays;
import java.util.HashMap;
Expand All @@ -26,6 +27,7 @@
import org.flowable.common.engine.impl.util.CollectionUtil;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricDetail;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricVariableUpdate;
import org.flowable.engine.impl.test.HistoryTestHelper;
import org.flowable.engine.impl.test.PluggableFlowableTestCase;
Expand Down Expand Up @@ -345,6 +347,40 @@ public void testHistoricVariableQuery2() {

}

@Test
public void testHistoricVariableQueryByProcessInstanceIds() {
deployTwoTasksTestProcess();

Set<String> processInstanceIds = new HashSet<>();
ProcessInstance instance1 = runtimeService.createProcessInstanceBuilder()
.processDefinitionKey("twoTasksProcess")
.variable("startVar", "hello")
.start();
runtimeService.createProcessInstanceBuilder()
.processDefinitionKey("twoTasksProcess")
.variable("startVar2", "hello2")
.start();
ProcessInstance instance3 = runtimeService.createProcessInstanceBuilder()
.processDefinitionKey("twoTasksProcess")
.variable("startVar3", "hello3")
.start();
processInstanceIds.add(instance1.getId());
processInstanceIds.add(instance3.getId());

waitForHistoryJobExecutorToProcessAllJobs(7000, 100);

assertThat(historyService.createHistoricVariableInstanceQuery().processInstanceIds(processInstanceIds).count()).isEqualTo(2);
assertThat(historyService.createHistoricVariableInstanceQuery().processInstanceIds(processInstanceIds).list()).hasSize(2);

assertThat(historyService.createHistoricVariableInstanceQuery().processInstanceIds(processInstanceIds).list())
.extracting(HistoricVariableInstance::getVariableName, HistoricVariableInstance::getValue)
.containsExactlyInAnyOrder(
tuple("startVar", "hello"),
tuple("startVar3", "hello3")
);
}


@Test
public void testHistoricVariableQueryByExecutionIds() {
deployTwoTasksTestProcess();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

package org.flowable.variable.api.history;

import java.util.Collection;
import java.util.Collections;
import java.util.Set;

import org.flowable.common.engine.api.query.Query;
Expand All @@ -31,6 +33,9 @@ public interface HistoricVariableInstanceQuery extends Query<HistoricVariableIns
/** Only select historic process variables with the given process instance. */
HistoricVariableInstanceQuery processInstanceId(String processInstanceId);

/** Only select historic process variables with the given process instances. */
HistoricVariableInstanceQuery processInstanceIds(Collection<String> processInstanceIds);

/** Only select historic process variables with the given id. **/
HistoricVariableInstanceQuery executionId(String executionId);

Expand Down Expand Up @@ -77,6 +82,11 @@ public interface HistoricVariableInstanceQuery extends Query<HistoricVariableIns
* Only select historic variables with the given scope id.
*/
HistoricVariableInstanceQuery scopeId(String scopeId);

/**
* Only select historic variables with the given scope ids.
*/
HistoricVariableInstanceQuery scopeIds(Collection<String> scopeIds);

/**
* Only select historic variables with the given sub scope id.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

package org.flowable.variable.service.impl;

import java.util.Collection;
import java.util.List;
import java.util.Set;

Expand Down Expand Up @@ -44,12 +45,14 @@ public class HistoricVariableInstanceQueryImpl extends AbstractQuery<HistoricVar
protected String executionId;
protected Set<String> executionIds;
protected String processInstanceId;
protected Collection<String> processInstanceIds;
protected String activityInstanceId;
protected String variableName;
protected String variableNameLike;
protected boolean excludeTaskRelated;
protected boolean excludeVariableInitialization;
protected String scopeId;
protected Collection<String> scopeIds;
protected String subScopeId;
protected String scopeType;
protected QueryVariableValue queryVariableValue;
Expand Down Expand Up @@ -83,6 +86,15 @@ public HistoricVariableInstanceQueryImpl processInstanceId(String processInstanc
return this;
}

@Override
public HistoricVariableInstanceQuery processInstanceIds(Collection<String> processInstanceIds) {
if (processInstanceIds == null || processInstanceIds.isEmpty()) {
throw new FlowableIllegalArgumentException("processInstanceIds is empty");
}
this.processInstanceIds = processInstanceIds;
return this;
}

@Override
public HistoricVariableInstanceQueryImpl executionId(String executionId) {
if (executionId == null) {
Expand Down Expand Up @@ -242,6 +254,15 @@ public HistoricVariableInstanceQuery scopeId(String scopeId) {
return this;
}

@Override
public HistoricVariableInstanceQuery scopeIds(Collection<String> scopeIds) {
if (scopeIds == null || scopeIds.isEmpty()) {
throw new FlowableIllegalArgumentException("scopeIds is empty");
}
this.scopeIds = scopeIds;
return this;
}

@Override
public HistoricVariableInstanceQuery subScopeId(String subScopeId) {
if (excludeLocalVariables) {
Expand Down Expand Up @@ -334,6 +355,14 @@ public String getProcessInstanceId() {
return processInstanceId;
}

public Collection<String> getProcessInstanceIds() {
return processInstanceIds;
}

public List<List<String>> getSafeProcessInstanceIds() {
return getSafeList(processInstanceIds);
}

public String getTaskId() {
return taskId;
}
Expand All @@ -358,6 +387,14 @@ public String getScopeId() {
return scopeId;
}

public Collection<String> getScopeIds() {
return scopeIds;
}

public List<List<String>> getSafeScopeIds() {
return getSafeList(scopeIds);
}

public String getSubScopeId() {
return subScopeId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,16 @@
<if test="processInstanceId != null">
and RES.PROC_INST_ID_ = #{processInstanceId, jdbcType=NVARCHAR}
</if>
<if test="processInstanceIds != null and !processInstanceIds.empty">
and (
<foreach item="listItem" collection="safeProcessInstanceIds" separator="OR">
RES.PROC_INST_ID_ in
<foreach item="item" collection="listItem" open="(" separator="," close=")">
#{item, jdbcType=NVARCHAR}
</foreach>
</foreach>
)
</if>
<if test="executionId != null">
and RES.EXECUTION_ID_ = #{executionId, jdbcType=NVARCHAR}
</if>
Expand All @@ -381,10 +391,14 @@
and RES.TASK_ID_ = #{taskId, jdbcType=NVARCHAR}
</if>
<if test="taskIds != null and !taskIds.empty">
and RES.TASK_ID_ in
<foreach item="taskId" index="index" collection="taskIds" open="(" separator="," close=")">
#{taskId, jdbcType=NVARCHAR}
and (
<foreach item="listItem" collection="safeTaskIds" separator="OR">
RES.TASK_ID_ in
<foreach item="item" collection="listItem" open="(" separator="," close=")">
#{item, jdbcType=NVARCHAR}
</foreach>
</foreach>
)
</if>
<if test="excludeTaskRelated">
and RES.TASK_ID_ is NULL
Expand All @@ -397,6 +411,16 @@
<if test="scopeId != null">
and RES.SCOPE_ID_ = #{scopeId, jdbcType=NVARCHAR}
</if>
<if test="scopeIds != null and !scopeIds.empty">
and (
<foreach item="listItem" collection="safeScopeIds" separator="OR">
RES.SCOPE_ID_ in
<foreach item="item" collection="listItem" open="(" separator="," close=")">
#{item, jdbcType=NVARCHAR}
</foreach>
</foreach>
)
</if>
<if test="subScopeId != null">
and RES.SUB_SCOPE_ID_ = #{subScopeId, jdbcType=NVARCHAR}
</if>
Expand Down

0 comments on commit 7095059

Please sign in to comment.