Skip to content

Commit afcbcac

Browse files
Update task properties, when changed, for case instance migration
1 parent f344a93 commit afcbcac

File tree

4 files changed

+211
-2
lines changed

4 files changed

+211
-2
lines changed

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

+33-2
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ protected void doMovePlanItemState(CaseInstanceChangeState caseInstanceChangeSta
139139

140140
executeChangePlanItemDefinitionWithNewTargetIds(caseInstanceChangeState, originalCaseDefinitionId, commandContext);
141141

142-
navigatePlanItemInstances(currentPlanItemInstances, caseInstanceChangeState.getCaseDefinitionToMigrateTo());
142+
navigatePlanItemInstances(currentPlanItemInstances, caseInstanceChangeState.getCaseDefinitionToMigrateTo(), originalCaseDefinitionId);
143143

144144
// Set the case variables first so they are available during the change state logic
145145
caseInstance.setVariables(caseInstanceChangeState.getCaseVariables());
@@ -856,9 +856,11 @@ protected void setCaseDefinitionIdForPlanItemInstances(Map<String, List<PlanItem
856856
}
857857
}
858858

859-
protected void navigatePlanItemInstances(Map<String, List<PlanItemInstanceEntity>> stagesByPlanItemDefinitionId, CaseDefinition caseDefinition) {
859+
protected void navigatePlanItemInstances(Map<String, List<PlanItemInstanceEntity>> stagesByPlanItemDefinitionId, CaseDefinition caseDefinition, String originalCaseDefinitionId) {
860860
if (caseDefinition != null) {
861861
TaskService taskService = cmmnEngineConfiguration.getTaskServiceConfiguration().getTaskService();
862+
CmmnModel originalCmmnModel = CaseDefinitionUtil.getCmmnModel(originalCaseDefinitionId);
863+
CmmnModel targetCmmnModel = CaseDefinitionUtil.getCmmnModel(caseDefinition.getId());
862864
for (List<PlanItemInstanceEntity> planItemInstances : stagesByPlanItemDefinitionId.values()) {
863865
for (PlanItemInstanceEntity planItemInstance : planItemInstances) {
864866

@@ -869,6 +871,31 @@ protected void navigatePlanItemInstances(Map<String, List<PlanItemInstanceEntity
869871
.subScopeId(planItemInstance.getId()).scopeType(ScopeTypes.CMMN).singleResult();
870872
if (task != null) {
871873
task.setScopeDefinitionId(caseDefinition.getId());
874+
PlanItemDefinition originalTaskDef = originalCmmnModel.findPlanItemDefinition(task.getTaskDefinitionKey());
875+
PlanItemDefinition targetTaskDef = targetCmmnModel.findPlanItemDefinition(task.getTaskDefinitionKey());
876+
if (originalTaskDef != null && targetTaskDef != null && originalTaskDef instanceof HumanTask && targetTaskDef instanceof HumanTask) {
877+
HumanTask originalHumanTask = (HumanTask) originalTaskDef;
878+
HumanTask targetHumanTask = (HumanTask) targetTaskDef;
879+
880+
if (taskPropertyValueIsDifferent(originalHumanTask.getName(), targetHumanTask.getName())) {
881+
task.setName(targetHumanTask.getName());
882+
}
883+
884+
if (taskPropertyValueIsDifferent(originalHumanTask.getFormKey(), targetHumanTask.getFormKey())) {
885+
task.setFormKey(targetHumanTask.getFormKey());
886+
}
887+
888+
if (taskPropertyValueIsDifferent(originalHumanTask.getCategory(), targetHumanTask.getCategory())) {
889+
task.setCategory(targetHumanTask.getCategory());
890+
}
891+
892+
if (taskPropertyValueIsDifferent(originalHumanTask.getDocumentation(), targetHumanTask.getDocumentation())) {
893+
task.setDescription(targetHumanTask.getDocumentation());
894+
}
895+
}
896+
897+
CmmnHistoryManager cmmnHistoryManager = cmmnEngineConfiguration.getCmmnHistoryManager();
898+
cmmnHistoryManager.recordTaskInfoChange(task, cmmnEngineConfiguration.getClock().getCurrentTime());
872899
}
873900
}
874901
}
@@ -1334,4 +1361,8 @@ protected <T extends PlanItemDefinitionMapping> boolean evaluateCondition(Variab
13341361
return true;
13351362
}
13361363

1364+
protected boolean taskPropertyValueIsDifferent(String originalValue, String targetValue) {
1365+
return (StringUtils.isNotEmpty(originalValue) && !originalValue.equals(targetValue)) ||
1366+
(StringUtils.isEmpty(originalValue) && StringUtils.isNotEmpty(targetValue));
1367+
}
13371368
}

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

+147
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,67 @@ void withSimpleOneTaskCaseIntroducingNewTaskWithSentryLinkedToFirstTask() {
378378
}
379379
}
380380
}
381+
382+
@Test
383+
void withSimpleOneTaskCaseChangingOnlyTaskProperties() {
384+
// Arrange
385+
deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/one-task.cmmn.xml");
386+
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("testCase").start();
387+
CaseDefinition destinationDefinition = deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/one-task-new-properties.cmmn.xml");
388+
389+
// Act
390+
cmmnMigrationService.createCaseInstanceMigrationBuilder()
391+
.migrateToCaseDefinition(destinationDefinition.getId())
392+
.migrate(caseInstance.getId());
393+
394+
// Assert
395+
CaseInstance caseInstanceAfterMigration = cmmnRuntimeService.createCaseInstanceQuery()
396+
.caseInstanceId(caseInstance.getId())
397+
.singleResult();
398+
assertThat(caseInstanceAfterMigration.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
399+
List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
400+
.caseInstanceId(caseInstance.getId())
401+
.list();
402+
assertThat(planItemInstances).hasSize(1);
403+
Map<String, List<PlanItemInstance>> planItemsByElementId = planItemInstances.stream()
404+
.collect(Collectors.groupingBy(PlanItemInstance::getElementId));
405+
PlanItemInstance planItem1 = planItemsByElementId.get("planItem1").get(0);
406+
assertThat(planItem1.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
407+
assertThat(planItem1.getName()).isEqualTo("Task 1");
408+
assertThat(planItem1.getState()).isEqualTo(PlanItemInstanceState.ACTIVE);
409+
410+
Task task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).singleResult();
411+
assertThat(task.getTaskDefinitionKey()).isEqualTo("humanTask1");
412+
assertThat(task.getName()).isEqualTo("Task 2");
413+
assertThat(task.getFormKey()).isEqualTo("myForm");
414+
assertThat(task.getCategory()).isEqualTo("myCategory");
415+
assertThat(task.getDescription()).isEqualTo("Example description");
416+
assertThat(task.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
417+
cmmnTaskService.complete(task.getId());
418+
419+
assertThat(cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isZero();
420+
421+
if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) {
422+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isEqualTo(1);
423+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).singleResult().getCaseDefinitionId())
424+
.isEqualTo(destinationDefinition.getId());
425+
426+
List<HistoricPlanItemInstance> historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery()
427+
.planItemInstanceCaseInstanceId(caseInstance.getId()).list();
428+
assertThat(historicPlanItemInstances).hasSize(1);
429+
assertThat(historicPlanItemInstances.get(0).getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
430+
431+
List<HistoricTaskInstance> historicTasks = cmmnHistoryService.createHistoricTaskInstanceQuery().caseInstanceId(caseInstance.getId()).list();
432+
assertThat(historicTasks).hasSize(1);
433+
for (HistoricTaskInstance historicTask : historicTasks) {
434+
assertThat(historicTask.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
435+
assertThat(historicTask.getName()).isEqualTo("Task 2");
436+
assertThat(historicTask.getFormKey()).isEqualTo("myForm");
437+
assertThat(historicTask.getCategory()).isEqualTo("myCategory");
438+
assertThat(historicTask.getDescription()).isEqualTo("Example description");
439+
}
440+
}
441+
}
381442

382443
@Test
383444
void withTwoTasksIntroducingANewStageAroundSecondTask() {
@@ -488,6 +549,92 @@ void withTwoTasksIntroducingANewStageAroundSecondTaskAndSecondTaskActive() {
488549
assertThat(planItem3.getPlanItemDefinitionId()).isEqualTo("expandedStage1");
489550
assertThat(planItem3.getState()).isEqualTo(PlanItemInstanceState.ACTIVE);
490551
}
552+
553+
@Test
554+
void withTwoTasksCaseChangingTaskProperties() {
555+
// Arrange
556+
deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/one-task.cmmn.xml");
557+
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("testCase").start();
558+
CaseDefinition destinationDefinition = deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/two-task-new-properties.cmmn.xml");
559+
560+
// Act
561+
cmmnMigrationService.createCaseInstanceMigrationBuilder()
562+
.migrateToCaseDefinition(destinationDefinition.getId())
563+
.addActivatePlanItemDefinitionMapping(PlanItemDefinitionMappingBuilder.createActivatePlanItemDefinitionMappingFor("humanTask2"))
564+
.migrate(caseInstance.getId());
565+
566+
// Assert
567+
CaseInstance caseInstanceAfterMigration = cmmnRuntimeService.createCaseInstanceQuery()
568+
.caseInstanceId(caseInstance.getId())
569+
.singleResult();
570+
assertThat(caseInstanceAfterMigration.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
571+
List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
572+
.caseInstanceId(caseInstance.getId())
573+
.list();
574+
assertThat(planItemInstances).hasSize(2);
575+
Map<String, List<PlanItemInstance>> planItemsByElementId = planItemInstances.stream()
576+
.collect(Collectors.groupingBy(PlanItemInstance::getElementId));
577+
PlanItemInstance planItem1 = planItemsByElementId.get("planItem1").get(0);
578+
assertThat(planItem1.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
579+
assertThat(planItem1.getName()).isEqualTo("Task 1");
580+
assertThat(planItem1.getState()).isEqualTo(PlanItemInstanceState.ACTIVE);
581+
582+
Task task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("humanTask1").singleResult();
583+
assertThat(task.getTaskDefinitionKey()).isEqualTo("humanTask1");
584+
assertThat(task.getName()).isEqualTo("Task 2");
585+
assertThat(task.getFormKey()).isEqualTo("myForm");
586+
assertThat(task.getCategory()).isEqualTo("myCategory");
587+
assertThat(task.getDescription()).isEqualTo("Example description");
588+
assertThat(task.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
589+
cmmnTaskService.complete(task.getId());
590+
591+
PlanItemInstance planItem2 = planItemsByElementId.get("planItem2").get(0);
592+
assertThat(planItem2.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
593+
assertThat(planItem2.getName()).isEqualTo("Task 3");
594+
assertThat(planItem2.getState()).isEqualTo(PlanItemInstanceState.ACTIVE);
595+
596+
task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).singleResult();
597+
assertThat(task.getTaskDefinitionKey()).isEqualTo("humanTask2");
598+
assertThat(task.getName()).isEqualTo("Task 3");
599+
assertThat(task.getFormKey()).isEqualTo("myForm2");
600+
assertThat(task.getCategory()).isEqualTo("myCategory2");
601+
assertThat(task.getDescription()).isEqualTo("Example description2");
602+
assertThat(task.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
603+
cmmnTaskService.complete(task.getId());
604+
605+
assertThat(cmmnRuntimeService.createCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isZero();
606+
607+
if (CmmnHistoryTestHelper.isHistoryLevelAtLeast(HistoryLevel.ACTIVITY, cmmnEngineConfiguration)) {
608+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).count()).isEqualTo(1);
609+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery().caseInstanceId(caseInstance.getId()).singleResult().getCaseDefinitionId())
610+
.isEqualTo(destinationDefinition.getId());
611+
612+
List<HistoricPlanItemInstance> historicPlanItemInstances = cmmnHistoryService.createHistoricPlanItemInstanceQuery()
613+
.planItemInstanceCaseInstanceId(caseInstance.getId()).list();
614+
assertThat(historicPlanItemInstances).hasSize(2);
615+
assertThat(historicPlanItemInstances.get(0).getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
616+
assertThat(historicPlanItemInstances.get(1).getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
617+
618+
List<HistoricTaskInstance> historicTasks = cmmnHistoryService.createHistoricTaskInstanceQuery().caseInstanceId(caseInstance.getId()).list();
619+
assertThat(historicTasks).hasSize(2);
620+
for (HistoricTaskInstance historicTask : historicTasks) {
621+
assertThat(historicTask.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
622+
623+
if ("humanTask1".equals(historicTask.getTaskDefinitionKey())) {
624+
assertThat(historicTask.getName()).isEqualTo("Task 2");
625+
assertThat(historicTask.getFormKey()).isEqualTo("myForm");
626+
assertThat(historicTask.getCategory()).isEqualTo("myCategory");
627+
assertThat(historicTask.getDescription()).isEqualTo("Example description");
628+
629+
} else {
630+
assertThat(historicTask.getName()).isEqualTo("Task 3");
631+
assertThat(historicTask.getFormKey()).isEqualTo("myForm2");
632+
assertThat(historicTask.getCategory()).isEqualTo("myCategory2");
633+
assertThat(historicTask.getDescription()).isEqualTo("Example description2");
634+
}
635+
}
636+
}
637+
}
491638

492639
@Test
493640
void withSimpleOneTaskCaseIntroducingNewTaskWithConditionalSentryNotActivated() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL" xmlns:flowable="http://flowable.org/cmmn"
3+
targetNamespace="http://flowable.org/cmmn">
4+
<case id="testCase" name="One Task Test Case" flowable:initiatorVariableName="initiator"
5+
flowable:candidateStarterGroups="flowableUser">
6+
<casePlanModel id="onecaseplanmodel1" name="Case plan model" flowable:formFieldValidation="false">
7+
<planItem id="planItem1" name="Task 1" definitionRef="humanTask1"/>
8+
<humanTask id="humanTask1" name="Task 2" flowable:formKey="myForm" flowable:category="myCategory">
9+
<documentation>Example description</documentation>
10+
</humanTask>
11+
</casePlanModel>
12+
</case>
13+
</definitions>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
3+
xmlns:flowable="http://flowable.org/cmmn"
4+
targetNamespace="http://flowable.org/cmmn">
5+
<case id="testCase" name="Two Task Test Case" flowable:initiatorVariableName="initiator"
6+
flowable:candidateStarterGroups="flowableUser">
7+
<casePlanModel id="onecaseplanmodel1" name="Case plan model">
8+
<planItem id="planItem1" name="Task 1" definitionRef="humanTask1"/>
9+
<planItem id="planItem2" name="Task 3" definitionRef="humanTask2"/>
10+
<humanTask id="humanTask1" name="Task 2" flowable:formKey="myForm" flowable:category="myCategory">
11+
<documentation>Example description</documentation>
12+
</humanTask>
13+
<humanTask id="humanTask2" name="Task 3" flowable:formKey="myForm2" flowable:category="myCategory2">
14+
<documentation>Example description2</documentation>
15+
</humanTask>
16+
</casePlanModel>
17+
</case>
18+
</definitions>

0 commit comments

Comments
 (0)