提交 0d0727d9 编写于 作者: M martin.grofcik

ACT-1822

MultiInstance loopIndexVariable support
上级 a2670ade
......@@ -133,6 +133,7 @@ public interface BpmnXMLConstants {
public static final String ATTRIBUTE_MULTIINSTANCE_SEQUENTIAL = "isSequential";
public static final String ATTRIBUTE_MULTIINSTANCE_COLLECTION = "collection";
public static final String ATTRIBUTE_MULTIINSTANCE_VARIABLE = "elementVariable";
public static final String ATTRIBUTE_MULTIINSTANCE_INDEX_VARIABLE = "elementIndexVariable";
public static final String ATTRIBUTE_TASK_IMPLEMENTATION = "implementation";
public static final String ATTRIBUTE_TASK_OPERATION_REF = "operationRef";
......
......@@ -39,6 +39,7 @@ public class MultiInstanceParser extends BaseChildElementParser {
}
multiInstanceDef.setInputDataItem(xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_MULTIINSTANCE_COLLECTION));
multiInstanceDef.setElementVariable(xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_MULTIINSTANCE_VARIABLE));
multiInstanceDef.setElementIndexVariable(xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_MULTIINSTANCE_INDEX_VARIABLE));
boolean readyWithMultiInstance = false;
try {
......
......@@ -21,6 +21,7 @@ public class MultiInstanceLoopCharacteristics extends BaseElement {
protected String loopCardinality;
protected String completionCondition;
protected String elementVariable;
protected String elementIndexVariable;
protected boolean sequential;
public String getInputDataItem() {
......@@ -47,6 +48,12 @@ public class MultiInstanceLoopCharacteristics extends BaseElement {
public void setElementVariable(String elementVariable) {
this.elementVariable = elementVariable;
}
public String getElementIndexVariable() {
return elementIndexVariable;
}
public void setElementIndexVariable(String elementIndexVariable) {
this.elementIndexVariable = elementIndexVariable;
}
public boolean isSequential() {
return sequential;
}
......
......@@ -60,9 +60,6 @@ public abstract class MultiInstanceActivityBehavior extends FlowNodeActivityBeha
protected final String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
protected final String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
// Variable names for inner instances (as described in the spec)
protected final String LOOP_COUNTER = "loopCounter";
// Instance members
protected ActivityImpl activity;
protected AbstractBpmnActivityBehavior innerActivityBehavior;
......@@ -71,6 +68,8 @@ public abstract class MultiInstanceActivityBehavior extends FlowNodeActivityBeha
protected Expression collectionExpression;
protected String collectionVariable;
protected String collectionElementVariable;
// default variable name for loop counter for inner instances (as described in the spec)
protected String collectionElementIndexVariable="loopCounter";
/**
* @param innerActivityBehavior The original {@link ActivityBehavior} of the activity
......@@ -84,7 +83,7 @@ public abstract class MultiInstanceActivityBehavior extends FlowNodeActivityBeha
}
public void execute(ActivityExecution execution) throws Exception {
if (getLocalLoopVariable(execution, LOOP_COUNTER) == null) {
if (getLocalLoopVariable(execution, getCollectionElementIndexVariable()) == null) {
try {
createInstances(execution);
} catch (BpmnError error) {
......@@ -291,6 +290,12 @@ public abstract class MultiInstanceActivityBehavior extends FlowNodeActivityBeha
public void setCollectionElementVariable(String collectionElementVariable) {
this.collectionElementVariable = collectionElementVariable;
}
public String getCollectionElementIndexVariable() {
return collectionElementIndexVariable;
}
public void setCollectionElementIndexVariable(String collectionElementIndexVariable) {
this.collectionElementIndexVariable = collectionElementIndexVariable;
}
public void setInnerActivityBehavior(AbstractBpmnActivityBehavior innerActivityBehavior) {
this.innerActivityBehavior = innerActivityBehavior;
this.innerActivityBehavior.setMultiInstanceActivityBehavior(this);
......
......@@ -78,7 +78,7 @@ public class ParallelMultiInstanceBehavior extends MultiInstanceActivityBehavior
if (concurrentExecution.isActive() && !concurrentExecution.isEnded()
&& concurrentExecution.getParent().isActive()
&& !concurrentExecution.getParent().isEnded()) {
setLoopVariable(concurrentExecution, LOOP_COUNTER, loopCounter);
setLoopVariable(concurrentExecution, getCollectionElementIndexVariable(), loopCounter);
executeOriginalBehavior(concurrentExecution, loopCounter);
}
}
......@@ -101,7 +101,7 @@ public class ParallelMultiInstanceBehavior extends MultiInstanceActivityBehavior
public void leave(ActivityExecution execution) {
callActivityEndListeners(execution);
int loopCounter = getLoopVariable(execution, LOOP_COUNTER);
int loopCounter = getLoopVariable(execution, getCollectionElementIndexVariable());
int nrOfInstances = getLoopVariable(execution, NUMBER_OF_INSTANCES);
int nrOfCompletedInstances = getLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES) + 1;
int nrOfActiveInstances = getLoopVariable(execution, NUMBER_OF_ACTIVE_INSTANCES) - 1;
......
......@@ -43,7 +43,7 @@ public class SequentialMultiInstanceBehavior extends MultiInstanceActivityBehavi
setLoopVariable(execution, NUMBER_OF_INSTANCES, nrOfInstances);
setLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES, 0);
setLoopVariable(execution, LOOP_COUNTER, 0);
setLoopVariable(execution, getCollectionElementIndexVariable(), 0);
setLoopVariable(execution, NUMBER_OF_ACTIVE_INSTANCES, 1);
logLoopDetails(execution, "initialized", 0, 0, 1, nrOfInstances);
......@@ -58,12 +58,12 @@ public class SequentialMultiInstanceBehavior extends MultiInstanceActivityBehavi
public void leave(ActivityExecution execution) {
callActivityEndListeners(execution);
int loopCounter = getLoopVariable(execution, LOOP_COUNTER) + 1;
int loopCounter = getLoopVariable(execution, getCollectionElementIndexVariable()) + 1;
int nrOfInstances = getLoopVariable(execution, NUMBER_OF_INSTANCES);
int nrOfCompletedInstances = getLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES) + 1;
int nrOfActiveInstances = getLoopVariable(execution, NUMBER_OF_ACTIVE_INSTANCES);
setLoopVariable(execution, LOOP_COUNTER, loopCounter);
setLoopVariable(execution, getCollectionElementIndexVariable(), loopCounter);
setLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES, nrOfCompletedInstances);
logLoopDetails(execution, "instance completed", loopCounter, nrOfCompletedInstances, nrOfActiveInstances, nrOfInstances);
......
......@@ -91,6 +91,11 @@ public abstract class AbstractActivityBpmnParseHandler<T extends FlowNode> exten
miActivityBehavior.setCollectionElementVariable(loopCharacteristics.getElementVariable());
}
// activiti:elementIndexVariable
if (StringUtils.isNotEmpty(loopCharacteristics.getElementIndexVariable())) {
miActivityBehavior.setCollectionElementIndexVariable(loopCharacteristics.getElementIndexVariable());
}
// Validation
if (miActivityBehavior.getLoopCardinalityExpression() == null && miActivityBehavior.getCollectionExpression() == null
&& miActivityBehavior.getCollectionVariable() == null) {
......
......@@ -43,7 +43,16 @@ public class MultiInstanceTest extends PluggableActivitiTestCase {
@Deployment(resources = {"org/activiti/engine/test/bpmn/multiinstance/MultiInstanceTest.sequentialUserTasks.bpmn20.xml"})
public void testSequentialUserTasks() {
String procId = runtimeService.startProcessInstanceByKey("miSequentialUserTasks",
checkSequentialUserTasks("miSequentialUserTasks");
}
@Deployment
public void testSequentialUserTasksCustomExtensions() {
checkSequentialUserTasks("miSequentialUserTasksCustomExtensions");
}
private void checkSequentialUserTasks(String processDefinitionKey) {
String procId = runtimeService.startProcessInstanceByKey(processDefinitionKey,
CollectionUtil.singletonMap("nrOfLoops", 3)).getId();
Task task = taskService.createTaskQuery().singleResult();
......@@ -240,16 +249,37 @@ public class MultiInstanceTest extends PluggableActivitiTestCase {
@Deployment
public void testParallelUserTasksCustomExtensions() {
checkParallelUserTasksCustomExtensions("miParallelUserTasks");
}
@Deployment
public void testParallelUserTasksCustomExtensionsLoopIndexVariable() {
checkParallelUserTasksCustomExtensions("miParallelUserTasksLoopVariable");
}
private void checkParallelUserTasksCustomExtensions(String processDefinitionKey) {
Map<String, Object> vars = new HashMap<String, Object>();
List<String> assigneeList = Arrays.asList("kermit", "gonzo", "fozzie");
vars.put("assigneeList", assigneeList);
runtimeService.startProcessInstanceByKey("miSequentialUserTasks", vars);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, vars);
for (String assignee : assigneeList) {
Task task = taskService.createTaskQuery().singleResult();
assertEquals(assignee, task.getAssignee());
taskService.complete(task.getId());
}
List<Task> tasks = taskService.createTaskQuery().orderByTaskName().asc().list();
assertEquals(3, tasks.size());
assertEquals("My Task 0", tasks.get(0).getName());
assertEquals("My Task 1", tasks.get(1).getName());
assertEquals("My Task 2", tasks.get(2).getName());
tasks = taskService.createTaskQuery().orderByTaskAssignee().asc().list();
assertEquals("fozzie", tasks.get(0).getAssignee());
assertEquals("gonzo", tasks.get(1).getAssignee());
assertEquals("kermit", tasks.get(2).getAssignee());
// Completing 3 tasks will trigger completioncondition
taskService.complete(tasks.get(0).getId());
taskService.complete(tasks.get(1).getId());
taskService.complete(tasks.get(2).getId());
assertEquals(0, taskService.createTaskQuery().count());
assertProcessEnded(processInstance.getProcessInstanceId());
}
@Deployment
......
......@@ -5,13 +5,13 @@
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="miSequentialUserTasks">
<process id="miParallelUserTasks">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="miTasks" />
<userTask id="miTasks" name="My Task ${loopCounter}" activiti:assignee="${assignee}">
<multiInstanceLoopCharacteristics isSequential="true"
<multiInstanceLoopCharacteristics isSequential="false"
activiti:collection="assigneeList" activiti:elementVariable="assignee">
</multiInstanceLoopCharacteristics>
</userTask>
......
<?xml version="1.0" encoding="UTF-8"?>
<definitions id="definition"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="miParallelUserTasksLoopVariable">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="miTasks" />
<userTask id="miTasks" name="My Task ${loopValueIndex}" activiti:assignee="${assignee}" >
<multiInstanceLoopCharacteristics isSequential="false"
activiti:collection="assigneeList" activiti:elementVariable="assignee"
activiti:elementIndexVariable="loopValueIndex"/>
</userTask>
<sequenceFlow id="flow3" sourceRef="miTasks" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<definitions id="definition"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="Examples">
<process id="miSequentialUserTasksCustomExtensions">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="miTasks" />
<userTask id="miTasks" name="My Task" activiti:assignee="kermit_${loopValueIndex}">
<multiInstanceLoopCharacteristics isSequential="true" activiti:elementIndexVariable="loopValueIndex">
<loopCardinality>${nrOfLoops}</loopCardinality>
<completionCondition>${nrOfCompletedInstances == 5}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>
<sequenceFlow id="flow4" sourceRef="miTasks" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
\ No newline at end of file
......@@ -4835,7 +4835,8 @@ public class MyTaskCreateListener implements TaskListener {
Additionally, each of the created executions will have an execution-local variable (i.e. not visible
for the other executions, and not stored on process instance level) :
<itemizedlist>
<listitem><para><emphasis role="bold">loopCounter</emphasis>: indicates the <emphasis>index in the for-each loop</emphasis> of that particular instance.</para></listitem>
<listitem><para><emphasis role="bold">loopCounter</emphasis>: indicates the <emphasis>index in the for-each loop</emphasis> of that particular instance. loopCounter variable can be renamed by activiti
<emphasis role="bold">elementIndexVariable</emphasis> attribute.</para></listitem>
</itemizedlist>
</para>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册