1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.engine.simulation;
17
18 import org.apache.log4j.MDC;
19 import org.kuali.rice.coreservice.framework.parameter.ParameterService;
20 import org.kuali.rice.kew.actionitem.ActionItem;
21 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
22 import org.kuali.rice.kew.actionrequest.KimGroupRecipient;
23 import org.kuali.rice.kew.actionrequest.KimPrincipalRecipient;
24 import org.kuali.rice.kew.actionrequest.Recipient;
25 import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
26 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
27 import org.kuali.rice.kew.api.KewApiConstants;
28 import org.kuali.rice.kew.api.WorkflowRuntimeException;
29 import org.kuali.rice.kew.api.exception.DocumentSimulatedRouteException;
30 import org.kuali.rice.kew.api.exception.InvalidActionTakenException;
31 import org.kuali.rice.kew.api.exception.ResourceUnavailableException;
32 import org.kuali.rice.kew.doctype.bo.DocumentType;
33 import org.kuali.rice.kew.engine.ActivationContext;
34 import org.kuali.rice.kew.engine.EngineState;
35 import org.kuali.rice.kew.engine.OrchestrationConfig;
36 import org.kuali.rice.kew.engine.ProcessContext;
37 import org.kuali.rice.kew.engine.RouteContext;
38 import org.kuali.rice.kew.engine.StandardWorkflowEngine;
39 import org.kuali.rice.kew.engine.node.Branch;
40 import org.kuali.rice.kew.engine.node.NoOpNode;
41 import org.kuali.rice.kew.engine.node.NodeJotter;
42 import org.kuali.rice.kew.engine.node.NodeType;
43 import org.kuali.rice.kew.engine.node.ProcessDefinitionBo;
44 import org.kuali.rice.kew.engine.node.RequestsNode;
45 import org.kuali.rice.kew.engine.node.RouteNode;
46 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
47 import org.kuali.rice.kew.engine.node.SimpleNode;
48 import org.kuali.rice.kew.engine.node.service.RouteNodeService;
49 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
50 import org.kuali.rice.kew.routeheader.service.RouteHeaderService;
51 import org.kuali.rice.kew.service.KEWServiceLocator;
52 import org.kuali.rice.kew.util.PerformanceLogger;
53 import org.kuali.rice.kew.util.Utilities;
54 import org.kuali.rice.kim.api.group.Group;
55 import org.kuali.rice.kim.api.identity.Person;
56
57 import java.sql.Timestamp;
58 import java.util.ArrayList;
59 import java.util.Collections;
60 import java.util.HashMap;
61 import java.util.HashSet;
62 import java.util.Iterator;
63 import java.util.List;
64 import java.util.Map;
65 import java.util.Set;
66
67
68
69
70
71
72
73
74 public class SimulationEngine extends StandardWorkflowEngine implements SimulationWorkflowEngine {
75
76 public SimulationEngine () {
77 super();
78 }
79 public SimulationEngine(RouteNodeService routeNodeService, RouteHeaderService routeHeaderService,
80 ParameterService parameterService, OrchestrationConfig config) {
81 super(routeNodeService, routeHeaderService, parameterService, config);
82 }
83
84 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SimulationEngine.class);
85
86 private SimulationCriteria criteria;
87 private SimulationResults results;
88
89 @Override
90 public SimulationResults runSimulation(SimulationCriteria criteria) throws Exception {
91 try {
92 this.criteria = criteria;
93 this.results = new SimulationResults();
94 validateCriteria(criteria);
95 process(criteria.getDocumentId(), null);
96 return results;
97 } finally {
98
99 this.criteria = null;
100 this.results = null;
101 }
102 }
103
104 @Override
105 public void process(String documentId, String nodeInstanceId) throws InvalidActionTakenException, DocumentSimulatedRouteException {
106 RouteContext context = RouteContext.createNewRouteContext();
107 try {
108 ActivationContext activationContext = new ActivationContext(ActivationContext.CONTEXT_IS_SIMULATION);
109 if (criteria.isActivateRequests() == null) {
110 activationContext.setActivateRequests(!criteria.getActionsToTake().isEmpty());
111 } else {
112 activationContext.setActivateRequests(criteria.isActivateRequests().booleanValue());
113 }
114 context.setActivationContext(activationContext);
115 context.setEngineState(new EngineState());
116
117 Map<Object, Object> visitedForDeepCopy = new HashMap<Object, Object>();
118
119 RequestsNode.setSuppressPolicyErrors(context);
120 DocumentRouteHeaderValue document = createSimulationDocument(documentId, criteria, context, visitedForDeepCopy);
121 document.setInitiatorWorkflowId("simulation");
122 if ( (criteria.isDocumentSimulation()) && ( (document.isProcessed()) || (document.isFinal()) ) ) {
123 results.setDocument(document);
124 return;
125 }
126 routeDocumentIfNecessary(document, criteria, context, visitedForDeepCopy);
127 results.setDocument(document);
128 documentId = document.getDocumentId();
129
130
131 boolean mdcHadDocId = MDC.get("docId") != null;
132 if (!mdcHadDocId) { MDC.put("docId", documentId); }
133
134 PerformanceLogger perfLog = new PerformanceLogger(documentId);
135 try {
136 if ( LOG.isInfoEnabled() ) {
137 LOG.info("Processing document for Simulation: " + documentId);
138 }
139 List<RouteNodeInstance> activeNodeInstances = getRouteNodeService().getActiveNodeInstances(document);
140 List<RouteNodeInstance> nodeInstancesToProcess = determineNodeInstancesToProcess(activeNodeInstances, criteria.getDestinationNodeName());
141
142 context.setDocument(document);
143
144 context.setEngineState(new EngineState());
145 while (! nodeInstancesToProcess.isEmpty()) {
146 RouteNodeInstance nodeInstance = nodeInstancesToProcess.remove(0);
147 if ( !nodeInstance.isActive() ) {
148 continue;
149 }
150 NodeJotter.jotNodeInstance(context.getDocument(), nodeInstance);
151 context.setNodeInstance(nodeInstance);
152 ProcessContext processContext = processNodeInstance(context, helper);
153 if (!hasReachedCompletion(processContext, context.getEngineState().getGeneratedRequests(), nodeInstance, criteria)) {
154 if (processContext.isComplete()) {
155 if (!processContext.getNextNodeInstances().isEmpty()) {
156 nodeInstancesToProcess.addAll(processContext.getNextNodeInstances());
157 }
158 context.getActivationContext().getSimulatedActionsTaken().addAll(processPotentialActionsTaken(context, document, nodeInstance, criteria));
159 }
160 } else {
161 context.getActivationContext().getSimulatedActionsTaken().addAll(processPotentialActionsTaken(context, document, nodeInstance, criteria));
162 }
163 }
164 List<ActionRequestValue> simulatedActionRequests = context.getEngineState().getGeneratedRequests();
165 Collections.sort(simulatedActionRequests, new Utilities.RouteLogActionRequestSorter());
166 results.setSimulatedActionRequests(simulatedActionRequests);
167 results.setSimulatedActionsTaken(context.getActivationContext().getSimulatedActionsTaken());
168 } catch (InvalidActionTakenException e) {
169 throw e;
170 } catch (Exception e) {
171 String errorMsg = "Error running simulation for document " + ((criteria.isDocumentSimulation()) ? "id " + documentId.toString() : "type " + criteria.getDocumentTypeName());
172 LOG.error(errorMsg,e);
173 throw new DocumentSimulatedRouteException(errorMsg, e);
174 } finally {
175 perfLog.log("Time to run simulation.");
176 RouteContext.clearCurrentRouteContext();
177
178 if (!mdcHadDocId) { MDC.remove("docID"); }
179 }
180 } finally {
181 RouteContext.releaseCurrentRouteContext();
182 }
183 }
184
185
186
187
188
189
190
191 private List<RouteNodeInstance> determineNodeInstancesToProcess(List<RouteNodeInstance> activeNodeInstances, String nodeName) throws InvalidActionTakenException {
192 if (org.apache.commons.lang.StringUtils.isEmpty(nodeName)) {
193 return activeNodeInstances;
194 }
195 List<RouteNodeInstance> nodeInstancesToProcess = new ArrayList<RouteNodeInstance>();
196 for (RouteNodeInstance nodeInstance : activeNodeInstances) {
197 if (nodeName.equals(nodeInstance.getName())) {
198
199 return new ArrayList<RouteNodeInstance>();
200 } else {
201 if (isNodeNameInPath(nodeName, nodeInstance)) {
202 nodeInstancesToProcess.add(nodeInstance);
203 }
204 }
205 }
206 if (nodeInstancesToProcess.size() == 0) {
207 throw new InvalidActionTakenException("Could not locate a node with the given name in the blanket approval path '" + nodeName + "'. " +
208 "The document is probably already passed the specified node or does not contain the node.");
209 }
210 return nodeInstancesToProcess;
211 }
212
213 private boolean isNodeNameInPath(String nodeName, RouteNodeInstance nodeInstance) {
214 boolean isInPath = false;
215 for (Iterator<RouteNode> iterator = nodeInstance.getRouteNode().getNextNodes().iterator(); iterator.hasNext();) {
216 RouteNode nextNode = (RouteNode) iterator.next();
217 isInPath = isInPath || isNodeNameInPath(nodeName, nextNode, new HashSet<String>());
218 }
219 return isInPath;
220 }
221
222 private boolean isNodeNameInPath(String nodeName, RouteNode node, Set<String> inspected) {
223 boolean isInPath = !inspected.contains(node.getRouteNodeId()) && node.getRouteNodeName().equals(nodeName);
224 inspected.add(node.getRouteNodeId());
225 if (helper.isSubProcessNode(node)) {
226 ProcessDefinitionBo subProcess = node.getDocumentType().getNamedProcess(node.getRouteNodeName());
227 RouteNode subNode = subProcess.getInitialRouteNode();
228 if (subNode != null) {
229 isInPath = isInPath || isNodeNameInPath(nodeName, subNode, inspected);
230 }
231 }
232 for (Iterator<RouteNode> iterator = node.getNextNodes().iterator(); iterator.hasNext();) {
233 RouteNode nextNode = (RouteNode) iterator.next();
234 isInPath = isInPath || isNodeNameInPath(nodeName, nextNode, inspected);
235 }
236 return isInPath;
237 }
238
239 private boolean hasReachedCompletion(ProcessContext processContext, List actionRequests, RouteNodeInstance nodeInstance, SimulationCriteria criteria) {
240 if (!criteria.getDestinationRecipients().isEmpty()) {
241 for (Iterator iterator = actionRequests.iterator(); iterator.hasNext();) {
242 ActionRequestValue request = (ActionRequestValue) iterator.next();
243 for (Iterator<Recipient> userIt = criteria.getDestinationRecipients().iterator(); userIt.hasNext();) {
244 Recipient recipient = (Recipient) userIt.next();
245 if (request.isRecipientRoutedRequest(recipient)) {
246 if ( (org.apache.commons.lang.StringUtils.isEmpty(criteria.getDestinationNodeName())) || (criteria.getDestinationNodeName().equals(request.getNodeInstance().getName())) ) {
247 return true;
248 }
249 }
250 }
251 }
252 }
253 return (org.apache.commons.lang.StringUtils.isEmpty(criteria.getDestinationNodeName()) && processContext.isComplete() && processContext.getNextNodeInstances().isEmpty())
254 || nodeInstance.getRouteNode().getRouteNodeName().equals(criteria.getDestinationNodeName());
255 }
256
257 private List<ActionTakenValue> processPotentialActionsTaken(RouteContext routeContext, DocumentRouteHeaderValue routeHeader, RouteNodeInstance justProcessedNode, SimulationCriteria criteria) {
258 List<ActionTakenValue> actionsTaken = new ArrayList<ActionTakenValue>();
259 List<ActionRequestValue> requestsToCheck = new ArrayList<ActionRequestValue>();
260 requestsToCheck.addAll(routeContext.getEngineState().getGeneratedRequests());
261 requestsToCheck.addAll(routeHeader.getActionRequests());
262 List<ActionRequestValue> pendingActionRequestValues = getCriteriaActionsToDoByNodeName(requestsToCheck, justProcessedNode.getName());
263 List<ActionTakenValue> actionsToTakeForNode = generateActionsToTakeForNode(justProcessedNode.getName(), routeHeader, criteria, pendingActionRequestValues);
264
265 for (ActionTakenValue actionTaken : actionsToTakeForNode)
266 {
267 KEWServiceLocator.getActionRequestService().deactivateRequests(actionTaken, pendingActionRequestValues, routeContext.getActivationContext());
268 actionsTaken.add(actionTaken);
269
270 }
271 return actionsTaken;
272 }
273
274 private List<ActionTakenValue> generateActionsToTakeForNode(String nodeName, DocumentRouteHeaderValue routeHeader, SimulationCriteria criteria, List<ActionRequestValue> pendingActionRequests) {
275 List<ActionTakenValue> actions = new ArrayList<ActionTakenValue>();
276 if ( (criteria.getActionsToTake() != null) && (!criteria.getActionsToTake().isEmpty()) ) {
277 for (SimulationActionToTake simAction : criteria.getActionsToTake()) {
278 if (nodeName.equals(simAction.getNodeName())) {
279 actions.add(createDummyActionTaken(routeHeader, simAction.getUser(), simAction.getActionToPerform(), findDelegatorForActionRequests(pendingActionRequests)));
280 }
281 }
282 }
283 return actions;
284 }
285
286 private List<ActionRequestValue> getCriteriaActionsToDoByNodeName(List<ActionRequestValue> generatedRequests, String nodeName) {
287 List<ActionRequestValue> requests = new ArrayList<ActionRequestValue>();
288 for (ActionRequestValue request : generatedRequests) {
289 if ( (request.isPending()) && request.getNodeInstance() != null && nodeName.equals(request.getNodeInstance().getName())) {
290 requests.add(request);
291 }
292 }
293 return requests;
294 }
295
296 private void validateCriteria(SimulationCriteria criteria) {
297 if (criteria.getDocumentId() == null && org.apache.commons.lang.StringUtils.isEmpty(criteria.getDocumentTypeName())) {
298 throw new IllegalArgumentException("No document type name or document id given, cannot simulate a document without a document type name or a document id.");
299 }
300 if (criteria.getXmlContent() == null) {
301 criteria.setXmlContent("");
302 }
303 }
304
305
306
307
308
309
310
311
312 private DocumentRouteHeaderValue createSimulationDocument(String documentId, SimulationCriteria criteria, RouteContext context, Map<Object, Object> visitedForDeepCopy) {
313 DocumentRouteHeaderValue document = null;
314 if (criteria.isDocumentSimulation()) {
315 document = getDocumentForSimulation(documentId, visitedForDeepCopy);
316 if (!org.apache.commons.lang.StringUtils.isEmpty(criteria.getXmlContent())) {
317 document.setDocContent(criteria.getXmlContent());
318 }
319 } else if (criteria.isDocumentTypeSimulation()) {
320 DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(criteria.getDocumentTypeName());
321 if (documentType == null) {
322 throw new IllegalArgumentException("Specified document type could not be found for name '"+criteria.getDocumentTypeName()+"'");
323 }
324 documentId = context.getEngineState().getNextSimulationId();
325 document = new DocumentRouteHeaderValue();
326 context.setDocument(document);
327 document.setDocumentId(documentId);
328 document.setCreateDate(new Timestamp(System.currentTimeMillis()));
329 document.setDocContent(criteria.getXmlContent());
330 document.setDocRouteLevel(new Integer(0));
331 document.setDocumentTypeId(documentType.getDocumentTypeId());
332 document.setDocRouteStatus(KewApiConstants.ROUTE_HEADER_INITIATED_CD);
333 initializeDocument(document);
334 }
335 if (document == null) {
336 throw new IllegalArgumentException("Workflow simulation engine could not locate document with id "+documentId);
337 }
338 for (ActionRequestValue actionRequest : document.getActionRequests()) {
339 actionRequest = actionRequest.deepCopy(visitedForDeepCopy);
340 document.getSimulatedActionRequests().add(actionRequest);
341 for (ActionItem actionItem : actionRequest.getActionItems()) {
342 actionRequest.getSimulatedActionItems().add(actionItem.deepCopy(visitedForDeepCopy));
343 }
344 }
345 context.setDocument(document);
346 installSimulationNodeInstances(context, criteria);
347 return document;
348 }
349
350 private DocumentRouteHeaderValue getDocumentForSimulation(String documentId, Map<Object, Object> visitedForDeepCopy) {
351 DocumentRouteHeaderValue document = getRouteHeaderService().getRouteHeader(documentId);
352 return document.deepCopy(visitedForDeepCopy);
353 }
354
355 private void routeDocumentIfNecessary(DocumentRouteHeaderValue document, SimulationCriteria criteria, RouteContext routeContext, Map<Object, Object> visitedForDeepCopy) throws InvalidActionTakenException {
356 if (criteria.getRoutingUser() != null) {
357 ActionTakenValue action = createDummyActionTaken(document, criteria.getRoutingUser(), KewApiConstants.ACTION_TAKEN_ROUTED_CD, null);
358 routeContext.getActivationContext().getSimulatedActionsTaken().add(action);
359 simulateDocumentRoute(action, document, criteria.getRoutingUser(), routeContext, visitedForDeepCopy);
360 }
361 }
362
363
364
365
366
367
368 private void installSimulationNodeInstances(RouteContext context, SimulationCriteria criteria) {
369 DocumentRouteHeaderValue document = context.getDocument();
370 List<RouteNode> simulationNodes = new ArrayList<RouteNode>();
371 if (!criteria.getNodeNames().isEmpty()) {
372 for (String nodeName : criteria.getNodeNames()) {
373 if ( LOG.isDebugEnabled() ) {
374 LOG.debug("Installing simulation starting node '"+nodeName+"'");
375 }
376 List<RouteNode> nodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodes(document.getDocumentType(), true);
377 boolean foundNode = false;
378 for (RouteNode node : nodes) {
379 if (node.getRouteNodeName().equals(nodeName)) {
380 simulationNodes.add(node);
381 foundNode = true;
382 break;
383 }
384 }
385 if (!foundNode) {
386 throw new IllegalArgumentException("Could not find node on the document type for the given name '"+nodeName+"'");
387 }
388 }
389 } else if (!criteria.getRuleTemplateNames().isEmpty()) {
390 List<RouteNode> nodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodes(document.getDocumentType(), true);
391 for (String ruleTemplateName : criteria.getRuleTemplateNames()) {
392 boolean foundNode = false;
393 for (RouteNode node : nodes) {
394 String routeMethodName = node.getRouteMethodName();
395 if (node.isFlexRM() && ruleTemplateName.equals(routeMethodName)) {
396 simulationNodes.add(node);
397 foundNode = true;
398 break;
399 }
400 }
401 if (!foundNode) {
402 throw new IllegalArgumentException("Could not find node on the document type with the given rule template name '"+ruleTemplateName+"'");
403 }
404 }
405 } else if (criteria.isFlattenNodes()) {
406
407 List<RouteNode> nodes = KEWServiceLocator.getRouteNodeService().getFlattenedNodes(document.getDocumentType(), true);
408 for ( RouteNode node : nodes ) {
409 try {
410 if ( NodeType.fromNode( node ).isTypeOf( SimpleNode.class )
411 && !NodeType.fromNode( node ).isTypeOf( NoOpNode.class ) ) {
412 simulationNodes.add(node);
413 }
414 } catch (ResourceUnavailableException ex) {
415 LOG.warn( "Unable to determine node type in simulator: " + ex.getMessage() );
416 }
417 }
418 } else {
419
420 return;
421 }
422
423
424 Branch defaultBranch = document.getInitialRouteNodeInstances().get(0).getBranch();
425
426 document.getInitialRouteNodeInstances().clear();
427
428 RouteNodeInstance currentNodeInstance = null;
429 for (RouteNode simulationNode : simulationNodes) {
430 RouteNodeInstance nodeInstance = helper.getNodeFactory().createRouteNodeInstance(document.getDocumentId(), simulationNode);
431 nodeInstance.setBranch(defaultBranch);
432 if (currentNodeInstance == null) {
433 document.getInitialRouteNodeInstances().add(nodeInstance);
434 nodeInstance.setActive(true);
435 saveNode(context, nodeInstance);
436 } else {
437 currentNodeInstance.addNextNodeInstance(nodeInstance);
438 saveNode(context, currentNodeInstance);
439 }
440 currentNodeInstance = nodeInstance;
441 }
442 installSimulationTerminationNode(context, document.getDocumentType(), currentNodeInstance);
443 }
444
445 private void installSimulationTerminationNode(RouteContext context, DocumentType documentType, RouteNodeInstance lastNodeInstance) {
446 RouteNode terminationNode = new RouteNode();
447 terminationNode.setDocumentType(documentType);
448 terminationNode.setDocumentTypeId(documentType.getDocumentTypeId());
449 terminationNode.setNodeType(NoOpNode.class.getName());
450 terminationNode.setRouteNodeName("SIMULATION_TERMINATION_NODE");
451 RouteNodeInstance terminationNodeInstance = helper.getNodeFactory().createRouteNodeInstance(lastNodeInstance.getDocumentId(), terminationNode);
452 terminationNodeInstance.setBranch(lastNodeInstance.getBranch());
453 lastNodeInstance.addNextNodeInstance(terminationNodeInstance);
454 saveNode(context, lastNodeInstance);
455 }
456
457
458 private void simulateDocumentRoute(ActionTakenValue actionTaken, DocumentRouteHeaderValue document, Person user, RouteContext routeContext, Map<Object, Object> visitedForDeepCopy) throws InvalidActionTakenException {
459 if (document.isRouted()) {
460 throw new WorkflowRuntimeException("Document can not simulate a route if it has already been routed");
461 }
462 ActionRequestService actionRequestService = KEWServiceLocator.getActionRequestService();
463
464 List<ActionRequestValue> actionRequests = new ArrayList<ActionRequestValue>();
465 for (ActionRequestValue actionRequest : actionRequestService.findPendingByDoc(document.getDocumentId())) {
466 ActionRequestValue arv = actionRequest.deepCopy(visitedForDeepCopy);
467 for (ActionItem actionItem : arv.getActionItems()) {
468 arv.getSimulatedActionItems().add(actionItem.deepCopy(visitedForDeepCopy));
469 }
470 actionRequests.add(arv);
471 }
472 LOG.debug("Simulate Deactivating all pending action requests");
473
474 for (ActionRequestValue actionRequest : actionRequests) {
475
476 if ( (user.getPrincipalId().equals(actionRequest.getPrincipalId())) && (actionRequest.isActive()) ) {
477 actionRequestService.deactivateRequest(actionTaken, actionRequest, routeContext.getActivationContext());
478 }
479
480 else if (KewApiConstants.SAVED_REQUEST_RESPONSIBILITY_ID.equals(actionRequest.getResponsibilityId())) {
481 actionRequestService.deactivateRequest(actionTaken, actionRequest, routeContext.getActivationContext());
482 }
483 }
484
485 document.markDocumentEnroute();
486 }
487
488 private ActionTakenValue createDummyActionTaken(DocumentRouteHeaderValue routeHeader, Person userToPerformAction, String actionToPerform, Recipient delegator) {
489 ActionTakenValue val = new ActionTakenValue();
490 val.setActionTaken(actionToPerform);
491 if (KewApiConstants.ACTION_TAKEN_ROUTED_CD.equals(actionToPerform)) {
492 val.setActionTaken(KewApiConstants.ACTION_TAKEN_COMPLETED_CD);
493 }
494 val.setAnnotation("");
495 val.setDocVersion(routeHeader.getDocVersion());
496 val.setDocumentId(routeHeader.getDocumentId());
497 val.setPrincipalId(userToPerformAction.getPrincipalId());
498
499 if (delegator != null) {
500 if (delegator instanceof KimPrincipalRecipient) {
501 val.setDelegatorPrincipalId(((KimPrincipalRecipient) delegator).getPrincipalId());
502 } else if (delegator instanceof KimGroupRecipient) {
503 Group group = ((KimGroupRecipient) delegator).getGroup();
504 val.setDelegatorGroupId(group.getId());
505 } else{
506 throw new IllegalArgumentException("Invalid Recipient type received: " + delegator.getClass().getName());
507 }
508 }
509 val.setCurrentIndicator(Boolean.TRUE);
510 return val;
511 }
512
513
514
515
516
517
518 private Recipient findDelegatorForActionRequests(List<ActionRequestValue> actionRequests) {
519 return KEWServiceLocator.getActionRequestService().findDelegator(actionRequests);
520 }
521
522
523
524
525
526
527
528 @Override
529 protected RouteNodeInstance saveNode(RouteContext context, RouteNodeInstance nodeInstance) {
530
531 if (nodeInstance.getRouteNodeInstanceId() == null) {
532 nodeInstance.setRouteNodeInstanceId(context.getEngineState().getNextSimulationId());
533 }
534
535
536 for (RouteNodeInstance routeNodeInstance : nodeInstance.getNextNodeInstances()) {
537 if (routeNodeInstance.getRouteNodeInstanceId() == null) {
538 routeNodeInstance.setRouteNodeInstanceId(context.getEngineState().getNextSimulationId());
539 }
540 }
541 if (nodeInstance.getProcess() != null && nodeInstance.getProcess().getRouteNodeInstanceId() == null) {
542 nodeInstance.getProcess().setRouteNodeInstanceId(context.getEngineState().getNextSimulationId());
543 }
544 if (nodeInstance.getBranch() != null && nodeInstance.getBranch().getBranchId() == null) {
545 nodeInstance.getBranch().setBranchId(context.getEngineState().getNextSimulationId());
546 }
547 return nodeInstance;
548 }
549
550 }