Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
开发团队
Flowable Engine
提交
f1a9010a
F
Flowable Engine
项目概览
开发团队
/
Flowable Engine
通知
9
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
Flowable Engine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f1a9010a
编写于
1月 03, 2015
作者:
J
Joram Barrez
提交者:
Tijs Rademakers
4月 10, 2015
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Merge
上级
5ecd7fc8
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
684 addition
and
195 deletion
+684
-195
modules/activiti-engine/src/main/java/org/activiti/engine/impl/agenda/Agenda.java
...src/main/java/org/activiti/engine/impl/agenda/Agenda.java
+21
-2
modules/activiti-engine/src/main/java/org/activiti/engine/impl/agenda/EndExecutionOperation.java
...rg/activiti/engine/impl/agenda/EndExecutionOperation.java
+1
-1
modules/activiti-engine/src/main/java/org/activiti/engine/impl/agenda/ExecuteInactiveBehaviorsOperation.java
...engine/impl/agenda/ExecuteInactiveBehaviorsOperation.java
+75
-0
modules/activiti-engine/src/main/java/org/activiti/engine/impl/agenda/TakeOutgoingSequenceFlowsOperation.java
...ngine/impl/agenda/TakeOutgoingSequenceFlowsOperation.java
+7
-6
modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/InclusiveGatewayActivityBehavior.java
.../impl/bpmn/behavior/InclusiveGatewayActivityBehavior.java
+70
-163
modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/handler/InclusiveGatewayParseHandler.java
...mpl/bpmn/parser/handler/InclusiveGatewayParseHandler.java
+1
-8
modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/AbstractSetProcessInstanceStateCmd.java
...i/engine/impl/cmd/AbstractSetProcessInstanceStateCmd.java
+2
-1
modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/SetProcessDefinitionVersionCmd.java
...iviti/engine/impl/cmd/SetProcessDefinitionVersionCmd.java
+2
-1
modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandContext.java
.../org/activiti/engine/impl/interceptor/CommandContext.java
+21
-1
modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandInvoker.java
.../org/activiti/engine/impl/interceptor/CommandInvoker.java
+6
-7
modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ExecutionEntity.java
...iviti/engine/impl/persistence/entity/ExecutionEntity.java
+1
-3
modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ExecutionEntityManager.java
...ngine/impl/persistence/entity/ExecutionEntityManager.java
+19
-2
modules/activiti-engine/src/main/java/org/activiti/engine/impl/pvm/delegate/InactiveActivityBehavior.java
...ti/engine/impl/pvm/delegate/InactiveActivityBehavior.java
+19
-0
modules/activiti-engine/src/main/java/org/activiti/engine/impl/util/ExecutionGraphUtil.java
...ava/org/activiti/engine/impl/util/ExecutionGraphUtil.java
+133
-0
modules/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/Execution.xml
...in/resources/org/activiti/db/mapping/entity/Execution.xml
+7
-0
modules/activiti-engine/src/test/java/org/activiti6/Activiti6Tests.java
...ti-engine/src/test/java/org/activiti6/Activiti6Tests.java
+84
-0
modules/activiti-engine/src/test/resources/org/activiti6/Activiti6Tests.testNonInterruptingMoreComplex2.bpmn20.xml
...Activiti6Tests.testNonInterruptingMoreComplex2.bpmn20.xml
+215
-0
未找到文件。
modules/activiti-engine/src/main/java/org/activiti/engine/impl/agenda/Agenda.java
浏览文件 @
f1a9010a
...
...
@@ -14,6 +14,7 @@ package org.activiti.engine.impl.agenda;
import
java.util.LinkedList
;
import
org.activiti.engine.impl.interceptor.CommandContext
;
import
org.activiti.engine.impl.pvm.delegate.ActivityExecution
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -25,10 +26,12 @@ public class Agenda {
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
Agenda
.
class
);
protected
CommandContext
commandContext
;
protected
LinkedList
<
Runnable
>
operations
=
new
LinkedList
<
Runnable
>();
public
Agenda
()
{
public
Agenda
(
CommandContext
commandContext
)
{
this
.
commandContext
=
commandContext
;
}
public
boolean
isEmpty
()
{
...
...
@@ -68,5 +71,21 @@ public class Agenda {
public
void
planDestroyScopeOperation
(
ActivityExecution
execution
)
{
planOperation
(
new
DestroyScopeOperation
(
this
,
execution
));
}
public
void
planExecuteInactiveBehaviorsOperation
()
{
planOperation
(
new
ExecuteInactiveBehaviorsOperation
(
this
));
}
public
CommandContext
getCommandContext
()
{
return
commandContext
;
}
public
void
setCommandContext
(
CommandContext
commandContext
)
{
this
.
commandContext
=
commandContext
;
}
public
LinkedList
<
Runnable
>
getOperations
()
{
return
operations
;
}
}
modules/activiti-engine/src/main/java/org/activiti/engine/impl/agenda/EndExecutionOperation.java
浏览文件 @
f1a9010a
...
...
@@ -57,7 +57,7 @@ public class EndExecutionOperation extends AbstractOperation {
// Delete current execution
logger
.
debug
(
"Ending execution {}"
,
execution
.
getId
());
deleteExecution
(
commandContext
,
executionEntity
);
logger
.
debug
(
"Parent execution found. Continuing process using execution {}"
,
parentExecution
.
getId
());
parentExecution
.
setCurrentFlowElement
(
executionEntity
.
getCurrentFlowElement
());
agenda
.
planTakeOutgoingSequenceFlowsOperation
(
parentExecution
,
true
);
...
...
modules/activiti-engine/src/main/java/org/activiti/engine/impl/agenda/ExecuteInactiveBehaviorsOperation.java
0 → 100644
浏览文件 @
f1a9010a
package
org.activiti.engine.impl.agenda
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
org.activiti.bpmn.model.FlowNode
;
import
org.activiti.bpmn.model.Process
;
import
org.activiti.engine.impl.context.Context
;
import
org.activiti.engine.impl.interceptor.CommandContext
;
import
org.activiti.engine.impl.persistence.entity.ExecutionEntity
;
import
org.activiti.engine.impl.pvm.delegate.InactiveActivityBehavior
;
import
org.activiti.engine.impl.util.cache.ProcessDefinitionCacheUtil
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/**
* @author Joram Barrez
*/
public
class
ExecuteInactiveBehaviorsOperation
extends
AbstractOperation
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ExecuteInactiveBehaviorsOperation
.
class
);
protected
Collection
<
ExecutionEntity
>
involvedExecutions
;
public
ExecuteInactiveBehaviorsOperation
(
Agenda
agenda
)
{
super
(
agenda
,
null
);
this
.
involvedExecutions
=
agenda
.
getCommandContext
().
getInvolvedExecutions
();
}
@Override
public
void
run
()
{
/**
* Algortithm: for each execution that is involved in this command context,
* 1) Verify if its process definitions has any InactiveActivityBehavior instances.
* 2) If so, verify if there are any executions inactive in those
* 3) Execute the inactivated behavior
*/
CommandContext
commandContext
=
Context
.
getCommandContext
();
for
(
ExecutionEntity
executionEntity
:
involvedExecutions
)
{
Process
process
=
ProcessDefinitionCacheUtil
.
getCachedProcess
(
executionEntity
.
getProcessDefinitionId
());
Collection
<
String
>
flowNodeIdsWithInactivatedBehavior
=
new
ArrayList
<
String
>();
for
(
FlowNode
flowNode
:
process
.
findFlowElementsOfType
(
FlowNode
.
class
))
{
if
(
flowNode
.
getBehavior
()
instanceof
InactiveActivityBehavior
)
{
flowNodeIdsWithInactivatedBehavior
.
add
(
flowNode
.
getId
());
}
}
// Only check if the process actually has inactivated functionality
// TODO: this information could be cached
if
(
flowNodeIdsWithInactivatedBehavior
.
size
()
>
0
)
{
Collection
<
ExecutionEntity
>
inactiveExecutions
=
commandContext
.
getExecutionEntityManager
()
.
getInactiveExecutionsForProcessInstance
(
executionEntity
.
getProcessInstanceId
());
for
(
ExecutionEntity
inactiveExecution
:
inactiveExecutions
)
{
if
(!
inactiveExecution
.
isActive
()
&&
flowNodeIdsWithInactivatedBehavior
.
contains
(
inactiveExecution
.
getActivityId
())
&&
!
commandContext
.
getDbSqlSession
().
isPersistentObjectDeleted
(
inactiveExecution
))
{
FlowNode
flowNode
=
(
FlowNode
)
process
.
getFlowElement
(
inactiveExecution
.
getActivityId
(),
true
);
InactiveActivityBehavior
inactiveActivityBehavior
=
((
InactiveActivityBehavior
)
flowNode
.
getBehavior
());
logger
.
debug
(
"Found InactiveActivityBehavior instance of class {} that can be executed on activity '{}'"
,
inactiveActivityBehavior
.
getClass
(),
flowNode
.
getId
());
inactiveActivityBehavior
.
executeInactive
(
inactiveExecution
);;
}
}
}
}
}
}
modules/activiti-engine/src/main/java/org/activiti/engine/impl/agenda/TakeOutgoingSequenceFlowsOperation.java
浏览文件 @
f1a9010a
...
...
@@ -39,11 +39,11 @@ public class TakeOutgoingSequenceFlowsOperation extends AbstractOperation {
execution
.
setCurrentActivityId
(
currentFlowElement
.
getId
());
}
// If execution is a scope, the scope must first be destroyed before we can continue
// if (
execution.isScope()) {
// coreEngine.destroyScope(commandContext,
execution);
//
// return;
//
}
// If execution is a scope
(and not the process instance)
, the scope must first be destroyed before we can continue
if
(
execution
.
getParentId
()
!=
null
&&
execution
.
isScope
())
{
agenda
.
planDestroyScopeOperation
(
execution
);
// return;
}
// No scope, can continue
if
(
currentFlowElement
instanceof
FlowNode
)
{
...
...
@@ -56,7 +56,8 @@ public class TakeOutgoingSequenceFlowsOperation extends AbstractOperation {
protected
void
leaveFlowNode
(
FlowNode
flowNode
)
{
logger
.
debug
(
"Leaving flow node {} by following it's {} outgoing sequenceflow"
,
flowNode
.
getClass
(),
flowNode
.
getOutgoingFlows
().
size
());
logger
.
debug
(
"Leaving flow node {} with id '{}' by following it's {} outgoing sequenceflow"
,
flowNode
.
getClass
(),
flowNode
.
getId
(),
flowNode
.
getOutgoingFlows
().
size
());
// Determine which sequence flows can be used for leaving
List
<
SequenceFlow
>
outgoingSequenceFlow
=
new
ArrayList
<
SequenceFlow
>();
...
...
modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/InclusiveGatewayActivityBehavior.java
浏览文件 @
f1a9010a
...
...
@@ -12,20 +12,16 @@
*/
package
org.activiti.engine.impl.bpmn.behavior
;
import
java.util.ArrayList
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Collection
;
import
java.util.Iterator
;
import
org.activiti.engine.ActivitiException
;
import
org.activiti.engine.delegate.Expression
;
import
org.activiti.engine.impl.Condition
;
import
org.activiti.engine.impl.bpmn.helper.SkipExpressionUtil
;
import
org.activiti.engine.impl.bpmn.parser.BpmnParse
;
import
org.activiti.engine.impl.context.Context
;
import
org.activiti.engine.impl.interceptor.CommandContext
;
import
org.activiti.engine.impl.persistence.entity.ExecutionEntity
;
import
org.activiti.engine.impl.pvm.PvmActivity
;
import
org.activiti.engine.impl.pvm.PvmTransition
;
import
org.activiti.engine.impl.persistence.entity.ExecutionEntityManager
;
import
org.activiti.engine.impl.pvm.delegate.ActivityExecution
;
import
org.activiti.engine.impl.pvm.delegate.InactiveActivityBehavior
;
import
org.activiti.engine.impl.util.ExecutionGraphUtil
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -37,156 +33,67 @@ import org.slf4j.LoggerFactory;
* @author Tom Van Buskirk
* @author Joram Barrez
*/
public
class
InclusiveGatewayActivityBehavior
extends
GatewayActivityBehavior
{
private
static
final
long
serialVersionUID
=
1L
;
private
static
Logger
log
=
LoggerFactory
.
getLogger
(
InclusiveGatewayActivityBehavior
.
class
.
getName
());
public
void
execute
(
ActivityExecution
execution
)
{
execution
.
inactivate
();
lockConcurrentRoot
(
execution
);
PvmActivity
activity
=
execution
.
getActivity
();
if
(!
activeConcurrentExecutionsExist
(
execution
))
{
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"inclusive gateway '{}' activates"
,
activity
.
getId
());
}
List
<
ActivityExecution
>
joinedExecutions
=
execution
.
findInactiveConcurrentExecutions
(
activity
);
String
defaultSequenceFlow
=
(
String
)
execution
.
getActivity
().
getProperty
(
"default"
);
List
<
PvmTransition
>
transitionsToTake
=
new
ArrayList
<
PvmTransition
>();
for
(
PvmTransition
outgoingTransition
:
execution
.
getActivity
().
getOutgoingTransitions
())
{
Expression
skipExpression
=
outgoingTransition
.
getSkipExpression
();
if
(!
SkipExpressionUtil
.
isSkipExpressionEnabled
(
execution
,
skipExpression
))
{
if
(
defaultSequenceFlow
==
null
||
!
outgoingTransition
.
getId
().
equals
(
defaultSequenceFlow
))
{
Condition
condition
=
(
Condition
)
outgoingTransition
.
getProperty
(
BpmnParse
.
PROPERTYNAME_CONDITION
);
if
(
condition
==
null
||
condition
.
evaluate
(
execution
))
{
transitionsToTake
.
add
(
outgoingTransition
);
}
}
}
else
if
(
SkipExpressionUtil
.
shouldSkipFlowElement
(
execution
,
skipExpression
)){
transitionsToTake
.
add
(
outgoingTransition
);
}
}
if
(!
transitionsToTake
.
isEmpty
())
{
execution
.
takeAll
(
transitionsToTake
,
joinedExecutions
);
}
else
{
if
(
defaultSequenceFlow
!=
null
)
{
PvmTransition
defaultTransition
=
execution
.
getActivity
().
findOutgoingTransition
(
defaultSequenceFlow
);
if
(
defaultTransition
!=
null
)
{
execution
.
take
(
defaultTransition
);
}
else
{
throw
new
ActivitiException
(
"Default sequence flow '"
+
defaultSequenceFlow
+
"' could not be not found"
);
}
}
else
{
// No sequence flow could be found, not even a default one
throw
new
ActivitiException
(
"No outgoing sequence flow of the inclusive gateway '"
+
execution
.
getActivity
().
getId
()
+
"' could be selected for continuing the process"
);
}
}
}
else
{
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"Inclusive gateway '{}' does not activate"
,
activity
.
getId
());
}
}
}
List
<?
extends
ActivityExecution
>
getLeaveExecutions
(
ActivityExecution
parent
)
{
List
<
ActivityExecution
>
executionlist
=
new
ArrayList
<
ActivityExecution
>();
List
<?
extends
ActivityExecution
>
subExecutions
=
parent
.
getExecutions
();
if
(
subExecutions
.
isEmpty
())
{
executionlist
.
add
(
parent
);
}
else
{
for
(
ActivityExecution
concurrentExecution
:
subExecutions
)
{
executionlist
.
addAll
(
getLeaveExecutions
(
concurrentExecution
));
}
}
return
executionlist
;
}
public
boolean
activeConcurrentExecutionsExist
(
ActivityExecution
execution
)
{
PvmActivity
activity
=
execution
.
getActivity
();
if
(
execution
.
isConcurrent
())
{
for
(
ActivityExecution
concurrentExecution
:
getLeaveExecutions
(
execution
.
getParent
()))
{
if
(
concurrentExecution
.
isActive
()
&&
concurrentExecution
.
getId
().
equals
(
execution
.
getId
())
==
false
)
{
// TODO: when is transitionBeingTaken cleared? Should we clear it?
boolean
reachable
=
false
;
PvmTransition
pvmTransition
=
((
ExecutionEntity
)
concurrentExecution
).
getTransitionBeingTaken
();
if
(
pvmTransition
!=
null
)
{
reachable
=
isReachable
(
pvmTransition
.
getDestination
(),
activity
,
new
HashSet
<
PvmActivity
>());
}
else
{
reachable
=
isReachable
(
concurrentExecution
.
getActivity
(),
activity
,
new
HashSet
<
PvmActivity
>());
}
if
(
reachable
)
{
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"an active concurrent execution found: '{}'"
,
concurrentExecution
.
getActivity
());
}
return
true
;
}
}
}
}
else
if
(
execution
.
isActive
())
{
// is this ever true?
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"an active concurrent execution found: '{}'"
,
execution
.
getActivity
());
}
return
true
;
}
return
false
;
}
protected
boolean
isReachable
(
PvmActivity
srcActivity
,
PvmActivity
targetActivity
,
Set
<
PvmActivity
>
visitedActivities
)
{
// if source has no outputs, it is the end of the process, and its parent process should be checked.
if
(
srcActivity
.
getOutgoingTransitions
().
isEmpty
())
{
visitedActivities
.
add
(
srcActivity
);
if
(!(
srcActivity
.
getParent
()
instanceof
PvmActivity
))
{
return
false
;
}
srcActivity
=
(
PvmActivity
)
srcActivity
.
getParent
();
}
if
(
srcActivity
.
equals
(
targetActivity
))
{
return
true
;
}
// To avoid infinite looping, we must capture every node we visit
// and check before going further in the graph if we have already visitied
// the node.
visitedActivities
.
add
(
srcActivity
);
List
<
PvmTransition
>
transitionList
=
srcActivity
.
getOutgoingTransitions
();
if
(
transitionList
!=
null
&&
!
transitionList
.
isEmpty
())
{
for
(
PvmTransition
pvmTransition
:
transitionList
)
{
PvmActivity
destinationActivity
=
pvmTransition
.
getDestination
();
if
(
destinationActivity
!=
null
&&
!
visitedActivities
.
contains
(
destinationActivity
))
{
boolean
reachable
=
isReachable
(
destinationActivity
,
targetActivity
,
visitedActivities
);
// If false, we should investigate other paths, and not yet return the
// result
if
(
reachable
)
{
return
true
;
}
}
}
}
return
false
;
}
public
class
InclusiveGatewayActivityBehavior
extends
GatewayActivityBehavior
implements
InactiveActivityBehavior
{
private
static
final
long
serialVersionUID
=
1L
;
private
static
Logger
logger
=
LoggerFactory
.
getLogger
(
InclusiveGatewayActivityBehavior
.
class
.
getName
());
@Override
public
void
execute
(
ActivityExecution
execution
)
{
// The join in the inclusive gateway works as follows:
// When an execution enters it, it is inactivated.
// All the inactivated executions stay in the inclusive gateway
// until ALL executions that CAN reach the inclusive gateway have reached it.
//
// This check is repeated on execution changes until the inactivated
// executions leave the gateway.
execution
.
inactivate
();
executeInclusiveGatewayLogic
((
ExecutionEntity
)
execution
);
}
@Override
public
void
executeInactive
(
ExecutionEntity
executionEntity
)
{
executeInclusiveGatewayLogic
(
executionEntity
);
}
protected
void
executeInclusiveGatewayLogic
(
ExecutionEntity
execution
)
{
CommandContext
commandContext
=
Context
.
getCommandContext
();
ExecutionEntityManager
executionEntityManager
=
commandContext
.
getExecutionEntityManager
();
Collection
<
ExecutionEntity
>
allExecutions
=
executionEntityManager
.
findChildExecutionsByProcessInstanceId
(
execution
.
getProcessInstanceId
());
Iterator
<
ExecutionEntity
>
executionIterator
=
allExecutions
.
iterator
();
boolean
oneExecutionCanReachGateway
=
false
;
while
(!
oneExecutionCanReachGateway
&&
executionIterator
.
hasNext
())
{
ExecutionEntity
executionEntity
=
executionIterator
.
next
();
if
(!
executionEntity
.
getActivityId
().
equals
(
execution
.
getCurrentActivityId
()))
{
boolean
canReachGateway
=
ExecutionGraphUtil
.
isReachable
(
execution
.
getProcessDefinitionId
(),
executionEntity
.
getActivityId
(),
execution
.
getCurrentActivityId
());
if
(
canReachGateway
)
{
oneExecutionCanReachGateway
=
true
;
}
}
}
// If no execution can reach the gateway, the gateway activates and executes fork behavior
if
(!
oneExecutionCanReachGateway
)
{
logger
.
debug
(
"Inclusive gateway cannot be reached by any execution and is activated"
);
// Kill all executions here (except the incoming)
Collection
<
ExecutionEntity
>
executionsInGateway
=
executionEntityManager
.
getInactiveExecutionsInActivity
(
execution
.
getCurrentActivityId
());
for
(
ExecutionEntity
executionEntityInGateway
:
executionsInGateway
)
{
if
(!
executionEntityInGateway
.
getId
().
equals
(
execution
.
getId
()))
{
executionEntityManager
.
delete
(
executionEntityInGateway
);
}
}
// Leave
// TODO: default sequence flow
commandContext
.
getAgenda
().
planTakeOutgoingSequenceFlowsOperation
(
execution
,
true
);
}
}
}
modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/handler/InclusiveGatewayParseHandler.java
浏览文件 @
f1a9010a
...
...
@@ -12,11 +12,9 @@
*/
package
org.activiti.engine.impl.bpmn.parser.handler
;
import
org.activiti.bpmn.constants.BpmnXMLConstants
;
import
org.activiti.bpmn.model.BaseElement
;
import
org.activiti.bpmn.model.InclusiveGateway
;
import
org.activiti.engine.impl.bpmn.parser.BpmnParse
;
import
org.activiti.engine.impl.pvm.process.ActivityImpl
;
/**
...
...
@@ -29,12 +27,7 @@ public class InclusiveGatewayParseHandler extends AbstractActivityBpmnParseHandl
}
protected
void
executeParse
(
BpmnParse
bpmnParse
,
InclusiveGateway
gateway
)
{
ActivityImpl
activity
=
createActivityOnCurrentScope
(
bpmnParse
,
gateway
,
BpmnXMLConstants
.
ELEMENT_GATEWAY_INCLUSIVE
);
activity
.
setAsync
(
gateway
.
isAsynchronous
());
activity
.
setExclusive
(!
gateway
.
isNotExclusive
());
activity
.
setActivityBehavior
(
bpmnParse
.
getActivityBehaviorFactory
().
createInclusiveGatewayActivityBehavior
(
gateway
));
gateway
.
setBehavior
(
bpmnParse
.
getActivityBehaviorFactory
().
createInclusiveGatewayActivityBehavior
(
gateway
));
}
}
modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/AbstractSetProcessInstanceStateCmd.java
浏览文件 @
f1a9010a
...
...
@@ -12,6 +12,7 @@
*/
package
org.activiti.engine.impl.cmd
;
import
java.util.Collection
;
import
java.util.List
;
import
org.activiti.engine.ActivitiException
;
...
...
@@ -57,7 +58,7 @@ public abstract class AbstractSetProcessInstanceStateCmd implements Command<Void
SuspensionStateUtil
.
setSuspensionState
(
executionEntity
,
getNewState
());
// All child executions are suspended
List
<
ExecutionEntity
>
childExecutions
=
commandContext
.
getExecutionEntityManager
().
findChildExecutionsByProcessInstanceId
(
executionId
);
Collection
<
ExecutionEntity
>
childExecutions
=
commandContext
.
getExecutionEntityManager
().
findChildExecutionsByProcessInstanceId
(
executionId
);
for
(
ExecutionEntity
childExecution
:
childExecutions
)
{
if
(!
childExecution
.
getId
().
equals
(
executionId
))
{
SuspensionStateUtil
.
setSuspensionState
(
childExecution
,
getNewState
());
...
...
modules/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/SetProcessDefinitionVersionCmd.java
浏览文件 @
f1a9010a
...
...
@@ -14,6 +14,7 @@
package
org.activiti.engine.impl.cmd
;
import
java.io.Serializable
;
import
java.util.Collection
;
import
java.util.List
;
import
org.activiti.engine.ActivitiException
;
...
...
@@ -113,7 +114,7 @@ public class SetProcessDefinitionVersionCmd implements Command<Void>, Serializab
commandContext
.
getHistoryManager
().
recordProcessDefinitionChange
(
processInstanceId
,
newProcessDefinition
.
getId
());
// switch all sub-executions of the process instance to the new process definition version
List
<
ExecutionEntity
>
childExecutions
=
executionManager
Collection
<
ExecutionEntity
>
childExecutions
=
executionManager
.
findChildExecutionsByProcessInstanceId
(
processInstanceId
);
for
(
ExecutionEntity
executionEntity
:
childExecutions
)
{
validateAndSwitchVersionOfExecution
(
commandContext
,
executionEntity
,
newProcessDefinition
);
...
...
modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandContext.java
浏览文件 @
f1a9010a
...
...
@@ -13,6 +13,7 @@
package
org.activiti.engine.impl.interceptor
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.LinkedList
;
import
java.util.List
;
...
...
@@ -36,6 +37,7 @@ import org.activiti.engine.impl.persistence.entity.CommentEntityManager;
import
org.activiti.engine.impl.persistence.entity.DeploymentEntityManager
;
import
org.activiti.engine.impl.persistence.entity.EventLogEntryEntityManager
;
import
org.activiti.engine.impl.persistence.entity.EventSubscriptionEntityManager
;
import
org.activiti.engine.impl.persistence.entity.ExecutionEntity
;
import
org.activiti.engine.impl.persistence.entity.ExecutionEntityManager
;
import
org.activiti.engine.impl.persistence.entity.GroupIdentityManager
;
import
org.activiti.engine.impl.persistence.entity.HistoricActivityInstanceEntityManager
;
...
...
@@ -82,9 +84,11 @@ public class CommandContext {
protected
List
<
CommandContextCloseListener
>
closeListeners
;
protected
Map
<
String
,
Object
>
attributes
;
// General-purpose storing of anything during the lifetime of a command context
protected
Agenda
agenda
=
new
Agenda
();
protected
Agenda
agenda
=
new
Agenda
(
this
);
protected
Map
<
String
,
ExecutionEntity
>
involvedExecutions
=
new
HashMap
<
String
,
ExecutionEntity
>(
1
);
// The executions involved with the command
protected
Object
result
=
null
;
public
void
performOperation
(
AtomicOperation
executionOperation
,
InterpretableExecution
execution
)
{
nextOperations
.
add
(
executionOperation
);
if
(
nextOperations
.
size
()==
1
)
{
...
...
@@ -382,6 +386,22 @@ public class CommandContext {
return
getSession
(
HistoryManager
.
class
);
}
// Involved executions //////////////////////////////////////////////////////
public
void
addInvolvedExecution
(
ExecutionEntity
executionEntity
)
{
if
(
executionEntity
.
getId
()
!=
null
)
{
involvedExecutions
.
put
(
executionEntity
.
getId
(),
executionEntity
);
}
}
public
boolean
hasInvolvedExecutions
()
{
return
involvedExecutions
.
size
()
>
0
;
}
public
Collection
<
ExecutionEntity
>
getInvolvedExecutions
()
{
return
involvedExecutions
.
values
();
}
// getters and setters //////////////////////////////////////////////////////
public
TransactionContext
getTransactionContext
()
{
...
...
modules/activiti-engine/src/main/java/org/activiti/engine/impl/interceptor/CommandInvoker.java
浏览文件 @
f1a9010a
...
...
@@ -37,13 +37,12 @@ public class CommandInvoker extends AbstractCommandInterceptor {
// Run loop for agenda
executeOperations
(
commandContext
);
// // At the end, call the execution tree change listeners.
// // TODO: optimization: only do this when the tree has actually changed
// // (ie check dbSqlSession).
// if (commandContext.hasInvolvedExecutions()) {
// commandContext.getAgenda().add(new ExecuteInactivatedBehavior(commandContext.getCoreEngine(), commandContext));
// executeOperations(commandContext);
// }
// At the end, call the execution tree change listeners.
// TODO: optimization: only do this when the tree has actually changed (ie check dbSqlSession).
if
(
commandContext
.
hasInvolvedExecutions
())
{
commandContext
.
getAgenda
().
planExecuteInactiveBehaviorsOperation
();
executeOperations
(
commandContext
);
}
return
(
T
)
commandContext
.
getResult
();
}
...
...
modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ExecutionEntity.java
浏览文件 @
f1a9010a
...
...
@@ -276,9 +276,7 @@ public class ExecutionEntity extends VariableScopeImpl implements ActivityExecut
// initialize the new execution
createdExecution
.
setProcessDefinitionId
(
this
.
getProcessDefinitionId
());
createdExecution
.
setProcessInstanceId
(
this
.
getProcessInstanceId
()
!=
null
?
this
.
getProcessInstanceId
()
:
this
.
getId
());
// createdExecution.setProcessDefinition(getProcessDefinition());
// createdExecution.setProcessInstance(getProcessInstance());
// createdExecution.setActivity(getActivity());
createdExecution
.
setScope
(
false
);
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"Child execution {} created with parent {}"
,
createdExecution
,
this
.
getId
());
...
...
modules/activiti-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ExecutionEntityManager.java
浏览文件 @
f1a9010a
...
...
@@ -107,8 +107,13 @@ public class ExecutionEntityManager extends AbstractEntityManager<ExecutionEntit
}
@SuppressWarnings
(
"unchecked"
)
public
List
<
ExecutionEntity
>
findChildExecutionsByProcessInstanceId
(
String
processInstanceId
)
{
return
getDbSqlSession
().
selectList
(
"selectExecutionsByProcessInstanceId"
,
processInstanceId
);
public
Collection
<
ExecutionEntity
>
findChildExecutionsByProcessInstanceId
(
final
String
processInstanceId
)
{
return
getList
(
"selectExecutionsByProcessInstanceId"
,
processInstanceId
,
new
CachedEntityMatcher
<
ExecutionEntity
>()
{
@Override
public
boolean
isRetained
(
ExecutionEntity
executionEntity
)
{
return
executionEntity
.
getProcessInstanceId
()
!=
null
&&
executionEntity
.
getProcessInstanceId
().
equals
(
processInstanceId
);
}
});
}
public
ExecutionEntity
findExecutionById
(
String
executionId
)
{
...
...
@@ -185,6 +190,18 @@ public class ExecutionEntityManager extends AbstractEntityManager<ExecutionEntit
});
}
public
Collection
<
ExecutionEntity
>
getInactiveExecutionsForProcessInstance
(
final
String
processInstanceId
)
{
HashMap
<
String
,
String
>
params
=
new
HashMap
<
String
,
String
>(
1
);
params
.
put
(
"processInstanceId"
,
processInstanceId
);
return
getList
(
"selectInactiveExecutionsForProcessInstance"
,
params
,
new
CachedEntityMatcher
<
ExecutionEntity
>()
{
public
boolean
isRetained
(
ExecutionEntity
executionEntity
)
{
return
executionEntity
.
getProcessInstanceId
()
!=
null
&&
executionEntity
.
getProcessInstanceId
().
equals
(
processInstanceId
)
&&
!
executionEntity
.
isActive
();
}
});
}
@SuppressWarnings
(
"unchecked"
)
public
List
<
Execution
>
findExecutionsByNativeQuery
(
Map
<
String
,
Object
>
parameterMap
,
int
firstResult
,
int
maxResults
)
{
return
getDbSqlSession
().
selectListWithRawParameter
(
"selectExecutionByNativeQuery"
,
parameterMap
,
firstResult
,
maxResults
);
...
...
modules/activiti-engine/src/main/java/org/activiti/engine/impl/pvm/delegate/InactiveActivityBehavior.java
0 → 100644
浏览文件 @
f1a9010a
package
org.activiti.engine.impl.pvm.delegate
;
import
org.activiti.engine.impl.persistence.entity.ExecutionEntity
;
/**
* If the behaviour of an element in a process implements this interface,
* it has a 'background job' functionality.
*
* The instance will be called at the end of executing the engine operations
* for each {@link ExecutionEntity} that currently is at the activity AND is inactive.
*
* @author Joram Barrez
*/
public
interface
InactiveActivityBehavior
{
void
executeInactive
(
ExecutionEntity
executionEntity
);
}
modules/activiti-engine/src/main/java/org/activiti/engine/impl/util/ExecutionGraphUtil.java
0 → 100644
浏览文件 @
f1a9010a
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.activiti.engine.impl.util
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
org.activiti.bpmn.model.FlowElementsContainer
;
import
org.activiti.bpmn.model.FlowNode
;
import
org.activiti.bpmn.model.Process
;
import
org.activiti.bpmn.model.SequenceFlow
;
import
org.activiti.bpmn.model.SubProcess
;
import
org.activiti.engine.ActivitiException
;
import
org.activiti.engine.impl.persistence.entity.ExecutionEntity
;
import
org.activiti.engine.impl.util.cache.ProcessDefinitionCacheUtil
;
public
class
ExecutionGraphUtil
{
/**
* Takes in a collection of executions belonging to the same process instance.
* Orders the executions in a list, first elements are the leaf, last element is the root elements.
*/
public
static
List
<
ExecutionEntity
>
orderFromRootToLeaf
(
Collection
<
ExecutionEntity
>
executions
)
{
List
<
ExecutionEntity
>
orderedList
=
new
ArrayList
<
ExecutionEntity
>(
executions
.
size
());
// Root elements
HashSet
<
String
>
previousIds
=
new
HashSet
<
String
>();
for
(
ExecutionEntity
execution
:
executions
)
{
if
(
execution
.
getParentId
()
==
null
)
{
orderedList
.
add
(
execution
);
previousIds
.
add
(
execution
.
getId
());
}
}
// Non-root elements
while
(
orderedList
.
size
()
<
executions
.
size
())
{
for
(
ExecutionEntity
execution
:
executions
)
{
if
(!
previousIds
.
contains
(
execution
.
getId
())
&&
previousIds
.
contains
(
execution
.
getParentId
()))
{
orderedList
.
add
(
execution
);
previousIds
.
add
(
execution
.
getId
());
}
}
}
return
orderedList
;
}
public
static
List
<
ExecutionEntity
>
orderFromLeafToRoot
(
Collection
<
ExecutionEntity
>
executions
)
{
List
<
ExecutionEntity
>
orderedList
=
orderFromRootToLeaf
(
executions
);
Collections
.
reverse
(
orderedList
);
return
orderedList
;
}
/**
* Verifies if the element with the given source identifier can reach the element with the target identifier
* through following sequence flow.
*/
public
static
boolean
isReachable
(
String
processDefinitionId
,
String
sourceElementId
,
String
targetElementId
)
{
// Fetch source and target elements
Process
process
=
ProcessDefinitionCacheUtil
.
getCachedProcess
(
processDefinitionId
);
FlowNode
sourceElement
=
(
FlowNode
)
process
.
getFlowElement
(
sourceElementId
,
true
);
FlowNode
targetElement
=
(
FlowNode
)
process
.
getFlowElement
(
targetElementId
,
true
);
if
(
sourceElement
==
null
)
{
throw
new
ActivitiException
(
"Invalid sourceElementId '"
+
sourceElementId
+
"': no element found for this id n process definition '"
+
processDefinitionId
+
"'"
);
}
if
(
targetElement
==
null
)
{
throw
new
ActivitiException
(
"Invalid targetElementId '"
+
targetElementId
+
"': no element found for this id n process definition '"
+
processDefinitionId
+
"'"
);
}
Set
<
String
>
visitedElements
=
new
HashSet
<
String
>();
return
isReachable
(
process
,
sourceElement
,
targetElement
,
visitedElements
);
}
public
static
boolean
isReachable
(
Process
process
,
FlowNode
sourceElement
,
FlowNode
targetElement
,
Set
<
String
>
visitedElements
)
{
// No outgoing seq flow: could be the end of eg . the process or an embedded subprocess
if
(
sourceElement
.
getOutgoingFlows
().
size
()
==
0
)
{
visitedElements
.
add
(
sourceElement
.
getId
());
FlowElementsContainer
parentElement
=
process
.
findParent
(
sourceElement
);
if
(
parentElement
!=
null
&&
parentElement
instanceof
SubProcess
)
{
sourceElement
=
(
SubProcess
)
parentElement
;
}
else
{
return
false
;
}
}
if
(
sourceElement
.
getId
().
equals
(
targetElement
.
getId
()))
{
return
true
;
}
// To avoid infinite looping, we must capture every node we visit
// and check before going further in the graph if we have already visitedthe node.
visitedElements
.
add
(
sourceElement
.
getId
());
List
<
SequenceFlow
>
sequenceFlows
=
sourceElement
.
getOutgoingFlows
();
if
(
sequenceFlows
!=
null
&&
sequenceFlows
.
size
()
>
0
)
{
for
(
SequenceFlow
sequenceFlow
:
sequenceFlows
)
{
String
targetRef
=
sequenceFlow
.
getTargetRef
();
FlowNode
sequenceFlowTarget
=
(
FlowNode
)
process
.
getFlowElement
(
targetRef
,
true
);
if
(
sequenceFlowTarget
!=
null
&&
!
visitedElements
.
contains
(
sequenceFlowTarget
.
getId
()))
{
boolean
reachable
=
isReachable
(
process
,
sequenceFlowTarget
,
targetElement
,
visitedElements
);
if
(
reachable
)
{
return
true
;
}
}
}
}
return
false
;
}
}
modules/activiti-engine/src/main/resources/org/activiti/db/mapping/entity/Execution.xml
浏览文件 @
f1a9010a
...
...
@@ -251,6 +251,13 @@
where ACT_ID_ = #{parameter.activityId}
</select>
<select
id=
"selectInactiveExecutionsForProcessInstance"
parameterType=
"org.activiti.engine.impl.db.ListQueryParameterObject"
resultMap=
"executionResultMap"
>
select *
from ${prefix}ACT_RU_EXECUTION
where PROC_INST_ID_ = #{parameter.processInstanceId}
and IS_ACTIVE_ = 0
</select>
<select
id=
"selectExecutionsByQueryCriteria"
parameterType=
"org.activiti.engine.impl.ExecutionQueryImpl"
resultMap=
"executionResultMap"
>
${limitBefore}
select distinct RES.* ${limitBetween}, P.KEY_ as ProcessDefinitionKey, P.ID_ as ProcessDefinitionId
...
...
modules/activiti-engine/src/test/java/org/activiti6/Activiti6Tests.java
浏览文件 @
f1a9010a
...
...
@@ -326,5 +326,89 @@ public class Activiti6Tests extends AbstractActvitiTest {
assertEquals
(
0
,
runtimeService
.
createExecutionQuery
().
count
());
}
@Test
@org
.
activiti
.
engine
.
test
.
Deployment
public
void
testNonInterruptingMoreComplex2
()
{
// Use case 1: no timers fire
ProcessInstance
processInstance
=
runtimeService
.
startProcessInstanceByKey
(
"nonInterruptingWithInclusiveMerge"
);
assertNotNull
(
processInstance
);
assertFalse
(
processInstance
.
isEnded
());
List
<
Task
>
tasks
=
taskService
.
createTaskQuery
().
processInstanceId
(
processInstance
.
getId
()).
orderByTaskName
().
asc
().
list
();
assertEquals
(
2
,
tasks
.
size
());
assertEquals
(
"A"
,
tasks
.
get
(
0
).
getName
());
assertEquals
(
"B"
,
tasks
.
get
(
1
).
getName
());
assertEquals
(
2
,
managementService
.
createJobQuery
().
count
());
// Completing A
taskService
.
complete
(
tasks
.
get
(
0
).
getId
());
tasks
=
taskService
.
createTaskQuery
().
processInstanceId
(
processInstance
.
getId
()).
orderByTaskName
().
asc
().
list
();
assertEquals
(
1
,
tasks
.
size
());
assertEquals
(
"B"
,
tasks
.
get
(
0
).
getName
());
assertEquals
(
1
,
managementService
.
createJobQuery
().
count
());
// Completing B should end the process
taskService
.
complete
(
tasks
.
get
(
0
).
getId
());
assertEquals
(
0
,
managementService
.
createJobQuery
().
count
());
assertEquals
(
0
,
runtimeService
.
createExecutionQuery
().
count
());
// Use case 2: The non interrupting timer on B fires
processInstance
=
runtimeService
.
startProcessInstanceByKey
(
"nonInterruptingWithInclusiveMerge"
);
tasks
=
taskService
.
createTaskQuery
().
processInstanceId
(
processInstance
.
getId
()).
orderByTaskName
().
asc
().
list
();
assertEquals
(
2
,
tasks
.
size
());
assertEquals
(
"A"
,
tasks
.
get
(
0
).
getName
());
assertEquals
(
"B"
,
tasks
.
get
(
1
).
getName
());
assertEquals
(
2
,
managementService
.
createJobQuery
().
count
());
// Completing B
taskService
.
complete
(
tasks
.
get
(
1
).
getId
());
tasks
=
taskService
.
createTaskQuery
().
processInstanceId
(
processInstance
.
getId
()).
orderByTaskName
().
asc
().
list
();
assertEquals
(
1
,
tasks
.
size
());
assertEquals
(
"A"
,
tasks
.
get
(
0
).
getName
());
assertEquals
(
1
,
managementService
.
createJobQuery
().
count
());
// Firing the timer should activate E and F too
managementService
.
executeJob
(
managementService
.
createJobQuery
().
singleResult
().
getId
());
tasks
=
taskService
.
createTaskQuery
().
processInstanceId
(
processInstance
.
getId
()).
orderByTaskName
().
asc
().
list
();
assertEquals
(
3
,
tasks
.
size
());
assertEquals
(
"A"
,
tasks
.
get
(
0
).
getName
());
assertEquals
(
"C"
,
tasks
.
get
(
1
).
getName
());
assertEquals
(
"D"
,
tasks
.
get
(
2
).
getName
());
// Firing the timer on D
assertEquals
(
1
,
managementService
.
createJobQuery
().
count
());
managementService
.
executeJob
(
managementService
.
createJobQuery
().
singleResult
().
getId
());
tasks
=
taskService
.
createTaskQuery
().
processInstanceId
(
processInstance
.
getId
()).
orderByTaskName
().
asc
().
list
();
assertEquals
(
4
,
tasks
.
size
());
assertEquals
(
"A"
,
tasks
.
get
(
0
).
getName
());
assertEquals
(
"C"
,
tasks
.
get
(
1
).
getName
());
assertEquals
(
"D"
,
tasks
.
get
(
2
).
getName
());
assertEquals
(
"G"
,
tasks
.
get
(
3
).
getName
());
// Completing C, D, A and G in that order to give the engine a bit of excercise
taskService
.
complete
(
taskService
.
createTaskQuery
().
taskName
(
"C"
).
singleResult
().
getId
());
tasks
=
taskService
.
createTaskQuery
().
processInstanceId
(
processInstance
.
getId
()).
orderByTaskName
().
asc
().
list
();
assertEquals
(
3
,
tasks
.
size
());
assertEquals
(
"A"
,
tasks
.
get
(
0
).
getName
());
assertEquals
(
"D"
,
tasks
.
get
(
1
).
getName
());
assertEquals
(
"G"
,
tasks
.
get
(
2
).
getName
());
taskService
.
complete
(
taskService
.
createTaskQuery
().
taskName
(
"D"
).
singleResult
().
getId
());
tasks
=
taskService
.
createTaskQuery
().
processInstanceId
(
processInstance
.
getId
()).
orderByTaskName
().
asc
().
list
();
assertEquals
(
2
,
tasks
.
size
());
assertEquals
(
"A"
,
tasks
.
get
(
0
).
getName
());
assertEquals
(
"G"
,
tasks
.
get
(
1
).
getName
());
taskService
.
complete
(
taskService
.
createTaskQuery
().
taskName
(
"A"
).
singleResult
().
getId
());
tasks
=
taskService
.
createTaskQuery
().
processInstanceId
(
processInstance
.
getId
()).
orderByTaskName
().
asc
().
list
();
assertEquals
(
1
,
tasks
.
size
());
assertEquals
(
"G"
,
tasks
.
get
(
0
).
getName
());
taskService
.
complete
(
taskService
.
createTaskQuery
().
taskName
(
"G"
).
singleResult
().
getId
());
assertEquals
(
0
,
runtimeService
.
createExecutionQuery
().
count
());
}
}
modules/activiti-engine/src/test/resources/org/activiti6/Activiti6Tests.testNonInterruptingMoreComplex2.bpmn20.xml
0 → 100644
浏览文件 @
f1a9010a
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns=
"http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd=
"http://www.w3.org/2001/XMLSchema"
xmlns:activiti=
"http://activiti.org/bpmn"
xmlns:bpmndi=
"http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:omgdc=
"http://www.omg.org/spec/DD/20100524/DC"
xmlns:omgdi=
"http://www.omg.org/spec/DD/20100524/DI"
typeLanguage=
"http://www.w3.org/2001/XMLSchema"
expressionLanguage=
"http://www.w3.org/1999/XPath"
targetNamespace=
"http://www.activiti.org/processdef"
xmlns:modeler=
"http://activiti.com/modeler"
modeler:version=
"1.0en"
modeler:exportDateTime=
"20140421160834832"
>
<process
id=
"nonInterruptingWithInclusiveMerge"
isExecutable=
"true"
>
<startEvent
id=
"sid-4EE6BBAE-E5AC-4DEB-AE43-C8732945403F"
></startEvent>
<sequenceFlow
id=
"sid-7B273A13-5CDA-46FA-9024-85EA2487FDD3"
sourceRef=
"sid-4EE6BBAE-E5AC-4DEB-AE43-C8732945403F"
targetRef=
"fork1"
></sequenceFlow>
<parallelGateway
id=
"fork1"
></parallelGateway>
<userTask
id=
"taskA"
name=
"A"
activiti:exclusive=
"false"
activiti:assignee=
"kermit"
></userTask>
<sequenceFlow
id=
"sid-4F0D9C1E-46CD-4B47-BFA1-CC67B2A288CF"
sourceRef=
"fork1"
targetRef=
"taskA"
></sequenceFlow>
<userTask
id=
"taskB"
name=
"B"
activiti:exclusive=
"false"
activiti:assignee=
"kermit"
></userTask>
<sequenceFlow
id=
"sid-DE3ED8E8-4696-45C1-AD10-245FCCEF676E"
sourceRef=
"fork1"
targetRef=
"taskB"
></sequenceFlow>
<boundaryEvent
id=
"sid-A1F1D200-DCC6-44AB-964D-162F594A1724"
attachedToRef=
"taskA"
cancelActivity=
"false"
>
<timerEventDefinition>
<timeDuration>
PT5M
</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<sequenceFlow
id=
"sid-99FEBF72-9C07-427C-9D83-46758A6A5ECC"
sourceRef=
"sid-A1F1D200-DCC6-44AB-964D-162F594A1724"
targetRef=
"fork2"
></sequenceFlow>
<parallelGateway
id=
"fork2"
></parallelGateway>
<userTask
id=
"taskD"
name=
"D"
activiti:exclusive=
"false"
activiti:assignee=
"kermit"
></userTask>
<sequenceFlow
id=
"sid-3B8C92A0-5605-4218-8C3D-991FD817867F"
sourceRef=
"fork2"
targetRef=
"taskD"
></sequenceFlow>
<userTask
id=
"taskC"
name=
"C"
activiti:exclusive=
"false"
activiti:assignee=
"kermit"
></userTask>
<sequenceFlow
id=
"sid-5C720FB7-AAE2-4129-89C2-D65B9E9D467C"
sourceRef=
"fork2"
targetRef=
"taskC"
></sequenceFlow>
<boundaryEvent
id=
"sid-DC4DD5EF-F7F2-4FB3-A26F-75AC52593F0C"
attachedToRef=
"taskB"
cancelActivity=
"true"
>
<timerEventDefinition>
<timeDuration>
PT5M
</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<sequenceFlow
id=
"sid-1C30450C-2EF9-49FA-AE6F-F4C5605F5482"
sourceRef=
"sid-DC4DD5EF-F7F2-4FB3-A26F-75AC52593F0C"
targetRef=
"fork3"
></sequenceFlow>
<parallelGateway
id=
"fork3"
></parallelGateway>
<userTask
id=
"taskE"
name=
"E"
activiti:exclusive=
"false"
activiti:assignee=
"kermit"
></userTask>
<sequenceFlow
id=
"sid-684C089F-C914-4658-99E9-EA0C78368AE4"
sourceRef=
"fork3"
targetRef=
"taskE"
></sequenceFlow>
<userTask
id=
"taskF"
name=
"F"
activiti:exclusive=
"false"
activiti:assignee=
"kermit"
></userTask>
<sequenceFlow
id=
"sid-D95AFE80-F75A-4690-B439-FEE684323242"
sourceRef=
"fork3"
targetRef=
"taskF"
></sequenceFlow>
<boundaryEvent
id=
"sid-A8E37A3C-0556-4C3D-849D-C0B2670E9B33"
attachedToRef=
"taskD"
cancelActivity=
"false"
>
<timerEventDefinition>
<timeDuration>
PT5M
</timeDuration>
</timerEventDefinition>
</boundaryEvent>
<userTask
id=
"taskG"
name=
"G"
activiti:exclusive=
"false"
activiti:assignee=
"kermit"
></userTask>
<sequenceFlow
id=
"sid-B3302BE0-25E6-4B8A-9A98-394763BFFD57"
sourceRef=
"sid-A8E37A3C-0556-4C3D-849D-C0B2670E9B33"
targetRef=
"taskG"
></sequenceFlow>
<sequenceFlow
id=
"sid-93BBCB2F-975D-4850-A03C-F4697F754B57"
sourceRef=
"taskF"
targetRef=
"join3"
></sequenceFlow>
<sequenceFlow
id=
"sid-77D89B22-F86D-4B4A-979A-5DF67E87EB27"
sourceRef=
"taskE"
targetRef=
"join3"
></sequenceFlow>
<exclusiveGateway
id=
"sid-3C9987C3-A192-47B4-A151-1A2BF6731DB1"
></exclusiveGateway>
<sequenceFlow
id=
"sid-654D7D7F-813D-4706-8BFE-91C995E62E89"
sourceRef=
"taskB"
targetRef=
"sid-3C9987C3-A192-47B4-A151-1A2BF6731DB1"
></sequenceFlow>
<sequenceFlow
id=
"sid-85955B9A-B371-4726-86C1-51BA8A3A52A9"
sourceRef=
"join3"
targetRef=
"sid-3C9987C3-A192-47B4-A151-1A2BF6731DB1"
></sequenceFlow>
<sequenceFlow
id=
"sid-481279FB-8AC2-41DB-9ECA-FD3DB21F7FFB"
sourceRef=
"taskD"
targetRef=
"join1"
></sequenceFlow>
<sequenceFlow
id=
"sid-2D6D3AF1-841B-43C8-9CD4-811C6D052A49"
sourceRef=
"taskA"
targetRef=
"join1"
></sequenceFlow>
<sequenceFlow
id=
"sid-907B6B46-1653-4C12-9424-ADEC628CDEB4"
sourceRef=
"sid-3C9987C3-A192-47B4-A151-1A2BF6731DB1"
targetRef=
"join2"
></sequenceFlow>
<parallelGateway
id=
"join2"
></parallelGateway>
<sequenceFlow
id=
"sid-DF04F892-5C6D-42F3-A334-23B4EE55E2E0"
sourceRef=
"join1"
targetRef=
"join2"
></sequenceFlow>
<endEvent
id=
"sid-540A205A-9797-4241-976D-FC1C3F1054A7"
></endEvent>
<sequenceFlow
id=
"sid-3CA8B470-1EFA-4D08-AD92-C3EBB9207AB5"
sourceRef=
"join2"
targetRef=
"sid-540A205A-9797-4241-976D-FC1C3F1054A7"
></sequenceFlow>
<sequenceFlow
id=
"sid-BE07659D-C512-497D-B2E9-06DD7CD43596"
sourceRef=
"taskC"
targetRef=
"join1"
></sequenceFlow>
<endEvent
id=
"sid-B956592B-3523-4AEE-8859-7E15190DF6A3"
></endEvent>
<sequenceFlow
id=
"sid-9B38FA93-D212-4A0E-9D16-8BD97C66C0B7"
sourceRef=
"taskG"
targetRef=
"sid-B956592B-3523-4AEE-8859-7E15190DF6A3"
></sequenceFlow>
<inclusiveGateway
id=
"join1"
></inclusiveGateway>
<inclusiveGateway
id=
"join3"
></inclusiveGateway>
</process>
<bpmndi:BPMNDiagram
id=
"BPMNDiagram_process"
>
<bpmndi:BPMNPlane
bpmnElement=
"process"
id=
"BPMNPlane_process"
>
<bpmndi:BPMNShape
bpmnElement=
"sid-4EE6BBAE-E5AC-4DEB-AE43-C8732945403F"
id=
"BPMNShape_sid-4EE6BBAE-E5AC-4DEB-AE43-C8732945403F"
>
<omgdc:Bounds
height=
"30.0"
width=
"30.0"
x=
"76.875"
y=
"396.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"fork1"
id=
"BPMNShape_fork1"
>
<omgdc:Bounds
height=
"40.0"
width=
"40.0"
x=
"152.3125"
y=
"391.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"taskA"
id=
"BPMNShape_taskA"
>
<omgdc:Bounds
height=
"80.0"
width=
"100.0"
x=
"236.19653575831592"
y=
"300.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"taskB"
id=
"BPMNShape_taskB"
>
<omgdc:Bounds
height=
"80.0"
width=
"100.0"
x=
"237.3125"
y=
"480.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"sid-A1F1D200-DCC6-44AB-964D-162F594A1724"
id=
"BPMNShape_sid-A1F1D200-DCC6-44AB-964D-162F594A1724"
>
<omgdc:Bounds
height=
"31.0"
width=
"31.0"
x=
"270.1385536374739"
y=
"283.6875934469829"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"fork2"
id=
"BPMNShape_fork2"
>
<omgdc:Bounds
height=
"40.0"
width=
"40.0"
x=
"267.13177681873697"
y=
"150.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"taskD"
id=
"BPMNShape_taskD"
>
<omgdc:Bounds
height=
"80.0"
width=
"100.0"
x=
"390.0"
y=
"130.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"taskC"
id=
"BPMNShape_taskC"
>
<omgdc:Bounds
height=
"80.0"
width=
"100.0"
x=
"390.0"
y=
"15.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"sid-DC4DD5EF-F7F2-4FB3-A26F-75AC52593F0C"
id=
"BPMNShape_sid-DC4DD5EF-F7F2-4FB3-A26F-75AC52593F0C"
>
<omgdc:Bounds
height=
"31.0"
width=
"31.0"
x=
"264.1921956739772"
y=
"545.4831493164252"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"fork3"
id=
"BPMNShape_fork3"
>
<omgdc:Bounds
height=
"40.0"
width=
"40.0"
x=
"260.0382935109658"
y=
"615.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"taskE"
id=
"BPMNShape_taskE"
>
<omgdc:Bounds
height=
"80.0"
width=
"100.0"
x=
"345.0382935109658"
y=
"595.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"taskF"
id=
"BPMNShape_taskF"
>
<omgdc:Bounds
height=
"80.0"
width=
"100.0"
x=
"345.0"
y=
"720.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"sid-A8E37A3C-0556-4C3D-849D-C0B2670E9B33"
id=
"BPMNShape_sid-A8E37A3C-0556-4C3D-849D-C0B2670E9B33"
>
<omgdc:Bounds
height=
"31.0"
width=
"31.0"
x=
"430.2235671828906"
y=
"195.08529456958772"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"taskG"
id=
"BPMNShape_taskG"
>
<omgdc:Bounds
height=
"80.00000000000003"
width=
"100.0"
x=
"525.0"
y=
"239.99999999999997"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"sid-3C9987C3-A192-47B4-A151-1A2BF6731DB1"
id=
"BPMNShape_sid-3C9987C3-A192-47B4-A151-1A2BF6731DB1"
>
<omgdc:Bounds
height=
"40.0"
width=
"40.0"
x=
"630.0"
y=
"501.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"join2"
id=
"BPMNShape_join2"
>
<omgdc:Bounds
height=
"40.0"
width=
"40.0"
x=
"795.0"
y=
"501.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"sid-540A205A-9797-4241-976D-FC1C3F1054A7"
id=
"BPMNShape_sid-540A205A-9797-4241-976D-FC1C3F1054A7"
>
<omgdc:Bounds
height=
"28.0"
width=
"28.0"
x=
"880.0"
y=
"507.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"sid-B956592B-3523-4AEE-8859-7E15190DF6A3"
id=
"BPMNShape_sid-B956592B-3523-4AEE-8859-7E15190DF6A3"
>
<omgdc:Bounds
height=
"28.0"
width=
"28.0"
x=
"670.0"
y=
"266.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"join1"
id=
"BPMNShape_join1"
>
<omgdc:Bounds
height=
"40.0"
width=
"40.0"
x=
"720.0"
y=
"150.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape
bpmnElement=
"join3"
id=
"BPMNShape_join3"
>
<omgdc:Bounds
height=
"40.0"
width=
"40.0"
x=
"630.0"
y=
"615.0"
></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge
bpmnElement=
"sid-481279FB-8AC2-41DB-9ECA-FD3DB21F7FFB"
id=
"BPMNEdge_sid-481279FB-8AC2-41DB-9ECA-FD3DB21F7FFB"
>
<omgdi:waypoint
x=
"490.0"
y=
"170.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"720.0"
y=
"170.0"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-2D6D3AF1-841B-43C8-9CD4-811C6D052A49"
id=
"BPMNEdge_sid-2D6D3AF1-841B-43C8-9CD4-811C6D052A49"
>
<omgdi:waypoint
x=
"336.1965357583159"
y=
"340.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"740.0"
y=
"340.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"740.0"
y=
"190.0"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-5C720FB7-AAE2-4129-89C2-D65B9E9D467C"
id=
"BPMNEdge_sid-5C720FB7-AAE2-4129-89C2-D65B9E9D467C"
>
<omgdi:waypoint
x=
"287.63177681873697"
y=
"150.5"
></omgdi:waypoint>
<omgdi:waypoint
x=
"287.63177681873697"
y=
"55.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"390.0"
y=
"55.0"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-907B6B46-1653-4C12-9424-ADEC628CDEB4"
id=
"BPMNEdge_sid-907B6B46-1653-4C12-9424-ADEC628CDEB4"
>
<omgdi:waypoint
x=
"669.5"
y=
"521.5"
></omgdi:waypoint>
<omgdi:waypoint
x=
"795.5"
y=
"521.5"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-7B273A13-5CDA-46FA-9024-85EA2487FDD3"
id=
"BPMNEdge_sid-7B273A13-5CDA-46FA-9024-85EA2487FDD3"
>
<omgdi:waypoint
x=
"106.87471700209974"
y=
"411.09214041957864"
></omgdi:waypoint>
<omgdi:waypoint
x=
"152.68605076309404"
y=
"411.37355076309404"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-1C30450C-2EF9-49FA-AE6F-F4C5605F5482"
id=
"BPMNEdge_sid-1C30450C-2EF9-49FA-AE6F-F4C5605F5482"
>
<omgdi:waypoint
x=
"280.34503932923866"
y=
"577.4824192628023"
></omgdi:waypoint>
<omgdi:waypoint
x=
"280.7098665920129"
y=
"615.6715730810471"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-99FEBF72-9C07-427C-9D83-46758A6A5ECC"
id=
"BPMNEdge_sid-99FEBF72-9C07-427C-9D83-46758A6A5ECC"
>
<omgdi:waypoint
x=
"286.37227844268637"
y=
"283.6893006407042"
></omgdi:waypoint>
<omgdi:waypoint
x=
"287.75005168273145"
y=
"189.3817251360055"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-77D89B22-F86D-4B4A-979A-5DF67E87EB27"
id=
"BPMNEdge_sid-77D89B22-F86D-4B4A-979A-5DF67E87EB27"
>
<omgdi:waypoint
x=
"445.0382935109658"
y=
"635.0978620253642"
></omgdi:waypoint>
<omgdi:waypoint
x=
"630.4607784237967"
y=
"635.4607784237967"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-B3302BE0-25E6-4B8A-9A98-394763BFFD57"
id=
"BPMNEdge_sid-B3302BE0-25E6-4B8A-9A98-394763BFFD57"
>
<omgdi:waypoint
x=
"446.2235671828906"
y=
"227.08529456958772"
></omgdi:waypoint>
<omgdi:waypoint
x=
"446.2235671828906"
y=
"280.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"525.0"
y=
"280.0"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-654D7D7F-813D-4706-8BFE-91C995E62E89"
id=
"BPMNEdge_sid-654D7D7F-813D-4706-8BFE-91C995E62E89"
>
<omgdi:waypoint
x=
"337.3125"
y=
"520.2065049044915"
></omgdi:waypoint>
<omgdi:waypoint
x=
"630.417055469155"
y=
"521.417055469155"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-3B8C92A0-5605-4218-8C3D-991FD817867F"
id=
"BPMNEdge_sid-3B8C92A0-5605-4218-8C3D-991FD817867F"
>
<omgdi:waypoint
x=
"306.6943310503003"
y=
"170.43744576843662"
></omgdi:waypoint>
<omgdi:waypoint
x=
"390.0"
y=
"170.16407620616707"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-BE07659D-C512-497D-B2E9-06DD7CD43596"
id=
"BPMNEdge_sid-BE07659D-C512-497D-B2E9-06DD7CD43596"
>
<omgdi:waypoint
x=
"490.0"
y=
"55.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"740.5"
y=
"55.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"740.5"
y=
"150.5"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-4F0D9C1E-46CD-4B47-BFA1-CC67B2A288CF"
id=
"BPMNEdge_sid-4F0D9C1E-46CD-4B47-BFA1-CC67B2A288CF"
>
<omgdi:waypoint
x=
"172.8125"
y=
"391.5"
></omgdi:waypoint>
<omgdi:waypoint
x=
"172.8125"
y=
"340.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"236.19653575831592"
y=
"340.0"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-684C089F-C914-4658-99E9-EA0C78368AE4"
id=
"BPMNEdge_sid-684C089F-C914-4658-99E9-EA0C78368AE4"
>
<omgdi:waypoint
x=
"299.6216268442991"
y=
"635.4166666666666"
></omgdi:waypoint>
<omgdi:waypoint
x=
"345.0382935109658"
y=
"635.2183406113537"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-9B38FA93-D212-4A0E-9D16-8BD97C66C0B7"
id=
"BPMNEdge_sid-9B38FA93-D212-4A0E-9D16-8BD97C66C0B7"
>
<omgdi:waypoint
x=
"625.0"
y=
"280.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"670.0"
y=
"280.0"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-3CA8B470-1EFA-4D08-AD92-C3EBB9207AB5"
id=
"BPMNEdge_sid-3CA8B470-1EFA-4D08-AD92-C3EBB9207AB5"
>
<omgdi:waypoint
x=
"834.6217948717949"
y=
"521.3782051282051"
></omgdi:waypoint>
<omgdi:waypoint
x=
"880.0002839785394"
y=
"521.0891701657418"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-85955B9A-B371-4726-86C1-51BA8A3A52A9"
id=
"BPMNEdge_sid-85955B9A-B371-4726-86C1-51BA8A3A52A9"
>
<omgdi:waypoint
x=
"650.4122807017544"
y=
"615.4122807017544"
></omgdi:waypoint>
<omgdi:waypoint
x=
"650.0869565217391"
y=
"540.9130434782609"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-93BBCB2F-975D-4850-A03C-F4697F754B57"
id=
"BPMNEdge_sid-93BBCB2F-975D-4850-A03C-F4697F754B57"
>
<omgdi:waypoint
x=
"445.0"
y=
"760.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"650.5"
y=
"760.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"650.5"
y=
"654.5"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-DF04F892-5C6D-42F3-A334-23B4EE55E2E0"
id=
"BPMNEdge_sid-DF04F892-5C6D-42F3-A334-23B4EE55E2E0"
>
<omgdi:waypoint
x=
"759.5"
y=
"170.5"
></omgdi:waypoint>
<omgdi:waypoint
x=
"815.0"
y=
"170.5"
></omgdi:waypoint>
<omgdi:waypoint
x=
"815.0"
y=
"501.0"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-DE3ED8E8-4696-45C1-AD10-245FCCEF676E"
id=
"BPMNEdge_sid-DE3ED8E8-4696-45C1-AD10-245FCCEF676E"
>
<omgdi:waypoint
x=
"172.8125"
y=
"430.5"
></omgdi:waypoint>
<omgdi:waypoint
x=
"172.8125"
y=
"520.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"237.3125"
y=
"520.0"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge
bpmnElement=
"sid-D95AFE80-F75A-4690-B439-FEE684323242"
id=
"BPMNEdge_sid-D95AFE80-F75A-4690-B439-FEE684323242"
>
<omgdi:waypoint
x=
"280.5382935109658"
y=
"654.5"
></omgdi:waypoint>
<omgdi:waypoint
x=
"280.5382935109658"
y=
"760.0"
></omgdi:waypoint>
<omgdi:waypoint
x=
"345.0"
y=
"760.0"
></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录