1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.kuali.rice.kew.engine;
18
19 import org.apache.log4j.MDC;
20 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
21 import org.kuali.rice.kew.engine.node.*;
22 import org.kuali.rice.kew.engine.node.Process;
23 import org.kuali.rice.kew.engine.node.service.RouteNodeService;
24 import org.kuali.rice.kew.engine.transition.Transition;
25 import org.kuali.rice.kew.engine.transition.TransitionEngine;
26 import org.kuali.rice.kew.engine.transition.TransitionEngineFactory;
27 import org.kuali.rice.kew.exception.InvalidActionTakenException;
28 import org.kuali.rice.kew.exception.RouteManagerException;
29 import org.kuali.rice.kew.exception.WorkflowException;
30 import org.kuali.rice.kew.postprocessor.*;
31 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
32 import org.kuali.rice.kew.routeheader.service.RouteHeaderService;
33 import org.kuali.rice.kew.service.KEWServiceLocator;
34 import org.kuali.rice.kew.util.KEWConstants;
35 import org.kuali.rice.kew.util.PerformanceLogger;
36 import org.kuali.rice.kew.util.Utilities;
37 import org.kuali.rice.kns.util.KNSConstants;
38
39 import java.util.*;
40
41
42
43
44
45
46
47
48
49 public class StandardWorkflowEngine implements WorkflowEngine {
50
51 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(StandardWorkflowEngine.class);
52
53 protected RouteHelper helper = new RouteHelper();
54 private boolean runPostProcessorLogic = true;
55
56 public StandardWorkflowEngine() {}
57
58 public StandardWorkflowEngine(boolean runPostProcessorLogic) {
59 setRunPostProcessorLogic(runPostProcessorLogic);
60 }
61
62 public void setRunPostProcessorLogic(boolean runPostProcessorLogic) {
63 this.runPostProcessorLogic = runPostProcessorLogic;
64 }
65
66 public boolean isRunPostProcessorLogic() {
67 return this.runPostProcessorLogic;
68 }
69
70 public void process(Long documentId, Long nodeInstanceId) throws Exception {
71 if (documentId == null) {
72 throw new IllegalArgumentException("Cannot process a null document id.");
73 }
74 MDC.put("docId", documentId);
75 boolean success = true;
76 RouteContext context = RouteContext.createNewRouteContext();
77 try {
78 if ( LOG.isInfoEnabled() ) {
79 LOG.info("Aquiring lock on document " + documentId);
80 }
81 KEWServiceLocator.getRouteHeaderService().lockRouteHeader(documentId, true);
82 if ( LOG.isInfoEnabled() ) {
83 LOG.info("Aquired lock on document " + documentId);
84 }
85
86 DocumentRouteHeaderValue document = getRouteHeaderService().getRouteHeader(documentId);
87 context.setDocument(document);
88 lockAdditionalDocuments(document);
89
90 if ( LOG.isInfoEnabled() ) {
91 LOG.info("Processing document: " + documentId + " : " + nodeInstanceId);
92 }
93
94 try {
95 document = notifyPostProcessorBeforeProcess(document, nodeInstanceId);
96 context.setDocument(document);
97 } catch (Exception e) {
98 LOG.warn("Problems contacting PostProcessor before engine process", e);
99 throw new RouteManagerException("Problems contacting PostProcessor: " + e.getMessage());
100 }
101 if (!document.isRoutable()) {
102 LOG.debug("Document not routable so returning with doing no action");
103 return;
104 }
105 List nodeInstancesToProcess = new LinkedList();
106 if (nodeInstanceId == null) {
107
108 nodeInstancesToProcess.addAll(RouteNodeUtils.getActiveNodeInstances(document));
109 } else {
110 RouteNodeInstance instanceNode = RouteNodeUtils.findRouteNodeInstanceById(nodeInstanceId,document);
111 if (instanceNode == null) {
112 throw new IllegalArgumentException("Invalid node instance id: " + nodeInstanceId);
113 }
114 nodeInstancesToProcess.add(instanceNode);
115 }
116
117 context.setEngineState(new EngineState());
118 ProcessContext processContext = new ProcessContext(true, nodeInstancesToProcess);
119 try {
120 while (!nodeInstancesToProcess.isEmpty()) {
121 context.setNodeInstance((RouteNodeInstance) nodeInstancesToProcess.remove(0));
122 processContext = processNodeInstance(context, helper);
123 if (processContext.isComplete() && !processContext.getNextNodeInstances().isEmpty()) {
124 nodeInstancesToProcess.addAll(processContext.getNextNodeInstances());
125 }
126 }
127 context.setDocument(nodePostProcess(context));
128 } catch (Exception e) {
129 success = false;
130
131
132 throw new RouteManagerException(e, context);
133 }
134 } finally {
135 if ( LOG.isInfoEnabled() ) {
136 LOG.info((success ? "Successfully processed" : "Failed to process") + " document: " + documentId + " : " + nodeInstanceId);
137 }
138 try {
139 notifyPostProcessorAfterProcess(context.getDocument(), nodeInstanceId, success);
140 } catch (Exception e) {
141 LOG.warn("Problems contacting PostProcessor after engine process", e);
142 throw new RouteManagerException("Problems contacting PostProcessor: " + e.getMessage(), context);
143 }
144 RouteContext.clearCurrentRouteContext();
145 MDC.remove("docId");
146 }
147 }
148
149 protected ProcessContext processNodeInstance(RouteContext context, RouteHelper helper) throws Exception {
150 RouteNodeInstance nodeInstance = context.getNodeInstance();
151 if ( LOG.isDebugEnabled() ) {
152 LOG.debug("Processing node instance: " + nodeInstance.getRouteNode().getRouteNodeName());
153 }
154 if (checkAssertions(context)) {
155
156 return new ProcessContext();
157 }
158 TransitionEngine transitionEngine = TransitionEngineFactory.createTransitionEngine(nodeInstance);
159 ProcessResult processResult = transitionEngine.isComplete(context);
160 nodeInstance.setInitial(false);
161
162
163
164 if (processResult.isComplete()) {
165 if ( LOG.isDebugEnabled() ) {
166 LOG.debug("Routing node has completed: " + nodeInstance.getRouteNode().getRouteNodeName());
167 }
168
169 context.getEngineState().getCompleteNodeInstances().add(nodeInstance.getRouteNodeInstanceId());
170 List nextNodeCandidates = invokeTransition(context, context.getNodeInstance(), processResult, transitionEngine);
171
172
173
174
175
176
177 List<RouteNodeInstance> nodesToActivate = new ArrayList<RouteNodeInstance>();
178 if (!nextNodeCandidates.isEmpty()) {
179
180
181
182 ArrayList<RouteNodeInstance> nextNodeInstances = new ArrayList<RouteNodeInstance>();
183
184 for (Iterator nextIt = nextNodeCandidates.iterator(); nextIt.hasNext();) {
185 RouteNodeInstance nextNodeInstance = (RouteNodeInstance) nextIt.next();
186 transitionEngine = TransitionEngineFactory.createTransitionEngine(nextNodeInstance);
187 RouteNodeInstance currentNextNodeInstance = nextNodeInstance;
188 nextNodeInstance = transitionEngine.transitionTo(nextNodeInstance, context);
189
190
191 if (!currentNextNodeInstance.equals(nextNodeInstance)) {
192 currentNextNodeInstance.getPreviousNodeInstances().remove(nodeInstance);
193 }
194
195
196
197
198
199
200
201
202
203 nextNodeInstance.getPreviousNodeInstances().remove(nodeInstance);
204 nextNodeInstances.add(nextNodeInstance);
205 handleBackwardCompatibility(context, nextNodeInstance);
206
207 notifyNodeChange(context, nextNodeInstance);
208 nodesToActivate.add(nextNodeInstance);
209
210 }
211
212 for (RouteNodeInstance nextNodeInstance : nextNodeInstances) {
213 nodeInstance.addNextNodeInstance(nextNodeInstance);
214 }
215 }
216
217
218 nodeInstance.setComplete(true);
219 nodeInstance.setActive(false);
220
221 for (RouteNodeInstance nodeToActivate : nodesToActivate) {
222 nodeToActivate.setActive(true);
223 }
224 } else {
225 nodeInstance.setComplete(false);
226 }
227
228 saveNode(context, nodeInstance);
229 return new ProcessContext(nodeInstance.isComplete(), nodeInstance.getNextNodeInstances());
230 }
231
232
233
234
235
236
237
238
239 private boolean checkAssertions(RouteContext context) throws Exception {
240 if (context.getNodeInstance().isComplete()) {
241 if ( LOG.isDebugEnabled() ) {
242 LOG.debug("The node has already been completed: " + context.getNodeInstance().getRouteNode().getRouteNodeName());
243 }
244 return true;
245 }
246 if (isRunawayProcessDetected(context.getEngineState())) {
247
248 throw new WorkflowException("Detected runaway process.");
249 }
250 return false;
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280 private List invokeTransition(RouteContext context, RouteNodeInstance nodeInstance, ProcessResult processResult, TransitionEngine transitionEngine) throws Exception {
281 List nextNodeInstances = nodeInstance.getNextNodeInstances();
282 if (nextNodeInstances.isEmpty()) {
283 Transition result = transitionEngine.transitionFrom(context, processResult);
284 nextNodeInstances = result.getNextNodeInstances();
285 if (nextNodeInstances.isEmpty() && nodeInstance.isInProcess()) {
286 transitionEngine = TransitionEngineFactory.createTransitionEngine(nodeInstance.getProcess());
287 context.setNodeInstance(nodeInstance);
288 nextNodeInstances = invokeTransition(context, nodeInstance.getProcess(), processResult, transitionEngine);
289 }
290 }
291 return nextNodeInstances;
292 }
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309 private void notifyNodeChange(RouteContext context, RouteNodeInstance nextNodeInstance) throws Exception {
310 if (!context.isSimulation()) {
311 RouteNodeInstance nodeInstance = context.getNodeInstance();
312
313 String nextStatus = nodeInstance.getRouteNode().getNextDocStatus();
314 if (nextStatus != null && nextStatus.length() > 0){
315 context.getDocument().updateAppDocStatus(nextStatus);
316 }
317
318 DocumentRouteLevelChange event = new DocumentRouteLevelChange(context.getDocument().getRouteHeaderId(), context.getDocument().getAppDocId(), CompatUtils.getLevelForNode(context.getDocument().getDocumentType(), context.getNodeInstance()
319 .getRouteNode().getRouteNodeName()), CompatUtils.getLevelForNode(context.getDocument().getDocumentType(), nextNodeInstance.getRouteNode().getRouteNodeName()), nodeInstance.getRouteNode().getRouteNodeName(), nextNodeInstance
320 .getRouteNode().getRouteNodeName(), nodeInstance.getRouteNodeInstanceId(), nextNodeInstance.getRouteNodeInstanceId());
321 context.setDocument(notifyPostProcessor(context.getDocument(), nodeInstance, event));
322 }
323 }
324
325 private void handleBackwardCompatibility(RouteContext context, RouteNodeInstance nextNodeInstance) {
326 context.getDocument().setDocRouteLevel(new Integer(context.getDocument().getDocRouteLevel().intValue() + 1));
327
328
329
330
331
332 saveDocument(context);
333 }
334
335 private void saveDocument(RouteContext context) {
336 if (!context.isSimulation()) {
337 getRouteHeaderService().saveRouteHeader(context.getDocument());
338 }
339 }
340
341 private void saveBranch(RouteContext context, Branch branch) {
342 if (!context.isSimulation()) {
343 KEWServiceLocator.getRouteNodeService().save(branch);
344 }
345 }
346
347 protected void saveNode(RouteContext context, RouteNodeInstance nodeInstance) {
348 if (!context.isSimulation()) {
349 getRouteNodeService().save(nodeInstance);
350 } else {
351
352
353 for (Iterator<RouteNodeInstance> iterator = nodeInstance.getNextNodeInstances().iterator(); iterator.hasNext();) {
354 RouteNodeInstance routeNodeInstance = (RouteNodeInstance) iterator.next();
355 if (routeNodeInstance.getRouteNodeInstanceId() == null) {
356 routeNodeInstance.setRouteNodeInstanceId(context.getEngineState().getNextSimulationId());
357 }
358 }
359 if (nodeInstance.getProcess() != null && nodeInstance.getProcess().getRouteNodeInstanceId() == null) {
360 nodeInstance.getProcess().setRouteNodeInstanceId(context.getEngineState().getNextSimulationId());
361 }
362 if (nodeInstance.getBranch() != null && nodeInstance.getBranch().getBranchId() == null) {
363 nodeInstance.getBranch().setBranchId(context.getEngineState().getNextSimulationId());
364 }
365 }
366 }
367
368
369
370 protected DocumentRouteHeaderValue nodePostProcess(RouteContext context) throws InvalidActionTakenException {
371 DocumentRouteHeaderValue document = context.getDocument();
372 Collection<RouteNodeInstance> activeNodes = getRouteNodeService().getActiveNodeInstances(document.getRouteHeaderId());
373 boolean moreNodes = false;
374 for (Iterator<RouteNodeInstance> iterator = activeNodes.iterator(); iterator.hasNext();) {
375 RouteNodeInstance nodeInstance = (RouteNodeInstance) iterator.next();
376 moreNodes = moreNodes || !nodeInstance.isComplete();
377 }
378 List pendingRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getRouteHeaderId());
379 boolean activeApproveRequests = false;
380 boolean activeAckRequests = false;
381 for (Iterator iterator = pendingRequests.iterator(); iterator.hasNext();) {
382 ActionRequestValue request = (ActionRequestValue) iterator.next();
383 activeApproveRequests = request.isApproveOrCompleteRequest() || activeApproveRequests;
384 activeAckRequests = request.isAcknowledgeRequest() || activeAckRequests;
385 }
386
387 if (!document.isProcessed() && (!moreNodes || !activeApproveRequests)) {
388 if ( LOG.isDebugEnabled() ) {
389 LOG.debug("No more nodes for this document " + document.getRouteHeaderId());
390 }
391
392 checkDefaultApprovalPolicy(document);
393 LOG.debug("Marking document approved");
394
395 DocumentRouteStatusChange event = new DocumentRouteStatusChange(document.getRouteHeaderId(), document.getAppDocId(), document.getDocRouteStatus(), KEWConstants.ROUTE_HEADER_APPROVED_CD);
396 document.markDocumentApproved();
397
398 notifyPostProcessor(context, event);
399
400 LOG.debug("Marking document processed");
401 event = new DocumentRouteStatusChange(document.getRouteHeaderId(), document.getAppDocId(), document.getDocRouteStatus(), KEWConstants.ROUTE_HEADER_PROCESSED_CD);
402 document.markDocumentProcessed();
403
404 notifyPostProcessor(context, event);
405 }
406
407
408
409 if (document.isProcessed()) {
410 DocumentRouteStatusChange event = new DocumentRouteStatusChange(document.getRouteHeaderId(), document.getAppDocId(), document.getDocRouteStatus(), KEWConstants.ROUTE_HEADER_FINAL_CD);
411 List actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getRouteHeaderId());
412 if (actionRequests.isEmpty()) {
413 document.markDocumentFinalized();
414
415 notifyPostProcessor(context, event);
416 } else {
417 boolean markFinalized = true;
418 for (Iterator iter = actionRequests.iterator(); iter.hasNext();) {
419 ActionRequestValue actionRequest = (ActionRequestValue) iter.next();
420 if (KEWConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ.equals(actionRequest.getActionRequested())) {
421 markFinalized = false;
422 }
423 }
424 if (markFinalized) {
425 document.markDocumentFinalized();
426
427 this.notifyPostProcessor(context, event);
428 }
429 }
430 }
431 saveDocument(context);
432 return document;
433 }
434
435
436
437
438
439
440
441
442
443
444
445
446
447 private void checkDefaultApprovalPolicy(DocumentRouteHeaderValue document) throws RouteManagerException {
448 if (!document.getDocumentType().getDefaultApprovePolicy().getPolicyValue().booleanValue()) {
449 LOG.debug("Checking if any requests have been generated for the document");
450 List requests = KEWServiceLocator.getActionRequestService().findAllActionRequestsByRouteHeaderId(document.getRouteHeaderId());
451 boolean approved = false;
452 for (Iterator iter = requests.iterator(); iter.hasNext();) {
453 ActionRequestValue actionRequest = (ActionRequestValue) iter.next();
454 if (actionRequest.isApproveOrCompleteRequest() && actionRequest.isDone()) {
455
456
457
458
459
460
461 LOG.debug("Found at least one processed approve request so document can be approved");
462 approved = true;
463 break;
464 }
465 }
466 if (!approved) {
467 LOG.debug("Document requires at least one request and none are present");
468
469 throw new RouteManagerException("Document should have generated at least one approval request.");
470 }
471 }
472 }
473
474 private DocumentRouteHeaderValue notifyPostProcessor(RouteContext context, DocumentRouteStatusChange event) {
475 DocumentRouteHeaderValue document = context.getDocument();
476 if (context.isSimulation()) {
477 return document;
478 }
479 if (hasContactedPostProcessor(context, event)) {
480 return document;
481 }
482 Long routeHeaderId = event.getRouteHeaderId();
483 PerformanceLogger performanceLogger = new PerformanceLogger(routeHeaderId);
484 ProcessDocReport processReport = null;
485 PostProcessor postProc = null;
486 try {
487
488 if (!isRunPostProcessorLogic()) {
489 postProc = new DefaultPostProcessor();
490 } else {
491 postProc = document.getDocumentType().getPostProcessor();
492 }
493 } catch (Exception e) {
494 LOG.error("Error retrieving PostProcessor for document " + document.getRouteHeaderId(), e);
495 throw new RouteManagerException("Error retrieving PostProcessor for document " + document.getRouteHeaderId(), e);
496 }
497 try {
498 processReport = postProc.doRouteStatusChange(event);
499 } catch (Exception e) {
500 LOG.error("Error notifying post processor", e);
501 throw new RouteManagerException(KEWConstants.POST_PROCESSOR_FAILURE_MESSAGE, e);
502 } finally {
503 performanceLogger.log("Time to notifyPostProcessor of event " + event.getDocumentEventCode() + ".");
504 }
505
506 if (!processReport.isSuccess()) {
507 LOG.warn("PostProcessor failed to process document: " + processReport.getMessage());
508 throw new RouteManagerException(KEWConstants.POST_PROCESSOR_FAILURE_MESSAGE + processReport.getMessage());
509 }
510 return document;
511 }
512
513
514
515
516
517
518
519
520
521
522
523 private boolean hasContactedPostProcessor(RouteContext context, DocumentRouteStatusChange event) {
524
525
526 Branch rootBranch = context.getDocument().getRootBranch();
527 String key = null;
528 if (KEWConstants.ROUTE_HEADER_PROCESSED_CD.equals(event.getNewRouteStatus())) {
529 key = KEWConstants.POST_PROCESSOR_PROCESSED_KEY;
530 } else if (KEWConstants.ROUTE_HEADER_FINAL_CD.equals(event.getNewRouteStatus())) {
531 key = KEWConstants.POST_PROCESSOR_FINAL_KEY;
532 } else {
533 return false;
534 }
535 BranchState branchState = null;
536 if (rootBranch != null) {
537 branchState = rootBranch.getBranchState(key);
538 } else {
539 return false;
540 }
541 if (branchState == null) {
542 branchState = new BranchState(key, "true");
543 rootBranch.addBranchState(branchState);
544 saveBranch(context, rootBranch);
545 return false;
546 }
547 return "true".equals(branchState.getValue());
548 }
549
550
551
552
553
554
555
556
557 private DocumentRouteHeaderValue notifyPostProcessor(DocumentRouteHeaderValue document, RouteNodeInstance nodeInstance, DocumentRouteLevelChange event) {
558 getRouteHeaderService().saveRouteHeader(document);
559 ProcessDocReport report = null;
560 try {
561 PostProcessor postProcessor = null;
562
563 if (!isRunPostProcessorLogic()) {
564 postProcessor = new DefaultPostProcessor();
565 } else {
566 postProcessor = document.getDocumentType().getPostProcessor();
567 }
568 report = postProcessor.doRouteLevelChange(event);
569 } catch (Exception e) {
570 LOG.warn("Problems contacting PostProcessor", e);
571 throw new RouteManagerException("Problems contacting PostProcessor: " + e.getMessage());
572 }
573 document = getRouteHeaderService().getRouteHeader(document.getRouteHeaderId());
574 if (!report.isSuccess()) {
575 LOG.error("PostProcessor rejected route level change::" + report.getMessage(), report.getProcessException());
576 throw new RouteManagerException("Route Level change failed in post processor::" + report.getMessage());
577 }
578 return document;
579 }
580
581
582
583
584
585 private DocumentRouteHeaderValue notifyPostProcessorBeforeProcess(DocumentRouteHeaderValue document, Long nodeInstanceId) {
586 return notifyPostProcessorBeforeProcess(document, nodeInstanceId, new BeforeProcessEvent(document.getRouteHeaderId(),document.getAppDocId(),nodeInstanceId));
587 }
588
589
590
591
592
593 private DocumentRouteHeaderValue notifyPostProcessorBeforeProcess(DocumentRouteHeaderValue document, Long nodeInstanceId, BeforeProcessEvent event) {
594 ProcessDocReport report = null;
595 try {
596 PostProcessor postProcessor = null;
597
598 if (!isRunPostProcessorLogic()) {
599 postProcessor = new DefaultPostProcessor();
600 } else {
601 postProcessor = document.getDocumentType().getPostProcessor();
602 }
603 report = postProcessor.beforeProcess(event);
604 } catch (Exception e) {
605 LOG.warn("Problems contacting PostProcessor", e);
606 throw new RouteManagerException("Problems contacting PostProcessor: " + e.getMessage());
607 }
608 document = getRouteHeaderService().getRouteHeader(document.getRouteHeaderId());
609 if (!report.isSuccess()) {
610 LOG.error("PostProcessor rejected route level change::" + report.getMessage(), report.getProcessException());
611 throw new RouteManagerException("Route Level change failed in post processor::" + report.getMessage());
612 }
613 return document;
614 }
615
616 protected void lockAdditionalDocuments(DocumentRouteHeaderValue document) throws Exception {
617 DocumentLockingEvent lockingEvent = new DocumentLockingEvent(document.getRouteHeaderId(), document.getAppDocId());
618
619 PostProcessor postProcessor = null;
620
621 if (!isRunPostProcessorLogic()) {
622 postProcessor = new DefaultPostProcessor();
623 } else {
624 postProcessor = document.getDocumentType().getPostProcessor();
625 }
626 List<Long> documentIdsToLock = postProcessor.getDocumentIdsToLock(lockingEvent);
627 if (documentIdsToLock != null && !documentIdsToLock.isEmpty()) {
628 for (Long documentId : documentIdsToLock) {
629 if ( LOG.isInfoEnabled() ) {
630 LOG.info("Aquiring additional lock on document " + documentId);
631 }
632 getRouteHeaderService().lockRouteHeader(documentId, true);
633 if ( LOG.isInfoEnabled() ) {
634 LOG.info("Aquired lock on document " + documentId);
635 }
636 }
637 }
638 }
639
640
641
642
643
644 private DocumentRouteHeaderValue notifyPostProcessorAfterProcess(DocumentRouteHeaderValue document, Long nodeInstanceId, boolean successfullyProcessed) {
645 if (document == null) {
646
647 return null;
648 }
649 return notifyPostProcessorAfterProcess(document, nodeInstanceId, new AfterProcessEvent(document.getRouteHeaderId(),document.getAppDocId(),nodeInstanceId,successfullyProcessed));
650 }
651
652
653
654
655
656 private DocumentRouteHeaderValue notifyPostProcessorAfterProcess(DocumentRouteHeaderValue document, Long nodeInstanceId, AfterProcessEvent event) {
657 ProcessDocReport report = null;
658 try {
659 PostProcessor postProcessor = null;
660
661 if (!isRunPostProcessorLogic()) {
662 postProcessor = new DefaultPostProcessor();
663 } else {
664 postProcessor = document.getDocumentType().getPostProcessor();
665 }
666 report = postProcessor.afterProcess(event);
667 } catch (Exception e) {
668 LOG.warn("Problems contacting PostProcessor", e);
669 throw new RouteManagerException("Problems contacting PostProcessor: " + e.getMessage());
670 }
671 document = getRouteHeaderService().getRouteHeader(document.getRouteHeaderId());
672 if (!report.isSuccess()) {
673 LOG.error("PostProcessor rejected route level change::" + report.getMessage(), report.getProcessException());
674 throw new RouteManagerException("Route Level change failed in post processor::" + report.getMessage());
675 }
676 return document;
677 }
678
679
680
681
682
683 public void initializeDocument(DocumentRouteHeaderValue document) {
684
685
686
687
688
689
690 RouteContext context = new RouteContext();
691 context.setDocument(document);
692 if (context.getEngineState() == null) {
693 context.setEngineState(new EngineState());
694 }
695 Process process = document.getDocumentType().getPrimaryProcess();
696 if (process == null || process.getInitialRouteNode() == null) {
697 if (process == null) {
698 throw new IllegalArgumentException("DocumentType '" + document.getDocumentType().getName() + "' has no primary process configured!");
699 }
700 return;
701 }
702 RouteNodeInstance nodeInstance = helper.getNodeFactory().createRouteNodeInstance(document.getRouteHeaderId(), process.getInitialRouteNode());
703 nodeInstance.setActive(true);
704 helper.getNodeFactory().createBranch(KEWConstants.PRIMARY_BRANCH_NAME, null, nodeInstance);
705 document.getInitialRouteNodeInstances().add(nodeInstance);
706 saveNode(context, nodeInstance);
707 }
708
709 protected RouteNodeService getRouteNodeService() {
710 return KEWServiceLocator.getRouteNodeService();
711 }
712
713 private boolean isRunawayProcessDetected(EngineState engineState) throws NumberFormatException {
714 String maxNodesConstant = Utilities.getKNSParameterValue(KEWConstants.KEW_NAMESPACE, KNSConstants.DetailTypes.ALL_DETAIL_TYPE, KEWConstants.MAX_NODES_BEFORE_RUNAWAY_PROCESS);
715 int maxNodes = (Utilities.isEmpty(maxNodesConstant)) ? 50 : Integer.valueOf(maxNodesConstant);
716 return engineState.getCompleteNodeInstances().size() > maxNodes;
717 }
718
719 protected RouteHeaderService getRouteHeaderService() {
720 return KEWServiceLocator.getRouteHeaderService();
721 }
722
723 }