Skip to content

Commit

Permalink
Automatically terminate plan item instances for which a plan item def…
Browse files Browse the repository at this point in the history
…inition doesn't exist in the target cmmn definition with a case migration
  • Loading branch information
tijsrademakers committed Aug 30, 2024
1 parent 97a241d commit 3c58869
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ protected void doMovePlanItemState(CaseInstanceChangeState caseInstanceChangeSta

executeTerminatePlanItemInstances(caseInstanceChangeState, caseInstance, commandContext);

executeTerminateNonExistingPlanItemInstancesInTargetCmmnModel(caseInstanceChangeState, commandContext);

setCaseDefinitionIdForPlanItemInstances(currentPlanItemInstances, caseInstanceChangeState.getCaseDefinitionToMigrateTo());

executeChangePlanItemIds(caseInstanceChangeState, originalCaseDefinitionId, commandContext);
Expand Down Expand Up @@ -835,6 +837,35 @@ protected void executeTerminatePlanItemInstances(CaseInstanceChangeState caseIns
}
}

protected void executeTerminateNonExistingPlanItemInstancesInTargetCmmnModel(CaseInstanceChangeState caseInstanceChangeState, CommandContext commandContext) {
if (caseInstanceChangeState.getCaseDefinitionToMigrateTo() != null) {
CmmnModel targetCmmnModel = CaseDefinitionUtil.getCmmnModel(caseInstanceChangeState.getCaseDefinitionToMigrateTo().getId());
List<String> excludePlanItemDefinitionIds = new ArrayList<>();
for (TerminatePlanItemDefinitionMapping planItemDefinitionMapping : caseInstanceChangeState.getTerminatePlanItemDefinitions()) {
excludePlanItemDefinitionIds.add(planItemDefinitionMapping.getPlanItemDefinitionId());
}

for (ChangePlanItemDefinitionWithNewTargetIdsMapping newTargetIdsMapping : caseInstanceChangeState.getChangePlanItemDefinitionWithNewTargetIds()) {
excludePlanItemDefinitionIds.add(newTargetIdsMapping.getExistingPlanItemDefinitionId());
}

for (ChangePlanItemIdWithDefinitionIdMapping definitionIdMapping : caseInstanceChangeState.getChangePlanItemIdsWithDefinitionId()) {
excludePlanItemDefinitionIds.add(definitionIdMapping.getExistingPlanItemDefinitionId());
}

for (String currentPlanItemDefinitionId : caseInstanceChangeState.getCurrentPlanItemInstances().keySet()) {
if (!excludePlanItemDefinitionIds.contains(currentPlanItemDefinitionId) && targetCmmnModel.findPlanItemDefinition(currentPlanItemDefinitionId) == null) {
for (PlanItemInstanceEntity currentPlanItemInstance : caseInstanceChangeState.getCurrentPlanItemInstances().get(currentPlanItemDefinitionId)) {
if (!PlanItemInstanceState.TERMINAL_STATES.contains(currentPlanItemInstance.getState())) {
terminatePlanItemInstance(currentPlanItemInstance, commandContext);
caseInstanceChangeState.addTerminatedPlanItemInstance(currentPlanItemInstance.getPlanItemDefinitionId(), currentPlanItemInstance);
}
}
}
}
}
}

protected abstract boolean isDirectPlanItemDefinitionMigration(PlanItemDefinition currentPlanItemDefinition, PlanItemDefinition newPlanItemDefinition);

protected Map<String, List<PlanItemInstanceEntity>> retrievePlanItemInstances(String caseInstanceId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,130 @@ void withSimpleOneTaskCaseChangingOnlyTaskProperties() {
}
}
}

@Test
void withAutomatedMigrationFromTwoTasksToOneTask() {
// Arrange
deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/two-task.cmmn.xml");
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("testCase").start();
CaseDefinition destinationDefinition = deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/one-task.cmmn.xml");

// Act
cmmnMigrationService.createCaseInstanceMigrationBuilder()
.migrateToCaseDefinition(destinationDefinition.getId())
.migrate(caseInstance.getId());

// Assert
CaseInstance caseInstanceAfterMigration = cmmnRuntimeService.createCaseInstanceQuery()
.caseInstanceId(caseInstance.getId())
.singleResult();
assertThat(caseInstanceAfterMigration.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
assertThat(caseInstanceAfterMigration.getCaseDefinitionVersion()).isEqualTo(2);
assertThat(caseInstanceAfterMigration.getCaseDefinitionDeploymentId()).isEqualTo(destinationDefinition.getDeploymentId());
List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
.caseInstanceId(caseInstance.getId())
.list();
assertThat(planItemInstances).hasSize(1);
assertThat(planItemInstances)
.extracting(PlanItemInstance::getCaseDefinitionId)
.containsOnly(destinationDefinition.getId());
assertThat(planItemInstances)
.extracting(PlanItemInstance::getName)
.containsExactlyInAnyOrder("Task 1");
assertThat(planItemInstances)
.extracting(PlanItemInstance::getState)
.containsOnly(PlanItemInstanceState.ACTIVE);

List<Task> tasks = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).list();
assertThat(tasks).hasSize(1);
assertThat(tasks.get(0).getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
cmmnTaskService.complete(tasks.get(0).getId());

assertThat(cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isZero();

if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) {
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isEqualTo(1);
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).singleResult().getCaseDefinitionId())
.isEqualTo(destinationDefinition.getId());

List<HistoricPlanItemInstance> historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery()
.planItemInstanceCaseInstanceId(caseInstance.getId()).list();
assertThat(historicPlanItemInstances).hasSize(2);
for (HistoricPlanItemInstance historicPlanItemInstance : historicPlanItemInstances) {
assertThat(historicPlanItemInstance.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
}

List<HistoricTaskInstance> historicTasks = cmmnHistoryService.createHistoricTaskInstanceQuery().caseInstanceId(caseInstance.getId()).list();
assertThat(historicTasks).hasSize(2);
for (HistoricTaskInstance historicTask : historicTasks) {
assertThat(historicTask.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
}
}
}

@Test
void withActivateTaskFromTwoTasksToOneTask() {
// Arrange
deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/two-task.cmmn.xml");
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("testCase").start();
CaseDefinition destinationDefinition = deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/one-task.cmmn.xml");

Task task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("humanTask1").singleResult();
cmmnTaskService.complete(task.getId());

// Act
cmmnMigrationService.createCaseInstanceMigrationBuilder()
.migrateToCaseDefinition(destinationDefinition.getId())
.addActivatePlanItemDefinitionMapping(PlanItemDefinitionMappingBuilder.createActivatePlanItemDefinitionMappingFor("humanTask1"))
.migrate(caseInstance.getId());

// Assert
CaseInstance caseInstanceAfterMigration = cmmnRuntimeService.createCaseInstanceQuery()
.caseInstanceId(caseInstance.getId())
.singleResult();
assertThat(caseInstanceAfterMigration.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
assertThat(caseInstanceAfterMigration.getCaseDefinitionVersion()).isEqualTo(2);
assertThat(caseInstanceAfterMigration.getCaseDefinitionDeploymentId()).isEqualTo(destinationDefinition.getDeploymentId());
List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
.caseInstanceId(caseInstance.getId())
.list();
assertThat(planItemInstances).hasSize(1);
assertThat(planItemInstances)
.extracting(PlanItemInstance::getCaseDefinitionId)
.containsOnly(destinationDefinition.getId());
assertThat(planItemInstances)
.extracting(PlanItemInstance::getName)
.containsExactlyInAnyOrder("Task 1");
assertThat(planItemInstances)
.extracting(PlanItemInstance::getState)
.containsOnly(PlanItemInstanceState.ACTIVE);

List<Task> tasks = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).list();
assertThat(tasks).hasSize(1);
assertThat(tasks.get(0).getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
cmmnTaskService.complete(tasks.get(0).getId());

assertThat(cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isZero();

if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) {
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isEqualTo(1);
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).singleResult().getCaseDefinitionId())
.isEqualTo(destinationDefinition.getId());

List<HistoricPlanItemInstance> historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery()
.planItemInstanceCaseInstanceId(caseInstance.getId()).list();
assertThat(historicPlanItemInstances).hasSize(3);
for (HistoricPlanItemInstance historicPlanItemInstance : historicPlanItemInstances) {
assertThat(historicPlanItemInstance.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
}

List<HistoricTaskInstance> historicTasks = cmmnHistoryService.createHistoricTaskInstanceQuery().caseInstanceId(caseInstance.getId()).list();
assertThat(historicTasks).hasSize(3);
for (HistoricTaskInstance historicTask : historicTasks) {
assertThat(historicTask.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
}
}
}

@Test
void withTwoTasksIntroducingANewStageAroundSecondTask() {
Expand Down

0 comments on commit 3c58869

Please sign in to comment.