Author: kukeltje
Date: 2009-07-30 07:07:13 -0400 (Thu, 30 Jul 2009)
New Revision: 5388
Modified:
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/ParallelGatewayActivity.java
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/ParallelGatewayBinding.java
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/TaskActivity.java
jbpm4/trunk/modules/bpmn/src/test/java/org/jbpm/bpmn/flownodes/ParallelGatewayTest.java
jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/parallelGateway.bpmn.xml
Log:
ParallelGateway activity implemented, execution test made and gren light for uncontrolled
flow test
Modified:
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/ParallelGatewayActivity.java
===================================================================
---
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/ParallelGatewayActivity.java 2009-07-30
09:43:55 UTC (rev 5387)
+++
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/ParallelGatewayActivity.java 2009-07-30
11:07:13 UTC (rev 5388)
@@ -29,9 +29,11 @@
import org.jbpm.api.Execution;
import org.jbpm.api.JbpmException;
import org.jbpm.api.activity.ActivityExecution;
+import org.jbpm.bpmn.parser.BpmnParser;
import org.jbpm.internal.log.Log;
import org.jbpm.pvm.internal.env.Environment;
import org.jbpm.pvm.internal.model.Activity;
+import org.jbpm.pvm.internal.model.Condition;
import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.jbpm.pvm.internal.model.Transition;
@@ -40,12 +42,13 @@
*/
public class ParallelGatewayActivity extends BpmnActivity {
+ private static final Log log = Log.getLog(ParallelGatewayActivity.class.getName());
+
private static final long serialVersionUID = 1L;
int multiplicity = -1;
LockMode lockMode = LockMode.UPGRADE;
-
//GatewayDirection indicates fork (divergence) or join (convergence). Maybe two
different activities is better
private String gatewayDirection;
@@ -55,11 +58,73 @@
public void execute(ExecutionImpl execution) {
+ if ("diverging".equals(gatewayDirection)) {
+ log.debug("Forking parallel gateway");
+ fork(execution);
+ } else if ("converging".equals(gatewayDirection)) {
+ log.debug("Joining parallel gateway");
+ join(execution);
+ }
+ }
+
+ public void fork(ExecutionImpl execution) {
Activity activity = execution.getActivity();
+
+ // evaluate the conditions and find the transitions that should be forked
+ List<Transition> forkingTransitions = new ArrayList<Transition>();
+ List<Transition> outgoingTransitions = activity.getOutgoingTransitions();
+ for (Transition transition: outgoingTransitions) {
+ Condition condition = transition.getCondition();
+ if ( (condition==null)
+ || (condition.evaluate(execution))
+ ) {
+ forkingTransitions.add(transition);
+ }
+ }
+
+ // if no outgoing transitions should be forked,
+ if (forkingTransitions.size()==0) {
+ // end this execution
+ execution.end();
+
+ // if there is exactly 1 transition to be taken, just use the incoming execution
+ } else if (forkingTransitions.size()==1) {
+ execution.take(forkingTransitions.get(0));
+
+ // if there are more transitions
+ } else {
+ ExecutionImpl concurrentRoot = null;
+ if (Execution.STATE_ACTIVE_ROOT.equals(execution.getState())) {
+ concurrentRoot = execution;
+ execution.setState(Execution.STATE_INACTIVE_CONCURRENT_ROOT);
+ execution.setActivity(null);
+ } else if (Execution.STATE_ACTIVE_CONCURRENT.equals(execution.getState())) {
+ concurrentRoot = execution.getParent();
+ }
+
+ for (Transition transition: forkingTransitions) {
+ // launch a concurrent path of execution
+ String childExecutionName = transition.getName();
+ ExecutionImpl concurrentExecution =
concurrentRoot.createExecution(childExecutionName);
+ concurrentExecution.setActivity(activity);
+ concurrentExecution.setState(Execution.STATE_ACTIVE_CONCURRENT);
+ concurrentExecution.take(transition);
+
+ if (concurrentRoot.isEnded()) {
+ break;
+ }
+ }
+ }
+ }
+
+ private void join(ExecutionImpl execution) {
+ Activity activity = execution.getActivity();
+
// if this is a single, non concurrent root
if (Execution.STATE_ACTIVE_ROOT.equals(execution.getState())) {
// just pass through
+
Transition transition = activity.getDefaultOutgoingTransition();
if (transition==null) {
throw new JbpmException("join must have an outgoing transition");
@@ -67,7 +132,7 @@
execution.take(transition);
} else if (Execution.STATE_ACTIVE_CONCURRENT.equals(execution.getState())) {
-
+
// force version increment in the parent execution
Session session = Environment.getFromCurrent(Session.class);
session.lock(execution.getParent(), lockMode);
Modified:
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/ParallelGatewayBinding.java
===================================================================
---
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/ParallelGatewayBinding.java 2009-07-30
09:43:55 UTC (rev 5387)
+++
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/ParallelGatewayBinding.java 2009-07-30
11:07:13 UTC (rev 5388)
@@ -75,6 +75,8 @@
return null;
}
- return new ParallelGatewayActivity();
+ ParallelGatewayActivity parallelGatewayActivity = new ParallelGatewayActivity();
+ parallelGatewayActivity.setGatewayDirection(gatewayDirection);
+ return parallelGatewayActivity;
}
}
Modified:
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/TaskActivity.java
===================================================================
---
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/TaskActivity.java 2009-07-30
09:43:55 UTC (rev 5387)
+++
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/TaskActivity.java 2009-07-30
11:07:13 UTC (rev 5388)
@@ -86,6 +86,7 @@
// if there are more transitions
} else {
+ log.debug("forking more");
ExecutionImpl concurrentRoot = null;
if (Execution.STATE_ACTIVE_ROOT.equals(execution.getState())) {
concurrentRoot = execution;
Modified:
jbpm4/trunk/modules/bpmn/src/test/java/org/jbpm/bpmn/flownodes/ParallelGatewayTest.java
===================================================================
---
jbpm4/trunk/modules/bpmn/src/test/java/org/jbpm/bpmn/flownodes/ParallelGatewayTest.java 2009-07-30
09:43:55 UTC (rev 5387)
+++
jbpm4/trunk/modules/bpmn/src/test/java/org/jbpm/bpmn/flownodes/ParallelGatewayTest.java 2009-07-30
11:07:13 UTC (rev 5388)
@@ -25,6 +25,7 @@
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.TaskQuery;
+import org.jbpm.api.history.HistoryProcessInstance;
import org.jbpm.api.task.Task;
import org.jbpm.bpmn.model.BpmnProcessDefinition;
import org.jbpm.bpmn.parser.BpmnParser;
@@ -48,7 +49,7 @@
return problems;
}
- public void testNormal() {
+ public void testNormalParse() {
List<Problem> problems =
parse("org/jbpm/bpmn/flownodes/parallelGateway.bpmn.xml");
@@ -57,6 +58,49 @@
}
}
+ public void testNormalExecute() {
+
+ String deploymentId =
repositoryService.createDeployment().addResourceFromClasspath("org/jbpm/bpmn/flownodes/parallelGateway.bpmn.xml").deploy();
+
+ try {
+ ProcessInstance pi =
executionService.startProcessInstanceByKey("ParallelGateway");
+
+ String pid = pi.getId();
+
+ TaskQuery taskQuery = taskService.createTaskQuery();
+ List<Task> allTasks = taskQuery.list();
+
+ // since the uncontrolled sequence flow OUT of the activity behaves as a fork
+ // we now have two tasks
+ assertEquals(2, allTasks.size());
+ assertEquals("UserTaskLeg1", allTasks.get(0).getActivityName());
+ assertEquals("UserTaskLeg2", allTasks.get(1).getActivityName());
+
+ // specifying a transition is unnecessary, BPMN has outgoing AND semantic!
+ // TODO: fix
+ // Currently not passing any 'outcome'
+ taskService.completeTask( allTasks.get(0).getId());
+
+ pi = executionService.findProcessInstanceById(pid);
+ // process instance should not be ended yet
+ assertNotNull(pi);
+
+ taskService.completeTask( allTasks.get(1).getId());
+
+ assertEquals(0, taskQuery.list().size());
+
+ pi = executionService.findProcessInstanceById(pid);
+ // process instance is ended
+ assertNull(pi);
+
+ }
+ finally {
+ repositoryService.deleteDeploymentCascade(deploymentId);
+ }
+ }
+
+
+
public void testInvalid() {
List<Problem> problems =
parse("org/jbpm/bpmn/flownodes/parallelGatewayInvalid.bpmn.xml");
@@ -73,6 +117,8 @@
try {
ProcessInstance pi =
executionService.startProcessInstanceByKey("ForkWithUncontrolledSequenceFlowProcess");
+ String pid = pi.getId();
+
TaskQuery taskQuery = taskService.createTaskQuery();
List<Task> allTasks = taskQuery.list();
@@ -81,43 +127,24 @@
assertEquals(2, allTasks.size());
assertEquals("UserTaskLeg1", allTasks.get(0).getActivityName());
assertEquals("UserTaskLeg2", allTasks.get(1).getActivityName());
-// assertEquals("UserTask", allTasks.get(0));
-//
-//
-// List<Task> groupTasks =
taskService.findGroupTasks("sampleResource");
-// assertEquals(1, groupTasks.size());
-// assertEquals("UserTask", groupTasks.get(0).getActivityName());
- // speciifiing a transition is unnecessary, BPMN has outgoing AND semantic!
+ // specifying a transition is unnecessary, BPMN has outgoing AND semantic!
// TODO: fix
+ // Currently not passing any 'outcome'
taskService.completeTask( allTasks.get(0).getId());
-
taskService.completeTask( allTasks.get(1).getId());
-
assertEquals(0, taskQuery.list().size());
-
- assertEquals(true, pi.isEnded());
-
- pi = executionService.findProcessInstanceById(pi.getId());
-
+
+ pi = executionService.findProcessInstanceById(pid);
// process instance is ended
assertNull(pi);
+
+
}
finally {
repositoryService.deleteDeploymentCascade(deploymentId);
}
-
- Parse parse =
bpmnParser.createParse().setResource("org/jbpm/bpmn/flownodes/forkWithUncontrolledSequenceFlow.bpmn.xml").execute();
-
- if (!parse.getProblems().isEmpty()) {
- fail("No problems should have occured. Problems: " +
parse.getProblems());
- }
-
- BpmnProcessDefinition processDefinition = ((List<BpmnProcessDefinition>)
parse.getDocumentObject()).get(0);
-
- ClientProcessInstance pi = processDefinition.createProcessInstance();
- pi.start();
}
}
Modified:
jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/parallelGateway.bpmn.xml
===================================================================
---
jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/parallelGateway.bpmn.xml 2009-07-30
09:43:55 UTC (rev 5387)
+++
jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/parallelGateway.bpmn.xml 2009-07-30
11:07:13 UTC (rev 5388)
@@ -5,26 +5,42 @@
xmlns:bpmn="http://schema.omg.org/spec/BPMN/2.0"
typeLanguage="http://www.w3.org/2001/XMLSchema"
expressionLanguage="http://www.w3.org/1999/XPath"
targetNamespace="http://sample.bpmn.camunda.com/">
- <bpmn:process id="Shipment" name="Shipment">
+ <bpmn:process id="ParallelGateway" name="ParallelGateway">
<!-- Start-Event -->
<bpmn:startEvent id="Start" />
- <bpmn:sequenceFlow id="flow1" sourceRef="Start"
- targetRef="parallelGatewayFork" name="fromStartToFork" />
+ <bpmn:sequenceFlow id="flow1" name="fromStartToFork"
+ sourceRef="Start"
+ targetRef="parallelGatewayFork" />
- <bpmn:parallelGateway id="parallelGatewayFork"
- name="The Fork" gatewayDirection="diverging"/>
+ <bpmn:parallelGateway id="parallelGatewayFork" name="The Fork"
+ gatewayDirection="diverging"/>
- <bpmn:sequenceFlow id="flow2" sourceRef="parallelGatewayFork"
- targetRef="parallelGatewayJoin" name="Leg 1" />
+ <bpmn:sequenceFlow id="flow2a" name="Leg 1"
+ sourceRef="parallelGatewayFork"
+ targetRef="UserTaskLeg1" />
+ <bpmn:userTask id="UserTaskLeg1" name="user task leg1"
implementation="other">
+ <bpmn:potentialOwner resourceRef="sampleResource" />
+ </bpmn:userTask>
+ <bpmn:sequenceFlow id="flow2b" name="Leg 1 -> Join"
+ sourceRef="UserTaskLeg1"
+ targetRef="parallelGatewayJoin" />
+
+ <bpmn:sequenceFlow id="flow3a" name="Leg 2"
+ sourceRef="parallelGatewayFork"
+ targetRef="UserTaskLeg2" />
+ <bpmn:userTask id="UserTaskLeg2" name="user task leg2"
implementation="other">
+ <bpmn:potentialOwner resourceRef="sampleResource" />
+ </bpmn:userTask>
+ <bpmn:sequenceFlow id="flow3b" name="Leg 2 -> Join"
+ sourceRef="UserTaskLeg2"
+ targetRef="parallelGatewayJoin" />
+
- <bpmn:sequenceFlow id="flow3" sourceRef="parallelGatewayFork"
- targetRef="parallelGatewayJoin" name="Leg 2" />
-
- <bpmn:parallelGateway id="parallelGatewayJoin"
- name="The Join" gatewayDirection="converging"/>
-
- <bpmn:sequenceFlow id="flow4" sourceRef="parallelGatewayJoin"
+ <bpmn:parallelGateway id="parallelGatewayJoin" name="The Join"
+ gatewayDirection="converging"/>
+ <bpmn:sequenceFlow id="flow4"
+ sourceRef="parallelGatewayJoin"
targetRef="End">
</bpmn:sequenceFlow>