1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.engine.node;
17
18 import org.apache.log4j.MDC;
19 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
20 import org.kuali.rice.kew.api.exception.WorkflowException;
21 import org.kuali.rice.kew.engine.RouteContext;
22 import org.kuali.rice.kew.engine.RouteHelper;
23 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
24 import org.kuali.rice.kew.service.KEWServiceLocator;
25 import org.kuali.rice.kew.api.KewApiConstants;
26 import org.kuali.rice.kew.util.PerformanceLogger;
27 import org.kuali.rice.kew.util.Utilities;
28
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.Iterator;
32 import java.util.List;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public class IteratedRequestActivationNode implements SimpleNode {
64
65 protected final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(getClass());
66 private static long generatedRequestPriority = 0;
67
68 protected static interface RequestFulfillmentCriteria {
69 public boolean pendingRequestsAreFulfilled(boolean activatedBlockingRequests, RouteContext routeContext);
70 }
71
72 private static class AllBlockingRequestsCompleteCriteria implements RequestFulfillmentCriteria {
73 public boolean pendingRequestsAreFulfilled(boolean activatedBlockingRequests, RouteContext routeContext) {
74
75 if (activatedBlockingRequests) {
76
77 assert(activatedBlockingRequests == blockingRequestsArePending(routeContext.getDocument(), routeContext.getNodeInstance())) : "Blocking requests were activated but none were subsequently found";
78 return false;
79 } else {
80
81 return !blockingRequestsArePending(routeContext.getDocument(), routeContext.getNodeInstance());
82 }
83 }
84 }
85
86 private static class SimulatingCriteria implements RequestFulfillmentCriteria {
87 public boolean pendingRequestsAreFulfilled(boolean activatedBlockingRequests, RouteContext routeContext) {
88
89 return true;
90 }
91 }
92
93 public SimpleResult process(RouteContext routeContext, RouteHelper routeHelper) throws Exception {
94
95 RequestFulfillmentCriteria criteria = getRequestFulfillmentCriteria(routeContext);
96
97
98 boolean activatedBlockingRequests = activateRequests(routeContext);
99 boolean initialRequestGeneration = routeContext.getNodeInstance().isInitial();
100 while (criteria.pendingRequestsAreFulfilled(activatedBlockingRequests, routeContext)) {
101 boolean newRequestsGenerated = generateNewRequests(initialRequestGeneration, routeContext, routeHelper);
102 initialRequestGeneration = false;
103
104 if (!newRequestsGenerated) {
105
106
107
108
109 return new SimpleResult(true);
110 }
111
112
113 activatedBlockingRequests = activateRequests(routeContext);
114
115
116
117 if (routeContext.isSimulation()) {
118 criteria = new SimulatingCriteria();
119 } else {
120 criteria = getRequestFulfillmentCriteria(routeContext);
121 }
122 }
123
124
125 return new SimpleResult(false);
126 }
127
128
129
130
131
132
133 protected RequestFulfillmentCriteria getRequestFulfillmentCriteria(RouteContext routeContext) {
134 return new AllBlockingRequestsCompleteCriteria();
135 }
136
137
138
139
140
141
142
143 protected boolean generateNewRequests(boolean initial, RouteContext context, RouteHelper routeHelper) throws WorkflowException, Exception {
144 return false;
145 }
146
147
148
149
150
151
152
153 protected boolean activateRequests(RouteContext routeContext) throws WorkflowException {
154 DocumentRouteHeaderValue document = routeContext.getDocument();
155 RouteNodeInstance nodeInstance = routeContext.getNodeInstance();
156 if (routeContext.isSimulation()) {
157
158 if (routeContext.getActivationContext().isActivateRequests()) {
159 activateRequests(routeContext, document, nodeInstance);
160 }
161
162 return false;
163 } else {
164
165 return activateRequests(routeContext, document, nodeInstance);
166 }
167 }
168
169
170
171
172 private static boolean blockingRequestsArePending(DocumentRouteHeaderValue document, RouteNodeInstance nodeInstance) {
173
174 List<ActionRequestValue> requests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocIdAtRouteNode(document.getDocumentId(), nodeInstance.getRouteNodeInstanceId());
175 boolean blockingRequestsArePending = false;
176 for (ActionRequestValue request: requests) {
177 if (request.isApproveOrCompleteRequest()) {
178 blockingRequestsArePending = true;
179 break;
180 }
181 }
182 return blockingRequestsArePending;
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 private boolean activateRequests(RouteContext context, DocumentRouteHeaderValue document, RouteNodeInstance nodeInstance) throws WorkflowException {
204 MDC.put("docId", document.getDocumentId());
205 PerformanceLogger performanceLogger = new PerformanceLogger(document.getDocumentId());
206 List generatedActionItems = new ArrayList();
207 List<ActionRequestValue> requests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocIdAtRouteNode(document.getDocumentId(), nodeInstance.getRouteNodeInstanceId());
208 if (context.isSimulation()) {
209 requests.addAll(context.getEngineState().getGeneratedRequests());
210 }
211
212
213
214 Collections.sort(requests, new Utilities.PrioritySorter());
215 LOG.info("Pending Root Requests " + requests.size());
216 String activationType = nodeInstance.getRouteNode().getActivationType();
217 boolean isParallel = KewApiConstants.ROUTE_LEVEL_PARALLEL.equals(activationType);
218 boolean activatedApproveRequest = false;
219 for (Iterator iter = requests.iterator(); iter.hasNext();) {
220 if (activatedApproveRequest && !isParallel) {
221 LOG.info("Already activated an apprve request and serial, so not activating any more");
222 break;
223 }
224 ActionRequestValue request = (ActionRequestValue) iter.next();
225 LOG.info("ActionRequestValue: " + request);
226 if (request.getParentActionRequest() != null || request.getNodeInstance() == null) {
227
228
229 continue;
230 }
231 if (request.isActive()) {
232 activatedApproveRequest = activatedApproveRequest || request.isApproveOrCompleteRequest();
233 continue;
234 }
235 logProcessingMessage(request);
236 LOG.info("Activating request. " + request);
237 activatedApproveRequest = activateRequest(context, request, nodeInstance, generatedActionItems) || activatedApproveRequest;
238 }
239
240
241 if (!context.isSimulation()) {
242 KEWServiceLocator.getNotificationService().notify(generatedActionItems);
243 }
244 performanceLogger.log("Time to activate requests.");
245 return activatedApproveRequest;
246 }
247
248 private boolean activateRequest(RouteContext context, ActionRequestValue actionRequest, RouteNodeInstance nodeInstance, List generatedActionItems) {
249 if (actionRequest.isRoleRequest()) {
250 List actionRequests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocIdAtRouteNode(actionRequest.getDocumentId(), nodeInstance.getRouteNodeInstanceId());
251 for (Iterator iterator = actionRequests.iterator(); iterator.hasNext();) {
252 ActionRequestValue siblingRequest = (ActionRequestValue) iterator.next();
253 if (actionRequest.getRoleName().equals(siblingRequest.getRoleName())) {
254 KEWServiceLocator.getActionRequestService().activateRequestNoNotification(siblingRequest, context.getActivationContext());
255
256 generatedActionItems.addAll(context.getActivationContext().getGeneratedActionItems());
257 }
258 }
259 }
260 KEWServiceLocator.getActionRequestService().activateRequestNoNotification(actionRequest, context.getActivationContext());
261
262 generatedActionItems.addAll(context.getActivationContext().getGeneratedActionItems());
263 return actionRequest.isApproveOrCompleteRequest() && ! actionRequest.isDone();
264 }
265
266 protected ActionRequestValue saveActionRequest(RouteContext context, ActionRequestValue actionRequest) {
267 if (!context.isSimulation()) {
268 return KEWServiceLocator.getActionRequestService().saveActionRequest(actionRequest);
269 } else {
270 actionRequest.setActionRequestId(String.valueOf(generatedRequestPriority++));
271 context.getEngineState().getGeneratedRequests().add(actionRequest);
272 return actionRequest;
273 }
274
275 }
276
277 private void logProcessingMessage(ActionRequestValue request) {
278
279 RouteNodeInstance nodeInstance = request.getNodeInstance();
280 StringBuffer buffer = new StringBuffer();
281 buffer.append("Processing AR: ").append(request.getActionRequestId()).append("\n");
282 buffer.append("AR Node Name: ").append(nodeInstance != null ? nodeInstance.getName() : "null").append("\n");
283 buffer.append("AR RouteLevel: ").append(request.getRouteLevel()).append("\n");
284 buffer.append("AR Request Code: ").append(request.getActionRequested()).append("\n");
285 buffer.append("AR Request priority: ").append(request.getPriority()).append("\n");
286 LOG.info(buffer);
287
288 }
289
290 }