From 97a241d9586666983da061a742eb3ff01b8fab66 Mon Sep 17 00:00:00 2001 From: Christopher Welsch <75045836+WelschChristopher@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:43:02 +0200 Subject: [PATCH] Add support for OR query filter for PlanItemInstanceQueries (#3922) Co-authored-by: Christopher Welsch --- .../api/runtime/PlanItemInstanceQuery.java | 10 + ...ybatisPlanItemInstanceDataManagerImpl.java | 6 + .../runtime/PlanItemInstanceQueryImpl.java | 569 ++++++++++++-- .../db/mapping/entity/PlanItemInstance.xml | 291 +++++++ .../PlanItemInstanceHistoryServiceTest.java | 20 + .../cmmn/test/runtime/CasePageTaskTest.java | 16 + .../runtime/PlanItemInstanceQueryTest.java | 737 +++++++++++++++++- .../cmmn/test/runtime/RuntimeServiceTest.java | 184 +++++ .../cmmn/test/tenant/MultiTenantTest.java | 4 + ...nceQueryTest.testOrQueryByCompletable.cmmn | 56 ++ ...InstanceQueryTest.testOrQueryByStages.cmmn | 332 ++++++++ ...st.testQueryByDerivedCaseDefinitionId.cmmn | 86 ++ 12 files changed, 2246 insertions(+), 65 deletions(-) create mode 100644 modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testOrQueryByCompletable.cmmn create mode 100644 modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testOrQueryByStages.cmmn create mode 100644 modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testQueryByDerivedCaseDefinitionId.cmmn diff --git a/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/api/runtime/PlanItemInstanceQuery.java b/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/api/runtime/PlanItemInstanceQuery.java index 3b63bb95745..6a2435cbc62 100644 --- a/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/api/runtime/PlanItemInstanceQuery.java +++ b/modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/api/runtime/PlanItemInstanceQuery.java @@ -96,6 +96,16 @@ public interface PlanItemInstanceQuery extends Query planItemDefinitionType); + /** + * Begin an OR statement. Make sure you invoke the endOr method at the end of your OR statement. + */ + PlanItemInstanceQuery or(); + + /** + * End an OR statement. + */ + PlanItemInstanceQuery endOr(); + /** * @return The query will only return ended (completed/terminated/occurred/exited) plan item instances. * No runtime instances will be returned. diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/persistence/entity/data/impl/MybatisPlanItemInstanceDataManagerImpl.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/persistence/entity/data/impl/MybatisPlanItemInstanceDataManagerImpl.java index 07f0d90a309..7e5e7670e32 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/persistence/entity/data/impl/MybatisPlanItemInstanceDataManagerImpl.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/persistence/entity/data/impl/MybatisPlanItemInstanceDataManagerImpl.java @@ -189,5 +189,11 @@ protected void setSafeInValueLists(PlanItemInstanceQueryImpl planItemInstanceQue if (planItemInstanceQuery.getInvolvedGroups() != null) { planItemInstanceQuery.setSafeInvolvedGroups(createSafeInValuesList(planItemInstanceQuery.getInvolvedGroups())); } + + if (planItemInstanceQuery.getOrQueryObjects() != null && !planItemInstanceQuery.getOrQueryObjects().isEmpty()) { + for (PlanItemInstanceQueryImpl oInstanceQuery : planItemInstanceQuery.getOrQueryObjects()) { + setSafeInValueLists(oInstanceQuery); + } + } } } diff --git a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/PlanItemInstanceQueryImpl.java b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/PlanItemInstanceQueryImpl.java index 264eff18936..453935c2f32 100644 --- a/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/PlanItemInstanceQueryImpl.java +++ b/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/PlanItemInstanceQueryImpl.java @@ -12,6 +12,7 @@ */ package org.flowable.cmmn.engine.impl.runtime; +import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; @@ -89,6 +90,10 @@ public class PlanItemInstanceQueryImpl extends AbstractVariableQueryImpl orQueryObjects = new ArrayList<>(); + protected PlanItemInstanceQueryImpl currentOrQueryObject; + protected boolean inOrStatement; + public PlanItemInstanceQueryImpl() { } @@ -108,7 +113,11 @@ public PlanItemInstanceQuery caseDefinitionId(String caseDefinitionId) { if (caseDefinitionId == null) { throw new FlowableIllegalArgumentException("Case definition id is null"); } - this.caseDefinitionId = caseDefinitionId; + if (inOrStatement) { + this.currentOrQueryObject.caseDefinitionId = caseDefinitionId; + } else { + this.caseDefinitionId = caseDefinitionId; + } return this; } @@ -117,7 +126,11 @@ public PlanItemInstanceQuery derivedCaseDefinitionId(String derivedCaseDefinitio if (derivedCaseDefinitionId == null) { throw new FlowableIllegalArgumentException("Derived case definition id is null"); } - this.derivedCaseDefinitionId = derivedCaseDefinitionId; + if (inOrStatement) { + this.currentOrQueryObject.derivedCaseDefinitionId = derivedCaseDefinitionId; + } else { + this.derivedCaseDefinitionId = derivedCaseDefinitionId; + } return this; } @@ -126,7 +139,11 @@ public PlanItemInstanceQuery caseInstanceId(String caseInstanceId) { if (caseInstanceId == null) { throw new FlowableIllegalArgumentException("Case instance id is null"); } - this.caseInstanceId = caseInstanceId; + if (inOrStatement) { + this.currentOrQueryObject.caseInstanceId = caseInstanceId; + } else { + this.caseInstanceId = caseInstanceId; + } return this; } @@ -135,7 +152,11 @@ public PlanItemInstanceQuery stageInstanceId(String stageInstanceId) { if (stageInstanceId == null) { throw new FlowableIllegalArgumentException("Stage instance id is null"); } - this.stageInstanceId = stageInstanceId; + if (inOrStatement) { + this.currentOrQueryObject.stageInstanceId = stageInstanceId; + } else { + this.stageInstanceId = stageInstanceId; + } return this; } @@ -144,7 +165,11 @@ public PlanItemInstanceQuery planItemInstanceId(String planItemInstanceId) { if (planItemInstanceId == null) { throw new FlowableIllegalArgumentException("Plan Item instance id is null"); } - this.planItemInstanceId = planItemInstanceId; + if (inOrStatement) { + this.currentOrQueryObject.planItemInstanceId = planItemInstanceId; + } else { + this.planItemInstanceId = planItemInstanceId; + } return this; } @@ -153,7 +178,11 @@ public PlanItemInstanceQuery planItemInstanceElementId(String elementId) { if (elementId == null) { throw new FlowableIllegalArgumentException("Element id is null"); } - this.elementId = elementId; + if (inOrStatement) { + this.currentOrQueryObject.elementId = elementId; + } else { + this.elementId = elementId; + } return this; } @@ -162,7 +191,11 @@ public PlanItemInstanceQuery planItemDefinitionId(String planItemDefinitionId) { if (planItemDefinitionId == null) { throw new FlowableIllegalArgumentException("Plan item definition id is null"); } - this.planItemDefinitionId = planItemDefinitionId; + if (inOrStatement) { + this.currentOrQueryObject.planItemDefinitionId = planItemDefinitionId; + } else { + this.planItemDefinitionId = planItemDefinitionId; + } return this; } @@ -171,7 +204,11 @@ public PlanItemInstanceQuery planItemDefinitionType(String planItemDefinitionTyp if (planItemDefinitionType == null) { throw new FlowableIllegalArgumentException("Plan item definition type is null"); } - this.planItemDefinitionType = planItemDefinitionType; + if (inOrStatement) { + this.currentOrQueryObject.planItemDefinitionType = planItemDefinitionType; + } else { + this.planItemDefinitionType = planItemDefinitionType; + } return this; } @@ -183,7 +220,11 @@ public PlanItemInstanceQuery planItemDefinitionTypes(List planItemDefini if (planItemDefinitionTypes.isEmpty()) { throw new FlowableIllegalArgumentException("Plan item definition types is empty"); } - this.planItemDefinitionTypes = planItemDefinitionTypes; + if (inOrStatement) { + this.currentOrQueryObject.planItemDefinitionTypes = planItemDefinitionTypes; + } else { + this.planItemDefinitionTypes = planItemDefinitionTypes; + } return this; } @@ -192,7 +233,11 @@ public PlanItemInstanceQuery planItemInstanceName(String name) { if (name == null) { throw new FlowableIllegalArgumentException("Name is null"); } - this.name = name; + if (inOrStatement) { + this.currentOrQueryObject.name = name; + } else { + this.name = name; + } return this; } @@ -201,7 +246,11 @@ public PlanItemInstanceQuery planItemInstanceState(String state) { if (state == null) { throw new FlowableIllegalArgumentException("State is null"); } - this.state = state; + if (inOrStatement) { + this.currentOrQueryObject.state = state; + } else { + this.state = state; + } return this; } @@ -260,7 +309,11 @@ public PlanItemInstanceQuery planItemInstanceCreatedBefore(Date createdBefore) { if (createdBefore == null) { throw new FlowableIllegalArgumentException("createdBefore is null"); } - this.createdBefore = createdBefore; + if (inOrStatement) { + this.currentOrQueryObject.createdBefore = createdBefore; + } else { + this.createdBefore = createdBefore; + } return this; } @@ -269,7 +322,11 @@ public PlanItemInstanceQuery planItemInstanceCreatedAfter(Date createdAfter) { if (createdAfter == null) { throw new FlowableIllegalArgumentException("createdAfter is null"); } - this.createdAfter = createdAfter; + if (inOrStatement) { + this.currentOrQueryObject.createdAfter = createdAfter; + } else { + this.createdAfter = createdAfter; + } return this; } @@ -278,7 +335,11 @@ public PlanItemInstanceQuery planItemInstanceLastAvailableBefore(Date availableB if (availableBefore == null) { throw new FlowableIllegalArgumentException("availableBefore is null"); } - this.lastAvailableBefore = availableBefore; + if (inOrStatement) { + this.currentOrQueryObject.lastAvailableBefore = availableBefore; + } else { + this.lastAvailableBefore = availableBefore; + } return this; } @@ -287,7 +348,11 @@ public PlanItemInstanceQuery planItemInstanceLastAvailableAfter(Date availableAf if (availableAfter == null) { throw new FlowableIllegalArgumentException("availableAfter is null"); } - this.lastAvailableAfter = availableAfter; + if (inOrStatement) { + this.currentOrQueryObject.lastAvailableAfter = availableAfter; + } else { + this.lastAvailableAfter = availableAfter; + } return this; } @@ -296,7 +361,11 @@ public PlanItemInstanceQuery planItemInstanceLastUnavailableBefore(Date unavaila if (unavailableBefore == null) { throw new FlowableIllegalArgumentException("unavailableBefore is null"); } - this.lastUnavailableBefore = unavailableBefore; + if (inOrStatement) { + this.currentOrQueryObject.lastUnavailableBefore = unavailableBefore; + } else { + this.lastUnavailableBefore = unavailableBefore; + } return this; } @@ -305,7 +374,11 @@ public PlanItemInstanceQuery planItemInstanceLastUnavailableAfter(Date unavailab if (unavailableAfter == null) { throw new FlowableIllegalArgumentException("unavailableAfter is null"); } - this.lastUnavailableAfter = unavailableAfter; + if (inOrStatement) { + this.currentOrQueryObject.lastUnavailableAfter = unavailableAfter; + } else { + this.lastUnavailableAfter = unavailableAfter; + } return this; } @@ -314,7 +387,11 @@ public PlanItemInstanceQuery planItemInstanceLastEnabledBefore(Date enabledBefor if (enabledBefore == null) { throw new FlowableIllegalArgumentException("enabledBefore is null"); } - this.lastEnabledBefore = enabledBefore; + if (inOrStatement) { + this.currentOrQueryObject.lastEnabledBefore = enabledBefore; + } else { + this.lastEnabledBefore = enabledBefore; + } return this; } @@ -323,7 +400,11 @@ public PlanItemInstanceQuery planItemInstanceLastEnabledAfter(Date enabledAfter) if (enabledAfter == null) { throw new FlowableIllegalArgumentException("enabledAfter is null"); } - this.lastEnabledAfter = enabledAfter; + if (inOrStatement) { + this.currentOrQueryObject.lastEnabledAfter = enabledAfter; + } else { + this.lastEnabledAfter = enabledAfter; + } return this; } @@ -332,7 +413,11 @@ public PlanItemInstanceQuery planItemInstanceLastDisabledBefore(Date disabledBef if (disabledBefore == null) { throw new FlowableIllegalArgumentException("disabledBefore is null"); } - this.lastDisabledBefore = disabledBefore; + if (inOrStatement) { + this.currentOrQueryObject.lastDisabledBefore = disabledBefore; + } else { + this.lastDisabledBefore = disabledBefore; + } return this; } @@ -341,7 +426,11 @@ public PlanItemInstanceQuery planItemInstanceLastDisabledAfter(Date disabledAfte if (disabledAfter == null) { throw new FlowableIllegalArgumentException("disabledAfter is null"); } - this.lastDisabledAfter = disabledAfter; + if (inOrStatement) { + this.currentOrQueryObject.lastDisabledAfter = disabledAfter; + } else { + this.lastDisabledAfter = disabledAfter; + } return this; } @@ -350,7 +439,11 @@ public PlanItemInstanceQuery planItemInstanceLastStartedBefore(Date startedBefor if (startedBefore == null) { throw new FlowableIllegalArgumentException("activatedBefore is null"); } - this.lastStartedBefore = startedBefore; + if (inOrStatement) { + this.currentOrQueryObject.lastStartedBefore = startedBefore; + } else { + this.lastStartedBefore = startedBefore; + } return this; } @@ -359,7 +452,11 @@ public PlanItemInstanceQuery planItemInstanceLastStartedAfter(Date startedAfter) if (startedAfter == null) { throw new FlowableIllegalArgumentException("startedAfter is null"); } - this.lastStartedAfter = startedAfter; + if (inOrStatement) { + this.currentOrQueryObject.lastStartedAfter = startedAfter; + } else { + this.lastStartedAfter = startedAfter; + } return this; } @@ -368,7 +465,11 @@ public PlanItemInstanceQuery planItemInstanceLastSuspendedBefore(Date suspendedB if (suspendedBefore == null) { throw new FlowableIllegalArgumentException("suspendedBefore is null"); } - this.lastSuspendedBefore = suspendedBefore; + if (inOrStatement) { + this.currentOrQueryObject.lastSuspendedBefore = suspendedBefore; + } else { + this.lastSuspendedBefore = suspendedBefore; + } return this; } @@ -377,7 +478,11 @@ public PlanItemInstanceQuery planItemInstanceLastSuspendedAfter(Date suspendedAf if (suspendedAfter == null) { throw new FlowableIllegalArgumentException("suspendedAfter is null"); } - this.lastSuspendedAfter = suspendedAfter; + if (inOrStatement) { + this.currentOrQueryObject.lastSuspendedAfter = suspendedAfter; + } else { + this.lastSuspendedAfter = suspendedAfter; + } return this; } @@ -386,7 +491,11 @@ public PlanItemInstanceQuery planItemInstanceCompletedBefore(Date completedBefor if (completedBefore == null) { throw new FlowableIllegalArgumentException("completedBefore is null"); } - this.completedBefore = completedBefore; + if (inOrStatement) { + this.currentOrQueryObject.completedBefore = completedBefore; + } else { + this.completedBefore = completedBefore; + } return this; } @@ -395,7 +504,11 @@ public PlanItemInstanceQuery planItemInstanceCompletedAfter(Date completedAfter) if (completedAfter == null) { throw new FlowableIllegalArgumentException("completedAfter is null"); } - this.completedAfter = completedAfter; + if (inOrStatement) { + this.currentOrQueryObject.completedAfter = completedAfter; + } else { + this.completedAfter = completedAfter; + } return this; } @@ -404,7 +517,11 @@ public PlanItemInstanceQuery planItemInstanceOccurredBefore(Date occurredBefore) if (occurredBefore == null) { throw new FlowableIllegalArgumentException("occurredBefore is null"); } - this.occurredBefore = occurredBefore; + if (inOrStatement) { + this.currentOrQueryObject.occurredBefore = occurredBefore; + } else { + this.occurredBefore = occurredBefore; + } return this; } @@ -413,7 +530,11 @@ public PlanItemInstanceQuery planItemInstanceOccurredAfter(Date occurredAfter) { if (occurredAfter == null) { throw new FlowableIllegalArgumentException("occurredAfter is null"); } - this.occurredAfter = occurredAfter; + if (inOrStatement) { + this.currentOrQueryObject.occurredAfter = occurredAfter; + } else { + this.occurredAfter = occurredAfter; + } return this; } @@ -422,7 +543,11 @@ public PlanItemInstanceQuery planItemInstanceTerminatedBefore(Date terminatedBef if (terminatedBefore == null) { throw new FlowableIllegalArgumentException("terminatedBefore is null"); } - this.terminatedBefore = terminatedBefore; + if (inOrStatement) { + this.currentOrQueryObject.terminatedBefore = terminatedBefore; + } else { + this.terminatedBefore = terminatedBefore; + } return this; } @@ -431,7 +556,11 @@ public PlanItemInstanceQuery planItemInstanceTerminatedAfter(Date terminatedAfte if (terminatedAfter == null) { throw new FlowableIllegalArgumentException("terminatedAfter is null"); } - this.terminatedAfter = terminatedAfter; + if (inOrStatement) { + this.currentOrQueryObject.terminatedAfter = terminatedAfter; + } else { + this.terminatedAfter = terminatedAfter; + } return this; } @@ -440,7 +569,11 @@ public PlanItemInstanceQuery planItemInstanceExitBefore(Date exitBefore) { if (exitBefore == null) { throw new FlowableIllegalArgumentException("exitBefore is null"); } - this.exitBefore = exitBefore; + if (inOrStatement) { + this.currentOrQueryObject.exitBefore = exitBefore; + } else { + this.exitBefore = exitBefore; + } return this; } @@ -449,7 +582,11 @@ public PlanItemInstanceQuery planItemInstanceExitAfter(Date exitAfter) { if (exitAfter == null) { throw new FlowableIllegalArgumentException("exitAfter is null"); } - this.exitAfter = exitAfter; + if (inOrStatement) { + this.currentOrQueryObject.exitAfter = exitAfter; + } else { + this.exitAfter = exitAfter; + } return this; } @@ -458,27 +595,45 @@ public PlanItemInstanceQuery planItemInstanceEndedBefore(Date endedBefore) { if (endedBefore == null) { throw new FlowableIllegalArgumentException("endedBefore is null"); } - this.endedBefore = endedBefore; + if (inOrStatement) { + this.currentOrQueryObject.endedBefore = endedBefore; + } else { + this.endedBefore = endedBefore; + } return this; } + @Override public PlanItemInstanceQuery planItemInstanceEndedAfter(Date endedAfter) { if (endedAfter == null) { throw new FlowableIllegalArgumentException("endedAfter is null"); } - this.endedAfter = endedAfter; + if (inOrStatement) { + this.currentOrQueryObject.endedAfter = endedAfter; + } else { + this.endedAfter = endedAfter; + } return this; } @Override public PlanItemInstanceQuery ended() { - this.ended = true; + if (inOrStatement) { + this.currentOrQueryObject.ended = true; + includeEnded = true; + } else { + this.ended = true; + } return this; } @Override public PlanItemInstanceQuery includeEnded() { - this.includeEnded = true; + if (inOrStatement) { + throw new FlowableIllegalArgumentException("includeEnded is not allowed within an or query"); + } else { + this.includeEnded = true; + } return this; } @@ -487,31 +642,51 @@ public PlanItemInstanceQuery planItemInstanceStartUserId(String startUserId) { if (startUserId == null) { throw new FlowableIllegalArgumentException("Start user id is null"); } - this.startUserId = startUserId; + if (inOrStatement) { + this.currentOrQueryObject.startUserId = startUserId; + } else { + this.startUserId = startUserId; + } return this; } @Override public PlanItemInstanceQuery planItemInstanceReferenceId(String referenceId) { - this.referenceId = referenceId; + if (inOrStatement) { + this.currentOrQueryObject.referenceId = referenceId; + } else { + this.referenceId = referenceId; + } return this; } @Override public PlanItemInstanceQuery planItemInstanceReferenceType(String referenceType) { - this.referenceType = referenceType; + if (inOrStatement) { + this.currentOrQueryObject.referenceType = referenceType; + } else { + this.referenceType = referenceType; + } return this; } @Override public PlanItemInstanceQuery planItemInstanceCompletable() { - this.completable = true; + if (inOrStatement) { + this.currentOrQueryObject.completable = true; + } else { + this.completable = true; + } return this; } @Override public PlanItemInstanceQuery onlyStages() { - this.onlyStages = true; + if (inOrStatement) { + this.currentOrQueryObject.onlyStages = true; + } else { + this.onlyStages = true; + } return this; } @@ -520,7 +695,11 @@ public PlanItemInstanceQuery planItemInstanceEntryCriterionId(String entryCriter if (entryCriterionId == null) { throw new FlowableIllegalArgumentException("EntryCriterionId is null"); } - this.entryCriterionId = entryCriterionId; + if (inOrStatement) { + this.currentOrQueryObject.entryCriterionId = entryCriterionId; + } else { + this.entryCriterionId = entryCriterionId; + } return this; } @@ -529,7 +708,11 @@ public PlanItemInstanceQuery planItemInstanceExitCriterionId(String exitCriterio if (exitCriterionId == null) { throw new FlowableIllegalArgumentException("ExitCriterionId is null"); } - this.exitCriterionId = exitCriterionId; + if (inOrStatement) { + this.currentOrQueryObject.exitCriterionId = exitCriterionId; + } else { + this.exitCriterionId = exitCriterionId; + } return this; } @@ -538,7 +721,11 @@ public PlanItemInstanceQuery planItemInstanceFormKey(String formKey) { if (formKey == null) { throw new FlowableIllegalArgumentException("formKey is null"); } - this.formKey = formKey; + if (inOrStatement) { + this.currentOrQueryObject.formKey = formKey; + } else { + this.formKey = formKey; + } return this; } @@ -547,7 +734,11 @@ public PlanItemInstanceQuery planItemInstanceExtraValue(String extraValue) { if (extraValue == null) { throw new FlowableIllegalArgumentException("extraValue is null"); } - this.extraValue = extraValue; + if (inOrStatement) { + this.currentOrQueryObject.extraValue = extraValue; + } else { + this.extraValue = extraValue; + } return this; } @@ -556,7 +747,11 @@ public PlanItemInstanceQuery involvedUser(String involvedUser) { if (involvedUser == null) { throw new FlowableIllegalArgumentException("involvedUser is null"); } - this.involvedUser = involvedUser; + if (inOrStatement) { + this.currentOrQueryObject.involvedUser = involvedUser; + } else { + this.involvedUser = involvedUser; + } return this; } @@ -565,7 +760,11 @@ public PlanItemInstanceQuery involvedGroups(Collection involvedGroups) { if (involvedGroups == null) { throw new FlowableIllegalArgumentException("involvedGroups is null"); } - this.involvedGroups = involvedGroups; + if (inOrStatement) { + this.currentOrQueryObject.involvedGroups = involvedGroups; + } else { + this.involvedGroups = involvedGroups; + } return this; } @@ -574,79 +773,309 @@ public PlanItemInstanceQuery planItemInstanceTenantId(String tenantId) { if (tenantId == null) { throw new FlowableIllegalArgumentException("Tenant id is null"); } - this.tenantId = tenantId; + if (inOrStatement) { + this.currentOrQueryObject.tenantId = tenantId; + } else { + this.tenantId = tenantId; + } return this; } @Override public PlanItemInstanceQuery planItemInstanceWithoutTenantId() { - this.withoutTenantId = true; + if (inOrStatement) { + this.currentOrQueryObject.withoutTenantId = true; + } else { + this.withoutTenantId = true; + } return this; } - + + @Override + public PlanItemInstanceQuery variableValueEquals(String name, Object value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueEquals(name, value); + } else { + super.variableValueEquals(name, value); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableValueEquals(Object value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueEquals(value); + } else { + super.variableValueEquals(value); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableValueEqualsIgnoreCase(String name, String value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueEqualsIgnoreCase(name, value); + } else { + super.variableValueEqualsIgnoreCase(name, value); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableValueNotEqualsIgnoreCase(String name, String value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueNotEqualsIgnoreCase(name, value); + } else { + super.variableValueNotEqualsIgnoreCase(name, value); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableValueNotEquals(String name, Object value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueNotEquals(name, value); + } else { + super.variableValueNotEquals(name, value); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableValueLikeIgnoreCase(String name, String value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueLikeIgnoreCase(name, value); + } else { + super.variableValueLikeIgnoreCase(name, value); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableValueLike(String name, String value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueLike(name, value); + } else { + super.variableValueLike(name, value); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableValueLessThanOrEqual(String name, Object value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueLessThanOrEqual(name, value); + } else { + super.variableValueLessThanOrEqual(name, value); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableValueLessThan(String name, Object value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueLessThan(name, value); + } else { + super.variableValueLessThan(name, value); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableValueGreaterThanOrEqual(String name, Object value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueGreaterThanOrEqual(name, value); + } else { + + super.variableValueGreaterThanOrEqual(name, value); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableValueGreaterThan(String name, Object value) { + if (inOrStatement) { + this.currentOrQueryObject.variableValueGreaterThan(name, value); + } else { + super.variableValueGreaterThan(name, value); + } + return this; + } + @Override + public PlanItemInstanceQuery variableExists(String name) { + if (inOrStatement) { + this.currentOrQueryObject.variableExists(name); + } else { + super.variableExists(name); + } + return this; + } + + @Override + public PlanItemInstanceQuery variableNotExists(String name) { + if (inOrStatement) { + this.currentOrQueryObject.variableNotExists(name); + } else { + super.variableNotExists(name); + } + return this; + } + @Override public PlanItemInstanceQuery caseVariableValueEquals(String name, Object value) { - return variableValueEquals(name, value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueEquals(name, value, false); + } else { + variableValueEquals(name, value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableValueEquals(Object value) { - return variableValueEquals(value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueEquals(value, false); + } else { + variableValueEquals(value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableValueEqualsIgnoreCase(String name, String value) { - return variableValueEqualsIgnoreCase(name, value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueEqualsIgnoreCase(name, value, false); + } else { + variableValueEqualsIgnoreCase(name, value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableValueNotEquals(String name, Object value) { - return variableValueNotEquals(name, value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueNotEquals(name, value, false); + } else { + variableValueNotEquals(name, value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableValueNotEqualsIgnoreCase(String name, String value) { - return variableValueNotEqualsIgnoreCase(name, value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueNotEqualsIgnoreCase(name, value, false); + } else { + variableValueNotEqualsIgnoreCase(name, value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableValueGreaterThan(String name, Object value) { - return variableValueGreaterThan(name, value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueGreaterThan(name, value, false); + } else { + variableValueGreaterThan(name, value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableValueGreaterThanOrEqual(String name, Object value) { - return variableValueGreaterThanOrEqual(name, value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueGreaterThanOrEqual(name, value, false); + } else { + variableValueGreaterThanOrEqual(name, value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableValueLessThan(String name, Object value) { - return variableValueLessThan(name, value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueLessThan(name, value, false); + } else { + variableValueLessThan(name, value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableValueLessThanOrEqual(String name, Object value) { - return variableValueLessThanOrEqual(name, value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueLessThanOrEqual(name, value, false); + } else { + variableValueLessThanOrEqual(name, value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableValueLike(String name, String value) { - return variableValueLike(name, value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueLike(name, value, false); + } else { + variableValueLike(name, value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableValueLikeIgnoreCase(String name, String value) { - return variableValueLikeIgnoreCase(name, value, false); + if (inOrStatement) { + this.currentOrQueryObject.variableValueLikeIgnoreCase(name, value, false); + } else { + variableValueLikeIgnoreCase(name, value, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableExists(String name) { - return variableExists(name, false); + if (inOrStatement) { + this.currentOrQueryObject.variableExists(name, false); + } else { + variableExists(name, false); + } + return this; } @Override public PlanItemInstanceQuery caseVariableNotExists(String name) { - return variableNotExists(name, false); + if (inOrStatement) { + this.currentOrQueryObject.variableNotExists(name, false); + } else { + variableNotExists(name, false); + } + return this; + } + + @Override + public PlanItemInstanceQuery or() { + if (inOrStatement) { + throw new FlowableIllegalArgumentException("The query is already in an or statement"); + } + + inOrStatement = true; + if (commandContext != null) { + currentOrQueryObject = new PlanItemInstanceQueryImpl(commandContext, cmmnEngineConfiguration); + } else { + currentOrQueryObject = new PlanItemInstanceQueryImpl(commandExecutor, cmmnEngineConfiguration); + } + orQueryObjects.add(currentOrQueryObject); + return this; + } + + @Override + public PlanItemInstanceQuery endOr() { + if (!inOrStatement) { + throw new FlowableIllegalArgumentException("endOr() can only be called after calling or()"); + } + + inOrStatement = false; + currentOrQueryObject = null; + return this; } @Override @@ -861,4 +1290,16 @@ public List> getSafeInvolvedGroups() { public void setSafeInvolvedGroups(List> safeInvolvedGroups) { this.safeInvolvedGroups = safeInvolvedGroups; } + + @Override + protected void ensureVariablesInitialized() { + super.ensureVariablesInitialized(); + for (PlanItemInstanceQueryImpl orQueryObject : orQueryObjects) { + orQueryObject.ensureVariablesInitialized(); + } + } + + public List getOrQueryObjects() { + return orQueryObjects; + } } diff --git a/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/PlanItemInstance.xml b/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/PlanItemInstance.xml index 7f6fe30d612..276c6264fad 100644 --- a/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/PlanItemInstance.xml +++ b/modules/flowable-cmmn-engine/src/main/resources/org/flowable/cmmn/db/mapping/entity/PlanItemInstance.xml @@ -634,6 +634,297 @@ + + and + + + or RES.CASE_DEF_ID_ = #{orQueryObject.caseDefinitionId, jdbcType=VARCHAR} + + + or RES.DERIVED_CASE_DEF_ID_ = #{orQueryObject.derivedCaseDefinitionId, jdbcType=VARCHAR} + + + or RES.CASE_INST_ID_ = #{orQueryObject.caseInstanceId, jdbcType=VARCHAR} + + + or RES.STAGE_INST_ID_ = #{orQueryObject.stageInstanceId, jdbcType=VARCHAR} + + + or RES.ID_ = #{orQueryObject.planItemInstanceId, jdbcType=VARCHAR} + + + or RES.ELEMENT_ID_ = #{orQueryObject.elementId, jdbcType=VARCHAR} + + + or RES.ITEM_DEFINITION_ID_ = #{orQueryObject.planItemDefinitionId, jdbcType=VARCHAR} + + + or RES.ITEM_DEFINITION_TYPE_ = #{orQueryObject.planItemDefinitionType, jdbcType=VARCHAR} + + + or RES.ITEM_DEFINITION_TYPE_ in + + #{planItemDefinitionType, jdbcType=VARCHAR} + + + + or RES.NAME_ = #{orQueryObject.name, jdbcType=NVARCHAR} + + + or RES.STATE_ = #{orQueryObject.state, jdbcType=VARCHAR} + + + or RES.CREATE_TIME_ <= #{orQueryObject.createdBefore, jdbcType=TIMESTAMP} + + + or RES.CREATE_TIME_ >= #{orQueryObject.createdAfter, jdbcType=TIMESTAMP} + + + or RES.LAST_AVAILABLE_TIME_ <= #{orQueryObject.lastAvailableBefore, jdbcType=TIMESTAMP} + + + or RES.LAST_AVAILABLE_TIME_ >= #{orQueryObject.lastAvailableAfter, jdbcType=TIMESTAMP} + + + or RES.LAST_UNAVAILABLE_TIME_ <= #{orQueryObject.lastUnavailableBefore, jdbcType=TIMESTAMP} + + + or RES.LAST_UNAVAILABLE_TIME_ >= #{orQueryObject.lastUnavailableAfter, jdbcType=TIMESTAMP} + + + or RES.LAST_ENABLED_TIME_ <= #{orQueryObject.lastEnabledBefore, jdbcType=TIMESTAMP} + + + or RES.LAST_ENABLED_TIME_ >= #{orQueryObject.lastEnabledAfter, jdbcType=TIMESTAMP} + + + or RES.LAST_DISABLED_TIME_ <= #{orQueryObject.lastDisabledBefore, jdbcType=TIMESTAMP} + + + or RES.LAST_DISABLED_TIME_ >= #{orQueryObject.lastDisabledAfter, jdbcType=TIMESTAMP} + + + or RES.LAST_STARTED_TIME_ <= #{orQueryObject.lastStartedBefore, jdbcType=TIMESTAMP} + + + or RES.LAST_STARTED_TIME_ >= #{orQueryObject.lastStartedAfter, jdbcType=TIMESTAMP} + + + or RES.LAST_SUSPENDED_TIME_ <= #{orQueryObject.lastSuspendedBefore, jdbcType=TIMESTAMP} + + + or RES.LAST_SUSPENDED_TIME_ >= #{orQueryObject.lastSuspendedAfter, jdbcType=TIMESTAMP} + + + or RES.COMPLETED_TIME_ <= #{orQueryObject.completedBefore, jdbcType=TIMESTAMP} + + + or RES.COMPLETED_TIME_ >= #{orQueryObject.completedAfter, jdbcType=TIMESTAMP} + + + or RES.OCCURRED_TIME_ <= #{orQueryObject.occurredBefore, jdbcType=TIMESTAMP} + + + or RES.OCCURRED_TIME_ >= #{orQueryObject.occurredAfter, jdbcType=TIMESTAMP} + + + or RES.TERMINATED_TIME_ <= #{orQueryObject.terminatedBefore, jdbcType=TIMESTAMP} + + + or RES.TERMINATED_TIME_ >= #{orQueryObject.terminatedAfter, jdbcType=TIMESTAMP} + + + or RES.EXIT_TIME_ <= #{orQueryObject.exitBefore, jdbcType=TIMESTAMP} + + + or RES.EXIT_TIME_ >= #{orQueryObject.exitAfter, jdbcType=TIMESTAMP} + + + or RES.ENDED_TIME_ <= #{orQueryObject.endedBefore, jdbcType=TIMESTAMP} + + + or RES.ENDED_TIME_ >= #{orQueryObject.endedAfter, jdbcType=TIMESTAMP} + + + or RES.ENDED_TIME_ is not null + + + or RES.START_USER_ID_ = #{orQueryObject.startUserId, jdbcType=VARCHAR} + + + or RES.REFERENCE_ID_ = #{orQueryObject.referenceId, jdbcType=VARCHAR} + + + or RES.REFERENCE_TYPE_ = #{orQueryObject.referenceType, jdbcType=VARCHAR} + + + or RES.IS_COMPLETEABLE_ = #{orQueryObject.completable, jdbcType=BOOLEAN} + + + or RES.ENTRY_CRITERION_ID_ = #{orQueryObject.entryCriterionId, jdbcType=VARCHAR} + + + or RES.EXIT_CRITERION_ID_ = #{orQueryObject.exitCriterionId, jdbcType=VARCHAR} + + + or RES.EXTRA_VALUE_ = #{orQueryObject.formKey, jdbcType=VARCHAR} + + + or RES.EXTRA_VALUE_ = #{orQueryObject.extraValue, jdbcType=VARCHAR} + + + or RES.TENANT_ID_ = #{orQueryObject.tenantId, jdbcType=VARCHAR} + + + or (RES.TENANT_ID_ is null or RES.TENANT_ID_ = '') + + + or RES.IS_STAGE_ = #{orQueryObject.onlyStages, jdbcType=BOOLEAN} + + + or exists(select I.ID_ from ${prefix}ACT_RU_IDENTITYLINK I where I.SUB_SCOPE_ID_ = RES.ID_ and I.SCOPE_TYPE_ = 'planItem' + and + ( + + I.USER_ID_ = #{orQueryObject.involvedUser, jdbcType=NVARCHAR} + + + or + + + ( + + + or + + I.GROUP_ID_ IN + + #{involvedGroup, jdbcType=NVARCHAR} + + + ) + + ) + ) + + + or + + + + and EXISTS ( + select ID_ from ${prefix}ACT_RU_VARIABLE where NAME_ = #{queryVariableValue.name, jdbcType=NVARCHAR} + + and RES.CASE_INST_ID_ = SCOPE_ID_ and SUB_SCOPE_ID_ is null and SCOPE_TYPE_ = 'cmmn' + + + and RES.ID_ = SUB_SCOPE_ID_ and SCOPE_TYPE_ = 'cmmn' + + ) + + + and NOT EXISTS ( + select ID_ from ${prefix}ACT_RU_VARIABLE where NAME_ = #{queryVariableValue.name, jdbcType=NVARCHAR} + + and RES.CASE_INST_ID_ = SCOPE_ID_ and SUB_SCOPE_ID_ is null and SCOPE_TYPE_ = 'cmmn' + + + and RES.ID_ = SUB_SCOPE_ID_ and SCOPE_TYPE_ = 'cmmn' + + ) + + + and exists ( + select 1 + from ${prefix}ACT_RU_VARIABLE V + + + and RES.ID_ = V.SUB_SCOPE_ID_ + and V.SCOPE_TYPE_ = 'cmmn' + + + and RES.CASE_INST_ID_ = V.SCOPE_ID_ + and V.SUB_SCOPE_ID_ is null + and V.SCOPE_TYPE_ = 'cmmn' + + + + and V.NAME_= #{queryVariableValue.name, jdbcType=NVARCHAR} + + + and V.TYPE_ = #{queryVariableValue.type, jdbcType=NVARCHAR} + + + + + and (lower(V.TEXT_) + + + and (V.TEXT_ + + + + LIKE + + + #{queryVariableValue.textValue, jdbcType=NVARCHAR} + + ${wildcardEscapeClause} + + + or V.TEXT_ is null + + ) + + + and V.TEXT2_ + + LIKE + + + #{queryVariableValue.textValue2, jdbcType=NVARCHAR} + + ${wildcardEscapeClause} + + + + and (V.LONG_ + + #{queryVariableValue.longValue, jdbcType=BIGINT} + + or V.LONG_ is null + + ) + + + and (V.DOUBLE_ + + #{queryVariableValue.doubleValue, jdbcType=DOUBLE} + + or V.DOUBLE_ is null + + ) + + + + + + and (V.TEXT_ is not null or V.TEXT2_ is not null or V.LONG_ is not null or V.DOUBLE_ is not null or V.BYTEARRAY_ID_ is not null) + + + and V.TEXT_ is null and V.TEXT2_ is null and V.LONG_ is null and V.DOUBLE_ is null and V.BYTEARRAY_ID_ is null + + + + + ) + + + + + + diff --git a/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/history/PlanItemInstanceHistoryServiceTest.java b/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/history/PlanItemInstanceHistoryServiceTest.java index a9fccdd414c..a99e7adf00f 100644 --- a/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/history/PlanItemInstanceHistoryServiceTest.java +++ b/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/history/PlanItemInstanceHistoryServiceTest.java @@ -568,6 +568,11 @@ public void testQueryByUnavailableState() { List planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastUnavailableAfter(startTime).list(); assertThat(planItemInstances).extracting(PlanItemInstance::getName).containsExactly("myEventListener"); + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastUnavailableAfter(startTime).endOr() + .list(); + assertThat(planItemInstances).extracting(PlanItemInstance::getName).containsExactly("myEventListener"); + if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) { List historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery().lastUnavailableAfter(startTime).list(); assertThat(historicPlanItemInstances).extracting(HistoricPlanItemInstance::getName).containsExactly("myEventListener"); @@ -576,6 +581,11 @@ public void testQueryByUnavailableState() { planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastUnavailableAfter(afterStartTime).list(); assertThat(planItemInstances).extracting(PlanItemInstance::getName).isEmpty(); + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastUnavailableAfter(afterStartTime).endOr() + .list(); + assertThat(planItemInstances).extracting(PlanItemInstance::getName).isEmpty(); + if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) { List historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery().lastUnavailableAfter(afterStartTime).list(); assertThat(historicPlanItemInstances).extracting(HistoricPlanItemInstance::getName).isEmpty(); @@ -585,6 +595,11 @@ public void testQueryByUnavailableState() { planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastUnavailableBefore(afterStartTime).list(); assertThat(planItemInstances).extracting(PlanItemInstance::getName).containsExactly("myEventListener"); + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastUnavailableBefore(afterStartTime).endOr() + .list(); + assertThat(planItemInstances).extracting(PlanItemInstance::getName).containsExactly("myEventListener"); + if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) { List historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery().lastUnavailableBefore(afterStartTime).list(); assertThat(historicPlanItemInstances).extracting(HistoricPlanItemInstance::getName).containsExactly("myEventListener"); @@ -594,6 +609,11 @@ public void testQueryByUnavailableState() { planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastUnavailableBefore(beforeStartTime).list(); assertThat(planItemInstances).extracting(PlanItemInstance::getName).isEmpty(); + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastUnavailableBefore(beforeStartTime).endOr() + .list(); + assertThat(planItemInstances).extracting(PlanItemInstance::getName).isEmpty(); + if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) { List historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery().lastUnavailableBefore(beforeStartTime).list(); assertThat(historicPlanItemInstances).extracting(HistoricPlanItemInstance::getName).isEmpty(); diff --git a/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/CasePageTaskTest.java b/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/CasePageTaskTest.java index 46f03e0e1a2..21a123b7ae8 100644 --- a/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/CasePageTaskTest.java +++ b/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/CasePageTaskTest.java @@ -81,6 +81,14 @@ public void testInStage() { .singleResult(); assertThat(pagePlanItemInstance).isNotNull(); + pagePlanItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseInstanceId(caseInstance.getId()).endOr() + .or().caseInstanceId("undefinedId").planItemDefinitionId("casePageTask1").endOr() + .or().caseInstanceId("undefinedId").planItemInstanceFormKey("myFormKeyValue").endOr() + .includeEnded() + .singleResult(); + assertThat(pagePlanItemInstance).isNotNull(); + // page tasks go into terminated or completed state, depending on the parent ending type like complete or exit assertThat(pagePlanItemInstance.getState()).isEqualTo(PlanItemInstanceState.COMPLETED); assertThat(pagePlanItemInstance.getFormKey()).isEqualTo("myFormKeyValue"); @@ -178,6 +186,10 @@ public void testIdentityLinks() { planItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery().involvedUser("janedoe").singleResult(); assertThat(planItemInstance.getName()).isEqualTo("Case Page Task One"); + planItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").involvedUser("janedoe").endOr().singleResult(); + assertThat(planItemInstance.getName()).isEqualTo("Case Page Task One"); + planItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery().involvedUser("johndoe2").singleResult(); assertThat(planItemInstance).isNull(); @@ -185,6 +197,10 @@ public void testIdentityLinks() { planItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery().involvedGroups(groups).singleResult(); assertThat(planItemInstance.getName()).isEqualTo("Case Page Task One"); + planItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").involvedGroups(groups).endOr().singleResult(); + assertThat(planItemInstance.getName()).isEqualTo("Case Page Task One"); + planItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery().involvedUser("johndoe").involvedGroups(groups).singleResult(); assertThat(planItemInstance.getName()).isEqualTo("Case Page Task One"); diff --git a/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.java b/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.java index b1ac4ec847e..c3a524da287 100644 --- a/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.java +++ b/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.java @@ -13,7 +13,10 @@ package org.flowable.cmmn.test.runtime; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.tuple; +import static org.flowable.cmmn.api.runtime.PlanItemInstanceState.ACTIVE; +import static org.flowable.cmmn.api.runtime.PlanItemInstanceState.AVAILABLE; import java.util.ArrayList; import java.util.Arrays; @@ -29,6 +32,7 @@ import org.flowable.cmmn.engine.PlanItemLocalizationManager; import org.flowable.cmmn.engine.test.CmmnDeployment; import org.flowable.cmmn.engine.test.FlowableCmmnTestCase; +import org.flowable.common.engine.api.FlowableIllegalArgumentException; import org.flowable.task.api.Task; import org.junit.Before; import org.junit.Test; @@ -47,14 +51,22 @@ public void deployCaseDefinition() { .deploy()); caseDefinitionId = cmmnRepositoryService.createCaseDefinitionQuery() .deploymentId(deploymentId) + .caseDefinitionKey("testPlanItemInstanceQuery") .singleResult() .getId(); } @Test + @CmmnDeployment(resources = "org/flowable/cmmn/test/runtime/oneHumanTaskCase.cmmn") public void testByCaseDefinitionId() { startInstances(5); - assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().list()).hasSize(20); + cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("oneHumanTaskCase").start(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseDefinitionId(caseDefinitionId).list()).hasSize(20); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseDefinitionId(caseDefinitionId).endOr() + .list()).hasSize(20); + } @Test @@ -62,6 +74,9 @@ public void testByCaseInstanceId() { List caseInstanceIds = startInstances(3); for (String caseInstanceId : caseInstanceIds) { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseInstanceId(caseInstanceId).list()).hasSize(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseDefinitionId("undefinedId").caseInstanceId(caseInstanceId).endOr() + .list()).hasSize(4); } } @@ -73,6 +88,10 @@ public void testByStageInstanceId() { .planItemInstanceName("Stage one") .singleResult(); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().stageInstanceId(planItemInstance.getId()).count()).isEqualTo(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").stageInstanceId(planItemInstance.getId()).endOr() + .count()).isEqualTo(2); + } @Test @@ -81,6 +100,9 @@ public void testByPlanItemInstanceId() { List planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery().list(); for (PlanItemInstance planItemInstance : planItemInstances) { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(planItemInstance.getId()).count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceId(planItemInstance.getId()).endOr() + .count()).isEqualTo(1); } } @@ -88,12 +110,20 @@ public void testByPlanItemInstanceId() { public void testByElementId() { startInstances(4); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceElementId("planItem3").list()).hasSize(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceElementId("planItem3").endOr() + .list()).hasSize(4); + } @Test public void testByName() { startInstances(9); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceName("B").list()).hasSize(9); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceName("B").endOr() + .list()).hasSize(9); + } @Test @@ -107,6 +137,27 @@ public void testByState() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceState(PlanItemInstanceState.ENABLED).list()).hasSize(1); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceStateEnabled().list()).hasSize(1); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceState(PlanItemInstanceState.ACTIVE).endOr() + .list()).hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceStateActive().endOr() + .list()).hasSize(2); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceState(PlanItemInstanceState.AVAILABLE).endOr() + .list()).hasSize(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceStateAvailable().endOr() + .list()).hasSize(1); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceState(PlanItemInstanceState.ENABLED).endOr() + .list()).hasSize(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceStateEnabled().endOr() + .list()).hasSize(1); } @Test @@ -114,6 +165,13 @@ public void testByPlanItemDefinitionType() { startInstances(3); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK).list()).hasSize(6); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemDefinitionType(PlanItemDefinitionType.STAGE).list()).hasSize(6); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK).endOr() + .list()).hasSize(6); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemDefinitionType(PlanItemDefinitionType.STAGE).endOr() + .list()).hasSize(6); } @Test @@ -121,6 +179,11 @@ public void testByPlanItemDefinitionTypes() { startInstances(2); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() .planItemDefinitionTypes(Arrays.asList(PlanItemDefinitionType.STAGE, PlanItemDefinitionType.HUMAN_TASK)).list()).hasSize(8); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemDefinitionTypes(Arrays.asList(PlanItemDefinitionType.STAGE, PlanItemDefinitionType.HUMAN_TASK)) + .endOr() + .list()).hasSize(8); } @Test @@ -133,6 +196,16 @@ public void testByStateEnabled() { .hasSize(4) .extracting(PlanItemInstance::getName) .containsOnly("B"); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceStateEnabled().endOr() + .list(); + + assertThat(planItemInstances) + .hasSize(4) + .extracting(PlanItemInstance::getName) + .containsOnly("B"); + } @Test @@ -148,6 +221,11 @@ public void testByStateDisabled() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceStateDisabled().list()) .hasSize(2) .extracting(PlanItemInstance::getName).containsOnly("B"); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceStateDisabled().endOr() + .list()).hasSize(2) + .extracting(PlanItemInstance::getName).containsOnly("B"); } @Test @@ -163,6 +241,16 @@ public void testByStateAvailable() { .hasSize(3) .extracting(PlanItemInstance::getName) .containsOnly("Stage two"); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceStateAvailable().endOr() + .orderByName().asc() + .list(); + + assertThat(planItemInstances) + .hasSize(3) + .extracting(PlanItemInstance::getName) + .containsOnly("Stage two"); } @Test @@ -178,6 +266,16 @@ public void testByStateActive() { .hasSize(4) .extracting(PlanItemInstance::getName) .containsExactly("A", "A", "Stage one", "Stage one"); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceStateActive().endOr() + .orderByName().asc() + .list(); + + assertThat(planItemInstances) + .hasSize(4) + .extracting(PlanItemInstance::getName) + .containsExactly("A", "A", "Stage one", "Stage one"); } @Test @@ -192,6 +290,16 @@ public void testByStateAndType() { .planItemInstanceState(PlanItemInstanceState.ENABLED) .planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK) .list()).hasSize(3); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceState(PlanItemInstanceState.ACTIVE).endOr() + .planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK) + .list()).hasSize(3); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .planItemInstanceState(PlanItemInstanceState.ENABLED) + .or().planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK).caseInstanceId("undefinedId").endOr() + .list()).hasSize(3); } @Test @@ -217,6 +325,19 @@ public void testByStateCompleted() { // Without ended, should only return runtime plan item instances assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceStateCompleted().list()).isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceStateCompleted().endOr().includeEnded() + .list()).hasSize(3); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .planItemInstanceStateCompleted() + .includeEnded() + .list()).hasSize(3); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceStateCompleted().endOr() + .list()).isEmpty(); + } @Test @@ -231,6 +352,18 @@ public void testByStateTerminated() { .list(); assertThat(planItemInstances).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").ended().endOr() + .planItemInstanceStateTerminated() + .list() + ).isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .ended() + .or().caseInstanceId("undefinedId").planItemInstanceStateTerminated().endOr() + .list() + ).isEmpty(); + // Completing the user event will terminate A/C/Stage for c UserEventListenerInstance userEventListenerInstance = cmmnRuntimeService.createUserEventListenerInstanceQuery() .caseInstanceId(caseInstance.getId()) @@ -245,6 +378,14 @@ public void testByStateTerminated() { assertThat(planItemInstances) .extracting(PlanItemInstance::getName) .containsExactly("A", "C", "The Stage"); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").ended().endOr() + .or().caseInstanceId("undefinedId").planItemInstanceStateTerminated().endOr() + .orderByName().asc() + .list()) + .extracting(PlanItemInstance::getName) + .containsExactly("A", "C", "The Stage"); } @Test @@ -265,6 +406,24 @@ public void testIncludeEnded() { planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceName("A").ended().list(); assertThat(planItemInstances).hasSize(4); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceName("A").endOr() + .list(); + + assertThat(planItemInstances).hasSize(7); // 11 - 4 (runtime only) + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceName("A").endOr() + .includeEnded() + .list(); + assertThat(planItemInstances).hasSize(11); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceName("A").endOr() + .or().caseInstanceId("undefinedId").ended().endOr() + .list(); + assertThat(planItemInstances).hasSize(4); } @Test @@ -288,6 +447,21 @@ public void testCreatedBefore() { .planItemInstanceCreatedBefore(new Date(now.getTime() + 30000)) .list(); assertThat(planItemInstances).hasSize(7); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .planItemInstanceName("A") + .planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK) + .or().caseInstanceId("undefinedId").planItemInstanceCreatedBefore(new Date(now.getTime() + 10000)).endOr() + .list(); + assertThat(planItemInstances).hasSize(3); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .planItemInstanceName("A") + .planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK) + .or().caseInstanceId("undefinedId").planItemInstanceCreatedBefore(new Date(now.getTime() + 30000)).endOr() + .list(); + + assertThat(planItemInstances).hasSize(7); } @Test @@ -311,6 +485,21 @@ public void testCreatedAfter() { .planItemInstanceCreatedAfter(new Date(now.getTime() + 10000)) .list(); assertThat(planItemInstances).hasSize(8); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().planItemInstanceName("A").caseInstanceId("undefinedId").endOr() + .or().caseInstanceId("undefinedId").planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK).endOr() + .or().caseInstanceId("undefinedId").planItemInstanceCreatedAfter(new Date(now.getTime() - 10000)).endOr() + .list(); + assertThat(planItemInstances).hasSize(10); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().planItemInstanceName("A").caseInstanceId("undefinedId").endOr() + .or().caseInstanceId("undefinedId").planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK).endOr() + .or().caseInstanceId("undefinedId").planItemInstanceCreatedAfter(new Date(now.getTime() + 10000)).endOr() + .list(); + + assertThat(planItemInstances).hasSize(8); } @Test @@ -348,6 +537,34 @@ public void testLastAvailableBeforeAndAfter() { .planItemInstanceLastAvailableBefore(new Date(now.getTime() + 10000)) .list(); assertThat(planItemInstances).hasSize(3); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceName("A").endOr() + .or().planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK).endOr() + .or().caseInstanceId("undefinedId").planItemInstanceLastAvailableAfter(new Date(now.getTime() - 10000)).endOr() + .list(); + assertThat(planItemInstances).hasSize(8); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceName("A").endOr() + .or().caseInstanceId("undefinedId").planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK).endOr() + .or().caseInstanceId("undefinedId").planItemInstanceLastAvailableBefore(new Date(now.getTime() - 10000)).endOr() + .or().caseInstanceId("undefinedId").list(); + assertThat(planItemInstances).isEmpty(); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceName("A").endOr() + .or().caseInstanceId("undefinedId").planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK).endOr() + .or().caseInstanceId("undefinedId").planItemInstanceLastAvailableAfter(new Date(now.getTime() + 10000)).endOr() + .list(); + assertThat(planItemInstances).hasSize(5); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceName("A").endOr() + .or().caseInstanceId("undefinedId").planItemDefinitionType(PlanItemDefinitionType.HUMAN_TASK).endOr() + .or().caseInstanceId("undefinedId").planItemInstanceLastAvailableBefore(new Date(now.getTime() + 10000)).endOr() + .list(); + assertThat(planItemInstances).hasSize(3); } @Test @@ -379,6 +596,28 @@ public void testLastEnabledBeforeAndAfter() { planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() .planItemInstanceLastEnabledAfter(new Date(now.getTime() + 250000)).list(); assertThat(planItemInstances).isEmpty(); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastEnabledBefore(new Date(now.getTime() + 30000)).endOr().list(); + assertThat(planItemInstances).hasSize(5); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastEnabledBefore(new Date(now.getTime() + 5000)).endOr().list(); + assertThat(planItemInstances).hasSize(2); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastEnabledBefore(new Date(now.getTime() - 1000)).endOr().list(); + assertThat(planItemInstances).isEmpty(); + + // After + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastEnabledAfter(new Date(now.getTime() - 5000)).endOr().list(); + assertThat(planItemInstances).hasSize(5); + + planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastEnabledAfter(new Date(now.getTime() + 250000)).endOr() + .list(); + assertThat(planItemInstances).isEmpty(); } @Test @@ -400,11 +639,31 @@ public void testLastDisabledBeforeAndAfter() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastDisabledBefore(new Date(now.getTime() + 5000)).list()).hasSize(1); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastDisabledBefore(new Date(now.getTime() - 5000)).list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledBefore(new Date(now.getTime() - 5000)).endOr() + .list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledBefore(new Date(now.getTime() + 5000)).endOr() + .list()).hasSize(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledBefore(new Date(now.getTime() - 5000)).endOr() + .list()).isEmpty(); + // After assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastDisabledAfter(new Date(now.getTime())).list()).hasSize(2); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastDisabledAfter(new Date(now.getTime() + 5000)).list()).hasSize(1); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastDisabledAfter(new Date(now.getTime() + 11000)).list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledAfter(new Date(now.getTime())).endOr() + .list()).hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledAfter(new Date(now.getTime() + 5000)).endOr() + .list()).hasSize(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledAfter(new Date(now.getTime() + 11000)).endOr() + .list()).isEmpty(); + // Re-enable and disable PlanItemInstance planItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(planItemInstanceId).singleResult(); Date lastEnabledTime = planItemInstance.getLastEnabledTime(); @@ -423,6 +682,22 @@ public void testLastDisabledBeforeAndAfter() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastDisabledAfter(new Date(now.getTime())).list()).hasSize(2); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastDisabledAfter(new Date(now.getTime() + 15000)).list()).hasSize(1); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastDisabledAfter(new Date(now.getTime() + 35000)).list()).isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledBefore(new Date(now.getTime() + 20000)).endOr() + .list()).hasSize(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledBefore(new Date(now.getTime() + 5000)).endOr() + .list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledAfter(new Date(now.getTime())).endOr() + .list()).hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledAfter(new Date(now.getTime() + 15000)).endOr() + .list()).hasSize(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastDisabledAfter(new Date(now.getTime() + 35000)).endOr() + .list()).isEmpty(); } @Test @@ -437,6 +712,20 @@ public void testLastStartedBeforeAndAfter() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastStartedBefore(new Date(now.getTime() + 1000)).list()).hasSize(8); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastStartedBefore(new Date(now.getTime() - 1000)).list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastStartedAfter(new Date(now.getTime() - 1000)).endOr() + .list()).hasSize(8); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastStartedAfter(new Date(now.getTime() + 1000)).endOr() + .list()).isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastStartedBefore(new Date(now.getTime() + 1000)).endOr() + .list()).hasSize(8); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastStartedBefore(new Date(now.getTime() - 1000)).endOr() + .list()).isEmpty(); + // Starting an enabled planitem setClockTo(now.getTime() + 10000); cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceName("B").listPage(0, 2) @@ -450,6 +739,26 @@ public void testLastStartedBeforeAndAfter() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastStartedBefore(new Date(now.getTime() + 15000)).list()).hasSize(10); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceLastStartedBefore(new Date(now.getTime() - 1000)).list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastStartedAfter(new Date(now.getTime() - 1000)).endOr() + .list()).hasSize(10); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastStartedAfter(new Date(now.getTime() + 5000)).endOr() + .list()).hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastStartedAfter(new Date(now.getTime() + 15000)).endOr() + .list()).isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastStartedBefore(new Date(now.getTime() + 1000)).endOr() + .list()).hasSize(8); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastStartedBefore(new Date(now.getTime() + 15000)).endOr() + .list()).hasSize(10); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceLastStartedBefore(new Date(now.getTime() - 1000)).endOr() + .list()).isEmpty(); + } @Test @@ -489,6 +798,70 @@ public void testCompletedBeforeAndAfter() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceEndedAfter(new Date(now.getTime())).ended().list()).hasSize(2); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceEndedAfter(new Date(now.getTime() + 15000)).includeEnded().list()) .hasSize(1); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceCompletedBefore(new Date(now.getTime() + 30000)).endOr() + .list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceCompletedBefore(new Date(now.getTime() + 30000)).endOr() + .includeEnded() + .list()) + .hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceCompletedBefore(new Date(now.getTime() + 15000)).endOr() + .includeEnded() + .list()) + .hasSize(1); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceCompletedAfter(new Date(now.getTime())).endOr() + .list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceCompletedAfter(new Date(now.getTime())).endOr() + .includeEnded() + .list()).hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceCompletedAfter(new Date(now.getTime())).endOr() + .or().caseInstanceId("undefinedId").ended().endOr() + .list()).hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceCompletedAfter(new Date(now.getTime() + 15000)).endOr() + .includeEnded() + .list()) + .hasSize(1); + + // Same queries, but with endedBefore/After + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceEndedBefore(new Date(now.getTime() + 30000)).endOr() + .list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceEndedBefore(new Date(now.getTime() + 30000)).endOr() + .includeEnded() + .list()) + .hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceEndedBefore(new Date(now.getTime() + 15000)).endOr() + .includeEnded() + .list()) + .hasSize(1); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceEndedAfter(new Date(now.getTime())).endOr() + .list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceEndedAfter(new Date(now.getTime())).endOr() + .includeEnded() + .list()).hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceEndedAfter(new Date(now.getTime())).endOr() + .or().caseInstanceId("undefinedId").ended().endOr() + .list()).hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceEndedAfter(new Date(now.getTime() + 15000)).endOr() + .includeEnded() + .list()) + .hasSize(1); + } @Test @@ -519,6 +892,41 @@ public void testLastOccurredBeforeAndAfter() { .hasSize(1); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceOccurredBefore(new Date(now.getTime() - 1000)).includeEnded().list()) .isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceOccurredAfter(new Date(now.getTime() - 1000)).endOr() + .list()).isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceOccurredAfter(new Date(now.getTime() - 1000)).endOr() + .includeEnded() + .list()) + .hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceOccurredAfter(new Date(now.getTime() + 1000)).endOr() + .includeEnded() + .list()) + .hasSize(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceOccurredAfter(new Date(now.getTime() + 15000)).endOr() + .includeEnded() + .list()) + .isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceOccurredBefore(new Date(now.getTime() + 20000)).endOr() + .includeEnded() + .list()) + .hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceOccurredBefore(new Date(now.getTime() + 5000)).endOr() + .includeEnded() + .list()) + .hasSize(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceOccurredBefore(new Date(now.getTime() - 1000)).endOr() + .includeEnded() + .list()) + .isEmpty(); } @Test @@ -568,6 +976,75 @@ public void testExitBeforeAndAfter() { .planItemDefinitionType(PlanItemDefinitionType.USER_EVENT_LISTENER) .planItemInstanceEndedAfter(new Date(now.getTime() - 1000)).list()).hasSize(2); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceExitAfter(new Date(now.getTime() - 1000)).endOr() + .list()).hasSize(6); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceExitAfter(new Date(now.getTime() + 1000)).endOr() + .list()).hasSize(3); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceExitAfter(new Date(now.getTime() + 20000)).endOr() + .list()) + .isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceExitBefore(new Date(now.getTime() - 1000)).endOr() + .list()) + .isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceExitBefore(new Date(now.getTime() + 1000)).endOr() + .list()) + .hasSize(3); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceExitBefore(new Date(now.getTime() + 20000)).endOr() + .list()) + .hasSize(6); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceEndedAfter(new Date(now.getTime() - 1000)).endOr() + .list()) + .hasSize(8); // + 2 for user event listener + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceEndedAfter(new Date(now.getTime() + 1000)).endOr() + .list()) + .hasSize(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceEndedAfter(new Date(now.getTime() + 20000)).endOr() + .list()) + .isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceEndedBefore(new Date(now.getTime() - 1000)).endOr() + .list()) + .isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceEndedBefore(new Date(now.getTime() + 1000)).endOr() + .list()) + .hasSize(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceEndedBefore(new Date(now.getTime() + 20000)).endOr() + .list()) + .hasSize(8); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemDefinitionType(PlanItemDefinitionType.USER_EVENT_LISTENER).endOr() + .or().caseInstanceId("undefinedId").planItemInstanceEndedAfter(new Date(now.getTime() - 1000)).endOr() + .list()).hasSize(2); + } @Test @@ -606,6 +1083,52 @@ public void testTerminateBeforeAndAfter() { .isEmpty(); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().includeEnded().planItemInstanceEndedAfter(new Date(now.getTime() - 1000)).list()) .hasSize(2); + + // Terminated + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceTerminatedBefore(new Date(now.getTime() + 1000)).endOr() + .list()) + .hasSize(2); // 2 -> stage and C + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceTerminatedBefore(new Date(now.getTime() - 1000)).endOr() + .list()) + .isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceTerminatedAfter(new Date(now.getTime() + 1000)).endOr() + .list()) + .isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceTerminatedAfter(new Date(now.getTime() - 1000)).endOr() + .list()) + .hasSize(2); + + // Ended + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceEndedBefore(new Date(now.getTime() + 1000)).endOr() + .list()) + .hasSize(2); // 2 -> stage and C + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceEndedBefore(new Date(now.getTime() - 1000)).endOr() + .list()) + .isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceEndedAfter(new Date(now.getTime() + 1000)).endOr() + .list()) + .isEmpty(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .includeEnded() + .or().caseInstanceId("undefinedId").planItemInstanceEndedAfter(new Date(now.getTime() - 1000)).endOr() + .list()) + .hasSize(2); } @Test @@ -681,6 +1204,7 @@ public void localize(HistoricPlanItemInstance historicPlanItemInstance, String l ); } + @Test public void testQueryVariableValueEqualsAndNotEquals() { CaseInstance caseWithStringValue = cmmnRuntimeService.createCaseInstanceBuilder() .caseDefinitionKey("testPlanItemInstanceQuery") @@ -712,6 +1236,13 @@ public void testQueryVariableValueEqualsAndNotEquals() { assertThat(planItemWithStringValue).isNotNull(); + planItemWithStringValue = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseDefinitionId("undefinedId").caseInstanceId(caseWithStringValue.getId()).endOr() + .or().caseDefinitionId("undefinedId").planItemInstanceName("Stage one").endOr() + .singleResult(); + + assertThat(planItemWithStringValue).isNotNull(); + PlanItemInstance planItemWithNullValue = cmmnRuntimeService.createPlanItemInstanceQuery() .caseInstanceId(caseWithNullValue.getId()) .planItemInstanceName("Stage one") @@ -719,6 +1250,13 @@ public void testQueryVariableValueEqualsAndNotEquals() { assertThat(planItemWithNullValue).isNotNull(); + planItemWithNullValue = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseDefinitionId("undefinedId").caseInstanceId(caseWithNullValue.getId()).endOr() + .or().caseDefinitionId("undefinedId").planItemInstanceName("Stage one").endOr() + .singleResult(); + + assertThat(planItemWithNullValue).isNotNull(); + PlanItemInstance planItemWithLongValue = cmmnRuntimeService.createPlanItemInstanceQuery() .caseInstanceId(caseWithLongValue.getId()) .planItemInstanceName("Stage one") @@ -726,6 +1264,13 @@ public void testQueryVariableValueEqualsAndNotEquals() { assertThat(planItemWithLongValue).isNotNull(); + planItemWithLongValue = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseDefinitionId("undefinedId").caseInstanceId(caseWithLongValue.getId()).endOr() + .or().caseDefinitionId("undefinedId").planItemInstanceName("Stage one").endOr() + .singleResult(); + + assertThat(planItemWithLongValue).isNotNull(); + PlanItemInstance planItemWithDoubleValue = cmmnRuntimeService.createPlanItemInstanceQuery() .caseInstanceId(caseWithDoubleValue.getId()) .planItemInstanceName("Stage one") @@ -733,6 +1278,13 @@ public void testQueryVariableValueEqualsAndNotEquals() { assertThat(planItemWithDoubleValue).isNotNull(); + planItemWithDoubleValue = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseDefinitionId("undefinedId").caseInstanceId(caseWithDoubleValue.getId()).endOr() + .or().caseDefinitionId("undefinedId").planItemInstanceName("Stage one").endOr() + .singleResult(); + + assertThat(planItemWithDoubleValue).isNotNull(); + assertThat(cmmnRuntimeService.hasLocalVariable(planItemWithStringValue.getId(), "var")).isFalse(); cmmnRuntimeService.setLocalVariable(planItemWithStringValue.getId(), "var", "TEST"); assertThat(cmmnRuntimeService.hasLocalVariable(planItemWithStringValue.getId(), "var")).isTrue(); @@ -754,6 +1306,12 @@ public void testQueryVariableValueEqualsAndNotEquals() { tuple("Stage one", caseWithStringValue.getId()) ); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueEquals("TEST").list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithStringValue.getId()) + ); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueNotEquals("var", 100L).list()) .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) .containsExactlyInAnyOrder( @@ -808,6 +1366,183 @@ public void testQueryVariableValueEqualsAndNotEquals() { .containsExactlyInAnyOrder( tuple("Stage one", caseWithStringValue.getId()) ); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueNotEquals("var", "TEST").endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithNullValue.getId()), + tuple("Stage one", caseWithLongValue.getId()), + tuple("Stage one", caseWithDoubleValue.getId()) + ); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueEquals("var", "TEST").endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithStringValue.getId()) + ); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueEquals("TEST").endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithStringValue.getId()) + ); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueNotEquals("var", 100L).endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithStringValue.getId()), + tuple("Stage one", caseWithNullValue.getId()), + tuple("Stage one", caseWithDoubleValue.getId()) + ); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueEquals("var", 100L).endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithLongValue.getId()) + ); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueNotEquals("var", 45.55).endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithStringValue.getId()), + tuple("Stage one", caseWithNullValue.getId()), + tuple("Stage one", caseWithLongValue.getId()) + ); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueEquals("var", 45.55).endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithDoubleValue.getId()) + ); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueNotEquals("var", "test").endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithStringValue.getId()), + tuple("Stage one", caseWithNullValue.getId()), + tuple("Stage one", caseWithLongValue.getId()), + tuple("Stage one", caseWithDoubleValue.getId()) + ); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueNotEqualsIgnoreCase("var", "test").endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithNullValue.getId()), + tuple("Stage one", caseWithLongValue.getId()), + tuple("Stage one", caseWithDoubleValue.getId()) + ); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueEquals("var", "test").endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .isEmpty(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueEqualsIgnoreCase("var", "test").endOr() + .list()) + .extracting(PlanItemInstance::getName, PlanItemInstance::getCaseInstanceId) + .containsExactlyInAnyOrder( + tuple("Stage one", caseWithStringValue.getId()) + ); + + } + + @Test + @CmmnDeployment + public void testOrQueryByCompletable() { + CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder() + .caseDefinitionKey("testNonAutoCompleteStageManualCompleteable") + .variable("required", true) + .start(); + + final PlanItemInstance stagePlanItemInstance1 = cmmnRuntimeService.createPlanItemInstanceQuery().planItemDefinitionType(PlanItemDefinitionType.STAGE) + .singleResult(); + // Completing the one task should mark the stage as completeable + Task task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).singleResult(); + assertThat(task.getName()).isEqualTo("Required task"); + cmmnTaskService.complete(task.getId()); + + PlanItemInstance stagePlanItemInstance2 = cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceId(stagePlanItemInstance1.getId()) + .singleResult(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceCompletable().singleResult()).isNotNull(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceCompletable().endOr().singleResult()).isNotNull(); + + cmmnRuntimeService.completeStagePlanItemInstance(stagePlanItemInstance2.getId()); + + } + + @Test + @CmmnDeployment + public void testQueryByDerivedCaseDefinitionId() { + CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("dynamicPlanItemInjection").start(); + + List planItemInstances = getPlanItemInstances(caseInstance.getId()); + // inject new plan item into Stage A + PlanItemInstance injectedTask = dynamicCmmnService + .createInjectedPlanItemInstanceBuilder() + .name("Injected Task A") + .caseDefinitionId(caseInstance.getCaseDefinitionId()) + .elementId(getPlanItemInstanceByName(planItemInstances, "Task A", ACTIVE).getElementId()) + .createInStage(getPlanItemInstanceIdByNameAndState(planItemInstances, "Stage A", ACTIVE)); + + // test the query for the derived case definition (in this unit test, it will be the same as the running one) + List derivedPlanItems = cmmnRuntimeService.createPlanItemInstanceQuery() + .derivedCaseDefinitionId(caseInstance.getCaseDefinitionId()) + .list(); + + assertThat(derivedPlanItems).isNotNull(); + assertThat(derivedPlanItems) + .extracting(PlanItemInstance::getName) + .containsExactly("Injected Task A"); + + derivedPlanItems = cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").derivedCaseDefinitionId(caseInstance.getCaseDefinitionId()).endOr() + .list(); + + assertThat(derivedPlanItems).isNotNull(); + assertThat(derivedPlanItems) + .extracting(PlanItemInstance::getName) + .containsExactly("Injected Task A"); + + } + + @Test + @CmmnDeployment + public void testOrQueryByStages() { + CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("myCase").start(); + + List activeStages = cmmnRuntimeService.createPlanItemInstanceQuery().caseInstanceId(caseInstance.getId()).onlyStages() + .planItemInstanceStateActive().list(); + assertThat(activeStages) + .extracting(PlanItemInstance::getPlanItemDefinitionId) + .containsExactly("expandedStage2"); + + activeStages = cmmnRuntimeService.createPlanItemInstanceQuery().caseInstanceId(caseInstance.getId()) + .or().caseInstanceId("undefinedId").onlyStages().endOr() + .planItemInstanceStateActive().list(); + assertThat(activeStages) + .extracting(PlanItemInstance::getPlanItemDefinitionId) + .containsExactly("expandedStage2"); } private List startInstances(int numberOfInstances) { diff --git a/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/RuntimeServiceTest.java b/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/RuntimeServiceTest.java index cefbf20ee5c..729abdac760 100644 --- a/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/RuntimeServiceTest.java +++ b/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/runtime/RuntimeServiceTest.java @@ -435,6 +435,94 @@ public void testPlanItemVariableQueryWithBlockingTask() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseVariableValueLessThan("numberVar", 5).count()).isZero(); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseVariableValueLessThanOrEqual("numberVar", 10).count()).isEqualTo(4); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseVariableValueLessThanOrEqual("numberVar", 9).count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseVariableValueEquals(9).count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseVariableValueEquals(10).count()).isEqualTo(4); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseVariableExists("numberVar").count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseVariableExists("notExisting").count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseVariableNotExists("numberVar").count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseVariableNotExists("notExisting").count()).isEqualTo(4); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueEquals("var", "test").endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueEquals("var", "test2").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueEqualsIgnoreCase("var", "TEST").endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueEqualsIgnoreCase("var", "TEST2").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueNotEquals("var", "test2").endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueNotEquals("var", "test").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueNotEqualsIgnoreCase("var", "TEST2").endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueNotEqualsIgnoreCase("var", "TEST").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueLike("var", "te%").endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueLike("var", "te2%").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueLikeIgnoreCase("var", "TE%").endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueLikeIgnoreCase("var", "TE2%").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueGreaterThan("numberVar", 5).endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueGreaterThan("numberVar", 11).endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueGreaterThanOrEqual("numberVar", 10).endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueGreaterThanOrEqual("numberVar", 11).endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueLessThan("numberVar", 20).endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueLessThan("numberVar", 5).endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueLessThanOrEqual("numberVar", 10).endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefined").caseVariableValueLessThanOrEqual("numberVar", 9).endOr() + .count()).isZero(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableValueEquals(9).endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableValueEquals(10).endOr() + .count()).isEqualTo(4); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableExists("numberVar").endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableExists("notExisting").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableNotExists("numberVar").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableNotExists("notExisting").endOr() + .count()).isEqualTo(4); PlanItemInstance planItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery() .caseInstanceId(caseInstance.getId()) @@ -459,6 +547,8 @@ public void testPlanItemVariableQueryWithBlockingTask() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().caseVariableValueEquals("localVar", "test").count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableExists("localNumberVar").count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableNotExists("localNumberVar").count()).isEqualTo(3); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueEquals("localVar", "test").count()).isEqualTo(1); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueEquals("localVar", "test2").count()).isZero(); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueEqualsIgnoreCase("localVar", "TEST").count()).isEqualTo(1); @@ -473,6 +563,7 @@ public void testPlanItemVariableQueryWithBlockingTask() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueLikeIgnoreCase("localVar", "TE2%").count()).isZero(); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueGreaterThan("localNumberVar", 5).count()).isEqualTo(1); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueGreaterThan("localNumberVar", 17).count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueGreaterThan("localNumberVar", 17).count()).isZero(); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueGreaterThanOrEqual("localNumberVar", 15).count()).isEqualTo(1); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueGreaterThanOrEqual("localNumberVar", 16).count()).isZero(); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueLessThan("localNumberVar", 20).count()).isEqualTo(1); @@ -480,6 +571,91 @@ public void testPlanItemVariableQueryWithBlockingTask() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueLessThanOrEqual("localNumberVar", 15).count()).isEqualTo(1); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().variableValueLessThanOrEqual("localNumberVar", 9).count()).isZero(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableExists("localNumberVar").endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableNotExists("localNumberVar").endOr() + .count()).isEqualTo(3); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableValueGreaterThan("numberVar", 10).endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableValueGreaterThan("numberVar", 11).endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableValueGreaterThanOrEqual("numberVar", 11).endOr() + .count()).isEqualTo(4); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableValueGreaterThanOrEqual("numberVar", 12).endOr() + .count()).isZero(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").caseVariableValueEquals("localVar", "test").endOr() + .count()).isZero(); + + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueEquals("localVar", "test").endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueEquals("localVar", "test2").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueEqualsIgnoreCase("localVar", "TEST").endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueEqualsIgnoreCase("localVar", "TEST2").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueNotEquals("localVar", "test2").endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueNotEquals("localVar", "test").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueNotEqualsIgnoreCase("localVar", "TEST2").endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueNotEqualsIgnoreCase("localVar", "TEST").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueLike("localVar", "te%").endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueLike("localVar", "te2%").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueLikeIgnoreCase("localVar", "TE%").endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueLikeIgnoreCase("localVar", "TE2%").endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueGreaterThan("localNumberVar", 5).endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueGreaterThan("localNumberVar", 17).endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueGreaterThanOrEqual("localNumberVar", 15).endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueGreaterThanOrEqual("localNumberVar", 16).endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueLessThan("localNumberVar", 20).endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueLessThan("localNumberVar", 5).endOr() + .count()).isZero(); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueLessThanOrEqual("localNumberVar", 15).endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").variableValueLessThanOrEqual("localNumberVar", 9).endOr() + .count()).isZero(); cmmnRuntimeService.triggerPlanItemInstance(planItemInstance.getId()); planItemInstance = cmmnRuntimeService.createPlanItemInstanceQuery().caseInstanceId(caseInstance.getId()) .planItemInstanceState(PlanItemInstanceState.ACTIVE).singleResult(); @@ -1176,6 +1352,14 @@ public void planItemQueryWithoutTenant() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceName("Task A").planItemInstanceWithoutTenantId().count()).isEqualTo(1); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceName("Task A").planItemInstanceWithoutTenantId().list()).hasSize(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceName("Task A").endOr() + .or().caseInstanceId("undefinedId").planItemInstanceWithoutTenantId().endOr() + .count()).isEqualTo(1); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceName("Task A").endOr() + .or().caseInstanceId("undefinedId").planItemInstanceWithoutTenantId().endOr() + .list()).hasSize(1); } @Test diff --git a/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/tenant/MultiTenantTest.java b/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/tenant/MultiTenantTest.java index 7e51a9b80df..f446a5e8eb1 100644 --- a/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/tenant/MultiTenantTest.java +++ b/modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/tenant/MultiTenantTest.java @@ -63,6 +63,10 @@ public void testCaseInstances() { assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceWithoutTenantId().count()).isEqualTo(3); assertThat(cmmnRuntimeService.createPlanItemInstanceQuery().planItemInstanceTenantId("test-tenant").count()).isEqualTo(5); + assertThat(cmmnRuntimeService.createPlanItemInstanceQuery() + .or().caseInstanceId("undefinedId").planItemInstanceTenantId("test-tenant").endOr() + .count()).isEqualTo(5); + } } diff --git a/modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testOrQueryByCompletable.cmmn b/modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testOrQueryByCompletable.cmmn new file mode 100644 index 00000000000..3920f95258f --- /dev/null +++ b/modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testOrQueryByCompletable.cmmn @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testOrQueryByStages.cmmn b/modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testOrQueryByStages.cmmn new file mode 100644 index 00000000000..d94ec557b29 --- /dev/null +++ b/modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testOrQueryByStages.cmmn @@ -0,0 +1,332 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + complete + + + + + + + + complete + + + + + + + + complete + + + + + + + + complete + + + + + + + + complete + + + + + + + + complete + + + + + + + + complete + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + complete + + + + + + + + complete + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testQueryByDerivedCaseDefinitionId.cmmn b/modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testQueryByDerivedCaseDefinitionId.cmmn new file mode 100644 index 00000000000..c095a8aa4dc --- /dev/null +++ b/modules/flowable-cmmn-engine/src/test/resources/org/flowable/cmmn/test/runtime/PlanItemInstanceQueryTest.testQueryByDerivedCaseDefinitionId.cmmn @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + complete + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file