Skip to content

Commit

Permalink
Update task properties, when changed, for case instance migration
Browse files Browse the repository at this point in the history
  • Loading branch information
tijsrademakers committed Aug 27, 2024
1 parent f344a93 commit afcbcac
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ protected void doMovePlanItemState(CaseInstanceChangeState caseInstanceChangeSta

executeChangePlanItemDefinitionWithNewTargetIds(caseInstanceChangeState, originalCaseDefinitionId, commandContext);

navigatePlanItemInstances(currentPlanItemInstances, caseInstanceChangeState.getCaseDefinitionToMigrateTo());
navigatePlanItemInstances(currentPlanItemInstances, caseInstanceChangeState.getCaseDefinitionToMigrateTo(), originalCaseDefinitionId);

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

protected void navigatePlanItemInstances(Map<String, List<PlanItemInstanceEntity>> stagesByPlanItemDefinitionId, CaseDefinition caseDefinition) {
protected void navigatePlanItemInstances(Map<String, List<PlanItemInstanceEntity>> stagesByPlanItemDefinitionId, CaseDefinition caseDefinition, String originalCaseDefinitionId) {
if (caseDefinition != null) {
TaskService taskService = cmmnEngineConfiguration.getTaskServiceConfiguration().getTaskService();
CmmnModel originalCmmnModel = CaseDefinitionUtil.getCmmnModel(originalCaseDefinitionId);
CmmnModel targetCmmnModel = CaseDefinitionUtil.getCmmnModel(caseDefinition.getId());
for (List<PlanItemInstanceEntity> planItemInstances : stagesByPlanItemDefinitionId.values()) {
for (PlanItemInstanceEntity planItemInstance : planItemInstances) {

Expand All @@ -869,6 +871,31 @@ protected void navigatePlanItemInstances(Map<String, List<PlanItemInstanceEntity
.subScopeId(planItemInstance.getId()).scopeType(ScopeTypes.CMMN).singleResult();
if (task != null) {
task.setScopeDefinitionId(caseDefinition.getId());
PlanItemDefinition originalTaskDef = originalCmmnModel.findPlanItemDefinition(task.getTaskDefinitionKey());
PlanItemDefinition targetTaskDef = targetCmmnModel.findPlanItemDefinition(task.getTaskDefinitionKey());
if (originalTaskDef != null && targetTaskDef != null && originalTaskDef instanceof HumanTask && targetTaskDef instanceof HumanTask) {
HumanTask originalHumanTask = (HumanTask) originalTaskDef;
HumanTask targetHumanTask = (HumanTask) targetTaskDef;

if (taskPropertyValueIsDifferent(originalHumanTask.getName(), targetHumanTask.getName())) {
task.setName(targetHumanTask.getName());
}

if (taskPropertyValueIsDifferent(originalHumanTask.getFormKey(), targetHumanTask.getFormKey())) {
task.setFormKey(targetHumanTask.getFormKey());
}

if (taskPropertyValueIsDifferent(originalHumanTask.getCategory(), targetHumanTask.getCategory())) {
task.setCategory(targetHumanTask.getCategory());
}

if (taskPropertyValueIsDifferent(originalHumanTask.getDocumentation(), targetHumanTask.getDocumentation())) {
task.setDescription(targetHumanTask.getDocumentation());
}
}

CmmnHistoryManager cmmnHistoryManager = cmmnEngineConfiguration.getCmmnHistoryManager();
cmmnHistoryManager.recordTaskInfoChange(task, cmmnEngineConfiguration.getClock().getCurrentTime());
}
}
}
Expand Down Expand Up @@ -1334,4 +1361,8 @@ protected <T extends PlanItemDefinitionMapping> boolean evaluateCondition(Variab
return true;
}

protected boolean taskPropertyValueIsDifferent(String originalValue, String targetValue) {
return (StringUtils.isNotEmpty(originalValue) && !originalValue.equals(targetValue)) ||
(StringUtils.isEmpty(originalValue) && StringUtils.isNotEmpty(targetValue));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,67 @@ void withSimpleOneTaskCaseIntroducingNewTaskWithSentryLinkedToFirstTask() {
}
}
}

@Test
void withSimpleOneTaskCaseChangingOnlyTaskProperties() {
// Arrange
deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/one-task.cmmn.xml");
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder().caseDefinitionKey("testCase").start();
CaseDefinition destinationDefinition = deployCaseDefinition("test1", "org/flowable/cmmn/test/migration/one-task-new-properties.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());
List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
.caseInstanceId(caseInstance.getId())
.list();
assertThat(planItemInstances).hasSize(1);
Map<String, List<PlanItemInstance>> planItemsByElementId = planItemInstances.stream()
.collect(Collectors.groupingBy(PlanItemInstance::getElementId));
PlanItemInstance planItem1 = planItemsByElementId.get("planItem1").get(0);
assertThat(planItem1.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
assertThat(planItem1.getName()).isEqualTo("Task 1");
assertThat(planItem1.getState()).isEqualTo(PlanItemInstanceState.ACTIVE);

Task task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).singleResult();
assertThat(task.getTaskDefinitionKey()).isEqualTo("humanTask1");
assertThat(task.getName()).isEqualTo("Task 2");
assertThat(task.getFormKey()).isEqualTo("myForm");
assertThat(task.getCategory()).isEqualTo("myCategory");
assertThat(task.getDescription()).isEqualTo("Example description");
assertThat(task.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
cmmnTaskService.complete(task.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(1);
assertThat(historicPlanItemInstances.get(0).getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());

List<HistoricTaskInstance> historicTasks = cmmnHistoryService.createHistoricTaskInstanceQuery().caseInstanceId(caseInstance.getId()).list();
assertThat(historicTasks).hasSize(1);
for (HistoricTaskInstance historicTask : historicTasks) {
assertThat(historicTask.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
assertThat(historicTask.getName()).isEqualTo("Task 2");
assertThat(historicTask.getFormKey()).isEqualTo("myForm");
assertThat(historicTask.getCategory()).isEqualTo("myCategory");
assertThat(historicTask.getDescription()).isEqualTo("Example description");
}
}
}

@Test
void withTwoTasksIntroducingANewStageAroundSecondTask() {
Expand Down Expand Up @@ -488,6 +549,92 @@ void withTwoTasksIntroducingANewStageAroundSecondTaskAndSecondTaskActive() {
assertThat(planItem3.getPlanItemDefinitionId()).isEqualTo("expandedStage1");
assertThat(planItem3.getState()).isEqualTo(PlanItemInstanceState.ACTIVE);
}

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

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

// Assert
CaseInstance caseInstanceAfterMigration = cmmnRuntimeService.createCaseInstanceQuery()
.caseInstanceId(caseInstance.getId())
.singleResult();
assertThat(caseInstanceAfterMigration.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
List<PlanItemInstance> planItemInstances = cmmnRuntimeService.createPlanItemInstanceQuery()
.caseInstanceId(caseInstance.getId())
.list();
assertThat(planItemInstances).hasSize(2);
Map<String, List<PlanItemInstance>> planItemsByElementId = planItemInstances.stream()
.collect(Collectors.groupingBy(PlanItemInstance::getElementId));
PlanItemInstance planItem1 = planItemsByElementId.get("planItem1").get(0);
assertThat(planItem1.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
assertThat(planItem1.getName()).isEqualTo("Task 1");
assertThat(planItem1.getState()).isEqualTo(PlanItemInstanceState.ACTIVE);

Task task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).taskDefinitionKey("humanTask1").singleResult();
assertThat(task.getTaskDefinitionKey()).isEqualTo("humanTask1");
assertThat(task.getName()).isEqualTo("Task 2");
assertThat(task.getFormKey()).isEqualTo("myForm");
assertThat(task.getCategory()).isEqualTo("myCategory");
assertThat(task.getDescription()).isEqualTo("Example description");
assertThat(task.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
cmmnTaskService.complete(task.getId());

PlanItemInstance planItem2 = planItemsByElementId.get("planItem2").get(0);
assertThat(planItem2.getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
assertThat(planItem2.getName()).isEqualTo("Task 3");
assertThat(planItem2.getState()).isEqualTo(PlanItemInstanceState.ACTIVE);

task = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).singleResult();
assertThat(task.getTaskDefinitionKey()).isEqualTo("humanTask2");
assertThat(task.getName()).isEqualTo("Task 3");
assertThat(task.getFormKey()).isEqualTo("myForm2");
assertThat(task.getCategory()).isEqualTo("myCategory2");
assertThat(task.getDescription()).isEqualTo("Example description2");
assertThat(task.getScopeDefinitionId()).isEqualTo(destinationDefinition.getId());
cmmnTaskService.complete(task.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);
assertThat(historicPlanItemInstances.get(0).getCaseDefinitionId()).isEqualTo(destinationDefinition.getId());
assertThat(historicPlanItemInstances.get(1).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());

if ("humanTask1".equals(historicTask.getTaskDefinitionKey())) {
assertThat(historicTask.getName()).isEqualTo("Task 2");
assertThat(historicTask.getFormKey()).isEqualTo("myForm");
assertThat(historicTask.getCategory()).isEqualTo("myCategory");
assertThat(historicTask.getDescription()).isEqualTo("Example description");

} else {
assertThat(historicTask.getName()).isEqualTo("Task 3");
assertThat(historicTask.getFormKey()).isEqualTo("myForm2");
assertThat(historicTask.getCategory()).isEqualTo("myCategory2");
assertThat(historicTask.getDescription()).isEqualTo("Example description2");
}
}
}
}

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

0 comments on commit afcbcac

Please sign in to comment.