Skip to content

Commit 3c58869

Browse files
Automatically terminate plan item instances for which a plan item definition doesn't exist in the target cmmn definition with a case migration
1 parent 97a241d commit 3c58869

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-0
lines changed

modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/AbstractCmmnDynamicStateManager.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ protected void doMovePlanItemState(CaseInstanceChangeState caseInstanceChangeSta
133133

134134
executeTerminatePlanItemInstances(caseInstanceChangeState, caseInstance, commandContext);
135135

136+
executeTerminateNonExistingPlanItemInstancesInTargetCmmnModel(caseInstanceChangeState, commandContext);
137+
136138
setCaseDefinitionIdForPlanItemInstances(currentPlanItemInstances, caseInstanceChangeState.getCaseDefinitionToMigrateTo());
137139

138140
executeChangePlanItemIds(caseInstanceChangeState, originalCaseDefinitionId, commandContext);
@@ -835,6 +837,35 @@ protected void executeTerminatePlanItemInstances(CaseInstanceChangeState caseIns
835837
}
836838
}
837839

840+
protected void executeTerminateNonExistingPlanItemInstancesInTargetCmmnModel(CaseInstanceChangeState caseInstanceChangeState, CommandContext commandContext) {
841+
if (caseInstanceChangeState.getCaseDefinitionToMigrateTo() != null) {
842+
CmmnModel targetCmmnModel = CaseDefinitionUtil.getCmmnModel(caseInstanceChangeState.getCaseDefinitionToMigrateTo().getId());
843+
List<String> excludePlanItemDefinitionIds = new ArrayList<>();
844+
for (TerminatePlanItemDefinitionMapping planItemDefinitionMapping : caseInstanceChangeState.getTerminatePlanItemDefinitions()) {
845+
excludePlanItemDefinitionIds.add(planItemDefinitionMapping.getPlanItemDefinitionId());
846+
}
847+
848+
for (ChangePlanItemDefinitionWithNewTargetIdsMapping newTargetIdsMapping : caseInstanceChangeState.getChangePlanItemDefinitionWithNewTargetIds()) {
849+
excludePlanItemDefinitionIds.add(newTargetIdsMapping.getExistingPlanItemDefinitionId());
850+
}
851+
852+
for (ChangePlanItemIdWithDefinitionIdMapping definitionIdMapping : caseInstanceChangeState.getChangePlanItemIdsWithDefinitionId()) {
853+
excludePlanItemDefinitionIds.add(definitionIdMapping.getExistingPlanItemDefinitionId());
854+
}
855+
856+
for (String currentPlanItemDefinitionId : caseInstanceChangeState.getCurrentPlanItemInstances().keySet()) {
857+
if (!excludePlanItemDefinitionIds.contains(currentPlanItemDefinitionId) && targetCmmnModel.findPlanItemDefinition(currentPlanItemDefinitionId) == null) {
858+
for (PlanItemInstanceEntity currentPlanItemInstance : caseInstanceChangeState.getCurrentPlanItemInstances().get(currentPlanItemDefinitionId)) {
859+
if (!PlanItemInstanceState.TERMINAL_STATES.contains(currentPlanItemInstance.getState())) {
860+
terminatePlanItemInstance(currentPlanItemInstance, commandContext);
861+
caseInstanceChangeState.addTerminatedPlanItemInstance(currentPlanItemInstance.getPlanItemDefinitionId(), currentPlanItemInstance);
862+
}
863+
}
864+
}
865+
}
866+
}
867+
}
868+
838869
protected abstract boolean isDirectPlanItemDefinitionMigration(PlanItemDefinition currentPlanItemDefinition, PlanItemDefinition newPlanItemDefinition);
839870

840871
protected Map<String, List<PlanItemInstanceEntity>> retrievePlanItemInstances(String caseInstanceId) {

modules/flowable-cmmn-engine/src/test/java/org/flowable/cmmn/test/migration/CaseInstanceMigrationTest.java

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,130 @@ void withSimpleOneTaskCaseChangingOnlyTaskProperties() {
439439
}
440440
}
441441
}
442+
443+
@Test
444+
void withAutomatedMigrationFromTwoTasksToOneTask() {
445+
// Arrange
446+
deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/two-task.cmmn.xml");
447+
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("testCase").start();
448+
CaseDefinition destinationDefinition = deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/one-task.cmmn.xml");
449+
450+
// Act
451+
cmmnMigrationService.createCaseInstanceMigrationBuilder()
452+
.migrateToCaseDefinition(destinationDefinition.getId())
453+
.migrate(caseInstance.getId());
454+
455+
// Assert
456+
CaseInstance caseInstanceAfterMigration = cmmnRuntimeService.createCaseInstanceQuery()
457+
.caseInstanceId(caseInstance.getId())
458+
.singleResult();
459+
assertThat(caseInstanceAfterMigration.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
460+
assertThat(caseInstanceAfterMigration.getCaseDefinitionVersion()).isEqualTo(2);
461+
assertThat(caseInstanceAfterMigration.getCaseDefinitionDeploymentId()).isEqualTo(destinationDefinition.getDeploymentId());
462+
List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
463+
.caseInstanceId(caseInstance.getId())
464+
.list();
465+
assertThat(planItemInstances).hasSize(1);
466+
assertThat(planItemInstances)
467+
.extracting(PlanItemInstance::getCaseDefinitionId)
468+
.containsOnly(destinationDefinition.getId());
469+
assertThat(planItemInstances)
470+
.extracting(PlanItemInstance::getName)
471+
.containsExactlyInAnyOrder("Task 1");
472+
assertThat(planItemInstances)
473+
.extracting(PlanItemInstance::getState)
474+
.containsOnly(PlanItemInstanceState.ACTIVE);
475+
476+
List<Task> tasks = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).list();
477+
assertThat(tasks).hasSize(1);
478+
assertThat(tasks.get(0).getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
479+
cmmnTaskService.complete(tasks.get(0).getId());
480+
481+
assertThat(cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isZero();
482+
483+
if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) {
484+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isEqualTo(1);
485+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).singleResult().getCaseDefinitionId())
486+
.isEqualTo(destinationDefinition.getId());
487+
488+
List<HistoricPlanItemInstance> historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery()
489+
.planItemInstanceCaseInstanceId(caseInstance.getId()).list();
490+
assertThat(historicPlanItemInstances).hasSize(2);
491+
for (HistoricPlanItemInstance historicPlanItemInstance : historicPlanItemInstances) {
492+
assertThat(historicPlanItemInstance.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
493+
}
494+
495+
List<HistoricTaskInstance> historicTasks = cmmnHistoryService.createHistoricTaskInstanceQuery().caseInstanceId(caseInstance.getId()).list();
496+
assertThat(historicTasks).hasSize(2);
497+
for (HistoricTaskInstance historicTask : historicTasks) {
498+
assertThat(historicTask.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
499+
}
500+
}
501+
}
502+
503+
@Test
504+
void withActivateTaskFromTwoTasksToOneTask() {
505+
// Arrange
506+
deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/two-task.cmmn.xml");
507+
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("testCase").start();
508+
CaseDefinition destinationDefinition = deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/one-task.cmmn.xml");
509+
510+
Task task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("humanTask1").singleResult();
511+
cmmnTaskService.complete(task.getId());
512+
513+
// Act
514+
cmmnMigrationService.createCaseInstanceMigrationBuilder()
515+
.migrateToCaseDefinition(destinationDefinition.getId())
516+
.addActivatePlanItemDefinitionMapping(PlanItemDefinitionMappingBuilder.createActivatePlanItemDefinitionMappingFor("humanTask1"))
517+
.migrate(caseInstance.getId());
518+
519+
// Assert
520+
CaseInstance caseInstanceAfterMigration = cmmnRuntimeService.createCaseInstanceQuery()
521+
.caseInstanceId(caseInstance.getId())
522+
.singleResult();
523+
assertThat(caseInstanceAfterMigration.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
524+
assertThat(caseInstanceAfterMigration.getCaseDefinitionVersion()).isEqualTo(2);
525+
assertThat(caseInstanceAfterMigration.getCaseDefinitionDeploymentId()).isEqualTo(destinationDefinition.getDeploymentId());
526+
List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
527+
.caseInstanceId(caseInstance.getId())
528+
.list();
529+
assertThat(planItemInstances).hasSize(1);
530+
assertThat(planItemInstances)
531+
.extracting(PlanItemInstance::getCaseDefinitionId)
532+
.containsOnly(destinationDefinition.getId());
533+
assertThat(planItemInstances)
534+
.extracting(PlanItemInstance::getName)
535+
.containsExactlyInAnyOrder("Task 1");
536+
assertThat(planItemInstances)
537+
.extracting(PlanItemInstance::getState)
538+
.containsOnly(PlanItemInstanceState.ACTIVE);
539+
540+
List<Task> tasks = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).list();
541+
assertThat(tasks).hasSize(1);
542+
assertThat(tasks.get(0).getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
543+
cmmnTaskService.complete(tasks.get(0).getId());
544+
545+
assertThat(cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isZero();
546+
547+
if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) {
548+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isEqualTo(1);
549+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).singleResult().getCaseDefinitionId())
550+
.isEqualTo(destinationDefinition.getId());
551+
552+
List<HistoricPlanItemInstance> historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery()
553+
.planItemInstanceCaseInstanceId(caseInstance.getId()).list();
554+
assertThat(historicPlanItemInstances).hasSize(3);
555+
for (HistoricPlanItemInstance historicPlanItemInstance : historicPlanItemInstances) {
556+
assertThat(historicPlanItemInstance.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
557+
}
558+
559+
List<HistoricTaskInstance> historicTasks = cmmnHistoryService.createHistoricTaskInstanceQuery().caseInstanceId(caseInstance.getId()).list();
560+
assertThat(historicTasks).hasSize(3);
561+
for (HistoricTaskInstance historicTask : historicTasks) {
562+
assertThat(historicTask.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
563+
}
564+
}
565+
}
442566

443567
@Test
444568
void withTwoTasksIntroducingANewStageAroundSecondTask() {

0 commit comments

Comments
 (0)