1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.actionrequest.service.impl;
17
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27
28 import org.apache.commons.lang.ObjectUtils;
29 import org.apache.commons.lang.StringUtils;
30 import org.apache.log4j.Logger;
31 import org.kuali.rice.core.api.config.CoreConfigHelper;
32 import org.kuali.rice.core.api.exception.RiceRuntimeException;
33 import org.kuali.rice.core.framework.services.CoreFrameworkServiceLocator;
34 import org.kuali.rice.kew.actionitem.ActionItem;
35 import org.kuali.rice.kew.actionlist.service.ActionListService;
36 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
37 import org.kuali.rice.kew.actionrequest.Recipient;
38 import org.kuali.rice.kew.actionrequest.dao.ActionRequestDAO;
39 import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
40 import org.kuali.rice.kew.api.document.DocumentRefreshQueue;
41 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
42 import org.kuali.rice.kew.actiontaken.service.ActionTakenService;
43 import org.kuali.rice.kew.api.action.ActionRequestPolicy;
44 import org.kuali.rice.kew.api.action.ActionRequestStatus;
45 import org.kuali.rice.kew.api.action.RecipientType;
46 import org.kuali.rice.kew.doctype.bo.DocumentType;
47 import org.kuali.rice.kew.engine.ActivationContext;
48 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
49 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
50 import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
51 import org.kuali.rice.kew.messaging.MessageServiceNames;
52 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
53 import org.kuali.rice.kew.routeheader.service.RouteHeaderService;
54 import org.kuali.rice.kew.routemodule.RouteModule;
55 import org.kuali.rice.kew.service.KEWServiceLocator;
56 import org.kuali.rice.kew.util.FutureRequestDocumentStateManager;
57 import org.kuali.rice.kew.api.KewApiConstants;
58 import org.kuali.rice.kew.util.PerformanceLogger;
59 import org.kuali.rice.kew.util.ResponsibleParty;
60 import org.kuali.rice.kim.api.identity.principal.Principal;
61 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
62 import org.kuali.rice.krad.util.KRADConstants;
63
64
65
66
67
68
69 public class ActionRequestServiceImpl implements ActionRequestService {
70 private static final Logger LOG = Logger.getLogger(ActionRequestServiceImpl.class);
71
72 private ActionRequestDAO actionRequestDAO;
73
74 public ActionRequestValue findByActionRequestId(String actionRequestId) {
75 return getActionRequestDAO().getActionRequestByActionRequestId(actionRequestId);
76 }
77
78 public Map<String, String> getActionsRequested(DocumentRouteHeaderValue routeHeader, String principalId, boolean completeAndApproveTheSame) {
79 return getActionsRequested(principalId, routeHeader.getActionRequests(), completeAndApproveTheSame);
80 }
81
82
83
84
85
86
87
88
89 protected Map<String, String> getActionsRequested(String principalId, List<ActionRequestValue> actionRequests, boolean completeAndApproveTheSame) {
90 Map<String, String> actionsRequested = new HashMap<String, String>();
91 actionsRequested.put(KewApiConstants.ACTION_REQUEST_FYI_REQ, "false");
92 actionsRequested.put(KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, "false");
93 actionsRequested.put(KewApiConstants.ACTION_REQUEST_APPROVE_REQ, "false");
94 actionsRequested.put(KewApiConstants.ACTION_REQUEST_COMPLETE_REQ, "false");
95 String topActionRequested = KewApiConstants.ACTION_REQUEST_FYI_REQ;
96 for (ActionRequestValue actionRequest : actionRequests) {
97
98
99
100 if (!RecipientType.ROLE.getCode().equals(actionRequest.getRecipientTypeCd()) &&
101 actionRequest.isRecipientRoutedRequest(principalId) && actionRequest.isActive()) {
102 int actionRequestComparison = ActionRequestValue.compareActionCode(actionRequest.getActionRequested(), topActionRequested, completeAndApproveTheSame);
103 if (actionRequest.isFYIRequest() && actionRequestComparison >= 0) {
104 actionsRequested.put(KewApiConstants.ACTION_REQUEST_FYI_REQ, "true");
105 } else if (actionRequest.isAcknowledgeRequest() && actionRequestComparison >= 0) {
106 actionsRequested.put(KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, "true");
107 actionsRequested.put(KewApiConstants.ACTION_REQUEST_FYI_REQ, "false");
108 topActionRequested = actionRequest.getActionRequested();
109 } else if (actionRequest.isApproveRequest() && actionRequestComparison >= 0) {
110 actionsRequested.put(KewApiConstants.ACTION_REQUEST_APPROVE_REQ, "true");
111 actionsRequested.put(KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, "false");
112 actionsRequested.put(KewApiConstants.ACTION_REQUEST_FYI_REQ, "false");
113 topActionRequested = actionRequest.getActionRequested();
114 } else if (actionRequest.isCompleteRequst() && actionRequestComparison >= 0) {
115 actionsRequested.put(KewApiConstants.ACTION_REQUEST_COMPLETE_REQ, "true");
116 actionsRequested.put(KewApiConstants.ACTION_REQUEST_APPROVE_REQ, "false");
117 actionsRequested.put(KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, "false");
118 actionsRequested.put(KewApiConstants.ACTION_REQUEST_FYI_REQ, "false");
119 if (completeAndApproveTheSame) {
120 actionsRequested.put(KewApiConstants.ACTION_REQUEST_APPROVE_REQ, "true");
121 }
122 topActionRequested = actionRequest.getActionRequested();
123 }
124 }
125 }
126 return actionsRequested;
127 }
128
129 public ActionRequestValue initializeActionRequestGraph(ActionRequestValue actionRequest,
130 DocumentRouteHeaderValue document, RouteNodeInstance nodeInstance) {
131 if (actionRequest.getParentActionRequest() != null) {
132 LOG.warn("-->A non parent action request from doc " + document.getDocumentId());
133 actionRequest = KEWServiceLocator.getActionRequestService().getRoot(actionRequest);
134 }
135 propagatePropertiesToRequestGraph(actionRequest, document, nodeInstance);
136 return actionRequest;
137 }
138
139 private void propagatePropertiesToRequestGraph(ActionRequestValue actionRequest, DocumentRouteHeaderValue document,
140 RouteNodeInstance nodeInstance) {
141 setPropertiesToRequest(actionRequest, document, nodeInstance);
142 for (ActionRequestValue actionRequestValue : actionRequest.getChildrenRequests())
143 {
144 propagatePropertiesToRequestGraph(actionRequestValue, document, nodeInstance);
145 }
146 }
147
148 private void setPropertiesToRequest(ActionRequestValue actionRequest, DocumentRouteHeaderValue document,
149 RouteNodeInstance nodeInstance) {
150 actionRequest.setDocumentId(document.getDocumentId());
151 actionRequest.setDocVersion(document.getDocVersion());
152 actionRequest.setRouteLevel(document.getDocRouteLevel());
153 actionRequest.setNodeInstance(nodeInstance);
154 actionRequest.setStatus(ActionRequestStatus.INITIALIZED.getCode());
155 }
156
157
158
159 public void activateRequests(Collection actionRequests) {
160 activateRequests(actionRequests, new ActivationContext(!ActivationContext.CONTEXT_IS_SIMULATION));
161 }
162
163 public void activateRequests(Collection actionRequests, boolean simulate) {
164 activateRequests(actionRequests, new ActivationContext(simulate));
165 }
166
167 public void activateRequests(Collection actionRequests, ActivationContext activationContext) {
168 if (actionRequests == null) {
169 return;
170 }
171 PerformanceLogger performanceLogger = null;
172 if ( LOG.isInfoEnabled() ) {
173 performanceLogger = new PerformanceLogger();
174 }
175 activationContext.setGeneratedActionItems(new ArrayList<ActionItem>());
176 activateRequestsInternal(actionRequests, activationContext);
177 if (!activationContext.isSimulation()) {
178 KEWServiceLocator.getNotificationService().notify(ActionItem.to(activationContext.getGeneratedActionItems()));
179 }
180 if ( LOG.isInfoEnabled() ) {
181 performanceLogger.log("Time to " + (activationContext.isSimulation() ? "simulate activation of " : "activate ")
182 + actionRequests.size() + " action requests.");
183 }
184 if ( LOG.isDebugEnabled() ) {
185 LOG.debug("Generated " + activationContext.getGeneratedActionItems().size() + " action items.");
186 }
187 }
188
189 public void activateRequest(ActionRequestValue actionRequest) {
190 activateRequests(Collections.singletonList(actionRequest), new ActivationContext(!ActivationContext.CONTEXT_IS_SIMULATION));
191 }
192
193 public void activateRequest(ActionRequestValue actionRequest, boolean simulate) {
194 activateRequests(Collections.singletonList(actionRequest), new ActivationContext(simulate));
195 }
196
197 public void activateRequest(ActionRequestValue actionRequest, ActivationContext activationContext) {
198 activateRequests(Collections.singletonList(actionRequest), activationContext);
199 }
200
201 public List activateRequestNoNotification(ActionRequestValue actionRequest, boolean simulate) {
202 return activateRequestNoNotification(actionRequest, new ActivationContext(simulate));
203 }
204
205 public List activateRequestNoNotification(ActionRequestValue actionRequest, ActivationContext activationContext) {
206 activationContext.setGeneratedActionItems(new ArrayList<ActionItem>());
207 activateRequestInternal(actionRequest, activationContext);
208 return activationContext.getGeneratedActionItems();
209 }
210
211
212
213
214
215
216
217 private void activateRequestsInternal(Collection actionRequests, ActivationContext activationContext) {
218 if (actionRequests == null) {
219 return;
220 }
221 List<?> actionRequestList = new ArrayList<Object>(actionRequests);
222 for (int i = 0; i < actionRequestList.size(); i++) {
223 activateRequestInternal((ActionRequestValue) actionRequestList.get(i), activationContext);
224 }
225 }
226
227
228
229
230
231 private void activateRequestInternal(ActionRequestValue actionRequest, ActivationContext activationContext) {
232 PerformanceLogger performanceLogger = null;
233 if ( LOG.isInfoEnabled() ) {
234 performanceLogger = new PerformanceLogger();
235 }
236 if (actionRequest == null || actionRequest.isActive() || actionRequest.isDeactivated()) {
237 return;
238 }
239 processResponsibilityId(actionRequest);
240 if (deactivateOnActionAlreadyTaken(actionRequest, activationContext)) {
241 return;
242 }
243 if (deactivateOnInactiveGroup(actionRequest, activationContext)) {
244 return;
245 }
246 if (deactivateOnEmptyGroup(actionRequest, activationContext)) {
247 return;
248 }
249 actionRequest.setStatus(ActionRequestStatus.ACTIVATED.getCode());
250 if (!activationContext.isSimulation()) {
251 saveActionRequest(actionRequest);
252 activationContext.getGeneratedActionItems().addAll(generateActionItems(actionRequest, activationContext));
253 }
254 activateRequestsInternal(actionRequest.getChildrenRequests(), activationContext);
255 activateRequestInternal(actionRequest.getParentActionRequest(), activationContext);
256 if ( LOG.isInfoEnabled() ) {
257 if (activationContext.isSimulation()) {
258 performanceLogger.log("Time to simulate activation of request.");
259 } else {
260 performanceLogger.log("Time to activate action request with id " + actionRequest.getActionRequestId());
261 }
262 }
263 }
264
265
266
267
268
269
270
271
272 private List<ActionItem> generateActionItems(ActionRequestValue actionRequest, ActivationContext activationContext) {
273 if ( LOG.isDebugEnabled() ) {
274 LOG.debug("generating the action items for request " + actionRequest.getActionRequestId());
275 }
276 List<ActionItem> actionItems = new ArrayList<ActionItem>();
277 if (!actionRequest.isPrimaryDelegator()) {
278 if (actionRequest.isGroupRequest()) {
279 List<String> principalIds = KimApiServiceLocator.getGroupService().getMemberPrincipalIds(actionRequest.getGroupId());
280 actionItems.addAll(createActionItemsForPrincipals(actionRequest, principalIds));
281 } else if (actionRequest.isUserRequest()) {
282 ActionItem actionItem = getActionListService().createActionItemForActionRequest(actionRequest);
283 actionItems.add(actionItem);
284 }
285 }
286 if (!activationContext.isSimulation()) {
287 for (ActionItem actionItem: actionItems) {
288 if ( LOG.isDebugEnabled() ) {
289 LOG.debug("Saving action item: " + actionItems);
290 }
291 getActionListService().saveActionItem(actionItem);
292 }
293 } else {
294 actionRequest.getSimulatedActionItems().addAll(actionItems);
295 }
296 return actionItems;
297 }
298
299 private List<ActionItem> createActionItemsForPrincipals(ActionRequestValue actionRequest, List<String> principalIds) {
300 List<ActionItem> actionItems = new ArrayList<ActionItem>();
301 for (String principalId: principalIds) {
302 ActionItem actionItem = getActionListService().createActionItemForActionRequest(actionRequest);
303 actionItem.setPrincipalId(principalId);
304 actionItem.setRoleName(actionRequest.getQualifiedRoleName());
305 actionItems.add(actionItem);
306 }
307 return actionItems;
308 }
309
310 private void processResponsibilityId(ActionRequestValue actionRequest) {
311 if (actionRequest.getResolveResponsibility()) {
312 String responsibilityId = actionRequest.getResponsibilityId();
313 try {
314 RouteModule routeModule = KEWServiceLocator.getRouteModuleService().findRouteModule(actionRequest);
315 if (responsibilityId != null && actionRequest.isRouteModuleRequest()) {
316 if ( LOG.isDebugEnabled() ) {
317 LOG.debug("Resolving responsibility id for action request id=" + actionRequest.getActionRequestId()
318 + " and responsibility id=" + actionRequest.getResponsibilityId());
319 }
320 ResponsibleParty responsibleParty = routeModule.resolveResponsibilityId(actionRequest.getResponsibilityId());
321 if (responsibleParty == null) {
322 return;
323 }
324 if (responsibleParty.getPrincipalId() != null) {
325 Principal user = KimApiServiceLocator.getIdentityService()
326 .getPrincipal(responsibleParty.getPrincipalId());
327 actionRequest.setPrincipalId(user.getPrincipalId());
328 } else if (responsibleParty.getGroupId() != null) {
329 actionRequest.setGroupId(responsibleParty.getGroupId());
330 } else if (responsibleParty.getRoleName() != null) {
331 actionRequest.setRoleName(responsibleParty.getRoleName());
332 }
333 }
334 } catch (Exception e) {
335 LOG.error("Exception thrown when trying to resolve responsibility id " + responsibilityId, e);
336 throw new RuntimeException(e);
337 }
338 }
339 }
340
341 protected boolean deactivateOnActionAlreadyTaken(ActionRequestValue actionRequestToActivate,
342 ActivationContext activationContext) {
343
344 FutureRequestDocumentStateManager futureRequestStateMngr = null;
345
346 if (actionRequestToActivate.isGroupRequest()) {
347 futureRequestStateMngr = new FutureRequestDocumentStateManager(actionRequestToActivate.getRouteHeader(), actionRequestToActivate.getGroup());
348 } else if (actionRequestToActivate.isUserRequest()) {
349 futureRequestStateMngr = new FutureRequestDocumentStateManager(actionRequestToActivate.getRouteHeader(), actionRequestToActivate.getPrincipalId());
350 } else {
351 return false;
352 }
353
354 if (futureRequestStateMngr.isReceiveFutureRequests()) {
355 return false;
356 }
357 if (!actionRequestToActivate.getForceAction() || futureRequestStateMngr.isDoNotReceiveFutureRequests()) {
358 ActionTakenValue previousActionTaken = null;
359 if (!activationContext.isSimulation()) {
360 previousActionTaken = getActionTakenService().getPreviousAction(actionRequestToActivate);
361 } else {
362 previousActionTaken = getActionTakenService().getPreviousAction(actionRequestToActivate,
363 activationContext.getSimulatedActionsTaken());
364 }
365 if (previousActionTaken != null) {
366 if ( LOG.isDebugEnabled() ) {
367 LOG.debug("found a satisfying action taken so setting this request done. Action Request Id "
368 + actionRequestToActivate.getActionRequestId());
369 }
370
371
372 if (!previousActionTaken.isForDelegator() && actionRequestToActivate.getParentActionRequest() != null) {
373 previousActionTaken.setDelegator(actionRequestToActivate.getParentActionRequest().getRecipient());
374 if (!activationContext.isSimulation()) {
375 getActionTakenService().saveActionTaken(previousActionTaken);
376 }
377 }
378 deactivateRequest(previousActionTaken, actionRequestToActivate, null, activationContext);
379 return true;
380 }
381 }
382 if ( LOG.isDebugEnabled() ) {
383 LOG.debug("Forcing action for action request " + actionRequestToActivate.getActionRequestId());
384 }
385 return false;
386 }
387
388
389
390
391
392
393 protected boolean deactivateOnEmptyGroup(ActionRequestValue actionRequestToActivate, ActivationContext activationContext) {
394 if (actionRequestToActivate.isGroupRequest()) {
395 if (KimApiServiceLocator.getGroupService().getMemberPrincipalIds(actionRequestToActivate.getGroup().getId()).isEmpty()) {
396 deactivateRequest(null, actionRequestToActivate, null, activationContext);
397 return true;
398 }
399 }
400 return false;
401 }
402
403
404
405
406
407 protected boolean deactivateOnInactiveGroup(ActionRequestValue actionRequestToActivate, ActivationContext activationContext) {
408 if (actionRequestToActivate.isGroupRequest()) {
409 if (!actionRequestToActivate.getGroup().isActive() && !actionRequestToActivate.getRouteHeader().getDocumentType().getFailOnInactiveGroup().getPolicyValue()) {
410 deactivateRequest(null, actionRequestToActivate, null, activationContext);
411 return true;
412 }
413 }
414 return false;
415 }
416
417 public void deactivateRequest(ActionTakenValue actionTaken, ActionRequestValue actionRequest) {
418 deactivateRequest(actionTaken, actionRequest, null, new ActivationContext(!ActivationContext.CONTEXT_IS_SIMULATION));
419 }
420
421 public void deactivateRequest(ActionTakenValue actionTaken, ActionRequestValue actionRequest, boolean simulate) {
422 deactivateRequest(actionTaken, actionRequest, null, new ActivationContext(simulate));
423 }
424
425 public void deactivateRequest(ActionTakenValue actionTaken, ActionRequestValue actionRequest,
426 ActivationContext activationContext) {
427 deactivateRequest(actionTaken, actionRequest, null, activationContext);
428 }
429
430 public void deactivateRequests(ActionTakenValue actionTaken, List actionRequests) {
431 deactivateRequests(actionTaken, actionRequests, null,
432 new ActivationContext(!ActivationContext.CONTEXT_IS_SIMULATION));
433 }
434
435 public void deactivateRequests(ActionTakenValue actionTaken, List actionRequests, boolean simulate) {
436 deactivateRequests(actionTaken, actionRequests, null, new ActivationContext(simulate));
437 }
438
439 public void deactivateRequests(ActionTakenValue actionTaken, List actionRequests, ActivationContext activationContext) {
440 deactivateRequests(actionTaken, actionRequests, null, activationContext);
441 }
442
443 private void deactivateRequests(ActionTakenValue actionTaken, Collection actionRequests,
444 ActionRequestValue deactivationRequester, ActivationContext activationContext) {
445 if (actionRequests == null) {
446 return;
447 }
448 for (Iterator iterator = actionRequests.iterator(); iterator.hasNext();) {
449 ActionRequestValue actionRequest = (ActionRequestValue) iterator.next();
450 deactivateRequest(actionTaken, actionRequest, deactivationRequester, activationContext);
451 }
452 }
453
454 private void deactivateRequest(ActionTakenValue actionTaken, ActionRequestValue actionRequest,
455 ActionRequestValue deactivationRequester, ActivationContext activationContext) {
456 if (actionRequest == null || actionRequest.isDeactivated()
457 || haltForAllApprove(actionRequest, deactivationRequester)) {
458 return;
459 }
460 actionRequest.setStatus(ActionRequestStatus.DONE.getCode());
461 actionRequest.setActionTaken(actionTaken);
462 if (actionTaken != null) {
463 actionTaken.getActionRequests().add(actionRequest);
464 }
465 if (!activationContext.isSimulation()) {
466 getActionRequestDAO().saveActionRequest(actionRequest);
467 deleteActionItems(actionRequest);
468 }
469 deactivateRequests(actionTaken, actionRequest.getChildrenRequests(), actionRequest, activationContext);
470 deactivateRequest(actionTaken, actionRequest.getParentActionRequest(), actionRequest, activationContext);
471 }
472
473
474
475
476
477
478
479
480
481 private boolean haltForAllApprove(ActionRequestValue actionRequest, ActionRequestValue deactivationRequester) {
482 if (ActionRequestPolicy.ALL.getCode().equals(actionRequest.getApprovePolicy())
483 && actionRequest.hasChild(deactivationRequester)) {
484 boolean allDeactivated = true;
485 for (ActionRequestValue childRequest : actionRequest.getChildrenRequests())
486 {
487 if (!(allDeactivated = childRequest.isDeactivated()))
488 {
489 return true;
490 }
491 }
492 }
493 return false;
494 }
495
496 public List<ActionRequestValue> getRootRequests(Collection<ActionRequestValue> actionRequests) {
497 Set<ActionRequestValue> unsavedRequests = new HashSet<ActionRequestValue>();
498 Map<String, ActionRequestValue> requestMap = new HashMap<String, ActionRequestValue>();
499 for (ActionRequestValue actionRequest1 : actionRequests)
500 {
501 ActionRequestValue actionRequest = (ActionRequestValue) actionRequest1;
502 ActionRequestValue rootRequest = getRoot(actionRequest);
503 if (rootRequest.getActionRequestId() != null)
504 {
505 requestMap.put(rootRequest.getActionRequestId(), rootRequest);
506 } else
507 {
508 unsavedRequests.add(rootRequest);
509 }
510 }
511 List<ActionRequestValue> requests = new ArrayList<ActionRequestValue>();
512 requests.addAll(requestMap.values());
513 requests.addAll(unsavedRequests);
514 return requests;
515 }
516
517 public ActionRequestValue getRoot(ActionRequestValue actionRequest) {
518 if (actionRequest == null) {
519 return null;
520 }
521 if (actionRequest.getParentActionRequest() != null) {
522 return getRoot(actionRequest.getParentActionRequest());
523 }
524 return actionRequest;
525 }
526
527
528
529
530
531
532 public List<ActionRequestValue> findAllPendingRequests(String documentId) {
533 ActionRequestDAO arDAO = getActionRequestDAO();
534 List<ActionRequestValue> pendingArs = arDAO.findByStatusAndDocId(ActionRequestStatus.ACTIVATED.getCode(), documentId);
535 return pendingArs;
536 }
537
538 public List findAllValidRequests(String principalId, String documentId, String requestCode) {
539 ActionRequestDAO arDAO = getActionRequestDAO();
540 Collection pendingArs = arDAO.findByStatusAndDocId(ActionRequestStatus.ACTIVATED.getCode(), documentId);
541 return findAllValidRequests(principalId, pendingArs, requestCode);
542 }
543
544 public List findAllValidRequests(String principalId, Collection actionRequests, String requestCode) {
545 List matchedArs = new ArrayList();
546 List<String> arGroups = KimApiServiceLocator.getGroupService().getGroupIdsByPrincipalId(principalId);
547 return filterActionRequestsByCode((List<ActionRequestValue>)actionRequests, principalId, arGroups, requestCode);
548 }
549
550
551
552
553
554
555
556
557
558
559 public List<ActionRequestValue> filterActionRequestsByCode(List<ActionRequestValue> actionRequests, String principalId, List<String> principalGroupIds, String requestCode) {
560 List<ActionRequestValue> filteredActionRequests = new ArrayList<ActionRequestValue>();
561
562 List<String> arGroups = null;
563 for (ActionRequestValue ar : actionRequests) {
564 if (ActionRequestValue.compareActionCode(ar.getActionRequested(), requestCode, true) > 0) {
565 continue;
566 }
567 if (ar.isUserRequest() && principalId.equals(ar.getPrincipalId())) {
568 filteredActionRequests.add(ar);
569 } else if (ar.isGroupRequest() && principalGroupIds != null && !principalGroupIds.isEmpty()) {
570 for (String groupId : principalGroupIds) {
571 if (groupId.equals(ar.getGroupId())) {
572 filteredActionRequests.add(ar);
573 }
574 }
575 }
576 }
577
578 return filteredActionRequests;
579 }
580
581 public void updateActionRequestsForResponsibilityChange(Set<String> responsibilityIds) {
582 PerformanceLogger performanceLogger = null;
583 if ( LOG.isInfoEnabled() ) {
584 performanceLogger = new PerformanceLogger();
585 }
586 Collection documentsAffected = getRouteHeaderService().findPendingByResponsibilityIds(responsibilityIds);
587 String cacheWaitValue = CoreFrameworkServiceLocator.getParameterService().getParameterValueAsString(KewApiConstants.KEW_NAMESPACE, KRADConstants.DetailTypes.RULE_DETAIL_TYPE, KewApiConstants.RULE_CACHE_REQUEUE_DELAY);
588 Long cacheWait = KewApiConstants.DEFAULT_CACHE_REQUEUE_WAIT_TIME;
589 if (!org.apache.commons.lang.StringUtils.isEmpty(cacheWaitValue)) {
590 try {
591 cacheWait = Long.valueOf(cacheWaitValue);
592 } catch (NumberFormatException e) {
593 LOG.warn("Cache wait time is not a valid number: " + cacheWaitValue);
594 }
595 }
596 if ( LOG.isInfoEnabled() ) {
597 LOG.info("Scheduling requeue of " + documentsAffected.size() + " documents, affected by " + responsibilityIds.size()
598 + " responsibility changes. Installing a processing wait time of " + cacheWait
599 + " milliseconds to avoid stale rule cache.");
600 }
601 for (Object aDocumentsAffected : documentsAffected)
602 {
603 String documentId = (String) aDocumentsAffected;
604
605 String applicationId = null;
606 DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByDocumentId(documentId);
607
608 if (documentType != null) {
609 applicationId = documentType.getApplicationId();
610 }
611
612 if (applicationId == null)
613 {
614 applicationId = CoreConfigHelper.getApplicationId();
615 }
616 if(documentType.getRegenerateActionRequestsOnChange().getPolicyValue()) {
617 DocumentRefreshQueue documentRequeuer = MessageServiceNames.getDocumentRequeuerService(applicationId,
618 documentId, cacheWait);
619 documentRequeuer.refreshDocument(documentId);
620 }
621 }
622 if ( LOG.isInfoEnabled() ) {
623 performanceLogger.log("Time to updateActionRequestsForResponsibilityChange");
624 }
625 }
626
627
628
629
630
631 public void deleteActionRequestGraph(ActionRequestValue actionRequest) {
632 deleteActionItems(actionRequest);
633 if (actionRequest.getActionTakenId() != null) {
634 ActionTakenValue actionTaken = getActionTakenService().findByActionTakenId(actionRequest.getActionTakenId());
635
636 if(actionTaken != null){
637 getActionTakenService().delete(actionTaken);
638 }
639
640 }
641 getActionRequestDAO().delete(actionRequest.getActionRequestId());
642 for (ActionRequestValue child: actionRequest.getChildrenRequests()) {
643 deleteActionRequestGraph(child);
644 }
645 }
646
647
648
649
650
651 private void deleteActionItems(ActionRequestValue actionRequest) {
652 List<ActionItem> actionItems = actionRequest.getActionItems();
653 if ( LOG.isDebugEnabled() ) {
654 LOG.debug("deleting " + actionItems.size() + " action items for action request: " + actionRequest);
655 }
656 for (ActionItem actionItem: actionItems) {
657 if ( LOG.isDebugEnabled() ) {
658 LOG.debug("deleting action item: " + actionItem);
659 }
660 getActionListService().deleteActionItem(actionItem);
661 }
662 }
663
664
665 public List<ActionRequestValue> findByDocumentIdIgnoreCurrentInd(String documentId) {
666 return getActionRequestDAO().findByDocumentIdIgnoreCurrentInd(documentId);
667 }
668
669 public List<ActionRequestValue> findAllActionRequestsByDocumentId(String documentId) {
670 return getActionRequestDAO().findAllByDocId(documentId);
671 }
672
673 public List<ActionRequestValue> findAllRootActionRequestsByDocumentId(String documentId) {
674 return getActionRequestDAO().findAllRootByDocId(documentId);
675 }
676
677 public List<ActionRequestValue> findPendingByActionRequestedAndDocId(String actionRequestedCd, String documentId) {
678 return getActionRequestDAO().findPendingByActionRequestedAndDocId(actionRequestedCd, documentId);
679 }
680
681
682
683
684 public List<String> getPrincipalIdsWithPendingActionRequestByActionRequestedAndDocId(String actionRequestedCd, String documentId) {
685 List<String> principalIds = new ArrayList<String>();
686 List<ActionRequestValue> actionRequests = findPendingByActionRequestedAndDocId(actionRequestedCd, documentId);
687 for(ActionRequestValue actionRequest: actionRequests){
688 if(actionRequest.isUserRequest()){
689 principalIds.add(actionRequest.getPrincipalId());
690 } else if(actionRequest.isGroupRequest()){
691 principalIds.addAll(
692 KimApiServiceLocator.getGroupService().getMemberPrincipalIds(actionRequest.getGroupId()));
693 }
694 }
695 return principalIds;
696 }
697
698 public List<ActionRequestValue> findPendingByDocIdAtOrBelowRouteLevel(String documentId, Integer routeLevel) {
699 return getActionRequestDAO().findPendingByDocIdAtOrBelowRouteLevel(documentId, routeLevel);
700 }
701
702 public List<ActionRequestValue> findPendingRootRequestsByDocId(String documentId) {
703 return getRootRequests(findPendingByDoc(documentId));
704 }
705
706 public List<ActionRequestValue> findPendingRootRequestsByDocIdAtRouteNode(String documentId, String nodeInstanceId) {
707 return getActionRequestDAO().findPendingRootRequestsByDocIdAtRouteNode(documentId, nodeInstanceId);
708 }
709
710 public List<ActionRequestValue> findRootRequestsByDocIdAtRouteNode(String documentId, String nodeInstanceId) {
711 return getActionRequestDAO().findRootRequestsByDocIdAtRouteNode(documentId, nodeInstanceId);
712 }
713
714 public List<ActionRequestValue> findPendingRootRequestsByDocIdAtOrBelowRouteLevel(String documentId, Integer routeLevel) {
715 return getActionRequestDAO().findPendingRootRequestsByDocIdAtOrBelowRouteLevel(documentId, routeLevel);
716 }
717
718 public List<ActionRequestValue> findPendingRootRequestsByDocIdAtRouteLevel(String documentId, Integer routeLevel) {
719 return getActionRequestDAO().findPendingRootRequestsByDocIdAtRouteLevel(documentId, routeLevel);
720 }
721
722 public List<ActionRequestValue> findPendingRootRequestsByDocumentType(String documentTypeId) {
723 return getActionRequestDAO().findPendingRootRequestsByDocumentType(documentTypeId);
724 }
725
726 public void saveActionRequest(ActionRequestValue actionRequest) {
727 if (actionRequest.isGroupRequest()) {
728 if (!actionRequest.getGroup().isActive() && actionRequest.getRouteHeader().getDocumentType().getFailOnInactiveGroup().getPolicyValue()) {
729 throw new RiceRuntimeException("Attempted to save an action request with an inactive group.");
730 }
731 }
732 getActionRequestDAO().saveActionRequest(actionRequest);
733 }
734
735 public List<ActionRequestValue> findPendingByDoc(String documentId) {
736 return getActionRequestDAO().findAllPendingByDocId(documentId);
737 }
738
739 public List<ActionRequestValue> findPendingByDocRequestCdRouteLevel(String documentId, String requestCode, Integer routeLevel) {
740 List<ActionRequestValue> requests = new ArrayList<ActionRequestValue>();
741 for (Object object : getActionRequestDAO().findAllPendingByDocId(documentId))
742 {
743 ActionRequestValue actionRequest = (ActionRequestValue) object;
744 if (ActionRequestValue.compareActionCode(actionRequest.getActionRequested(), requestCode, true) > 0)
745 {
746 continue;
747 }
748 if (actionRequest.getRouteLevel().intValue() == routeLevel.intValue())
749 {
750 requests.add(actionRequest);
751 }
752 }
753 return requests;
754 }
755
756 public List<ActionRequestValue> findPendingByDocRequestCdNodeName(String documentId, String requestCode, String nodeName) {
757 List<ActionRequestValue> requests = new ArrayList<ActionRequestValue>();
758 for (Object object : getActionRequestDAO().findAllPendingByDocId(documentId))
759 {
760 ActionRequestValue actionRequest = (ActionRequestValue) object;
761 if (ActionRequestValue.compareActionCode(actionRequest.getActionRequested(), requestCode, true) > 0)
762 {
763 continue;
764 }
765 if (actionRequest.getNodeInstance() != null && actionRequest.getNodeInstance().getName().equals(nodeName))
766 {
767 requests.add(actionRequest);
768 }
769 }
770 return requests;
771 }
772
773 public List findActivatedByGroup(String groupId) {
774 return getActionRequestDAO().findActivatedByGroup(groupId);
775 }
776
777 private ActionListService getActionListService() {
778 return (ActionListService) KEWServiceLocator.getActionListService();
779 }
780
781 private ActionTakenService getActionTakenService() {
782 return (ActionTakenService) KEWServiceLocator.getActionTakenService();
783 }
784
785 public ActionRequestDAO getActionRequestDAO() {
786 return actionRequestDAO;
787 }
788
789 public void setActionRequestDAO(ActionRequestDAO actionRequestDAO) {
790 this.actionRequestDAO = actionRequestDAO;
791 }
792
793 private RouteHeaderService getRouteHeaderService() {
794 return (RouteHeaderService) KEWServiceLocator.getService(KEWServiceLocator.DOC_ROUTE_HEADER_SRV);
795 }
796
797 public List<ActionRequestValue> findByStatusAndDocId(String statusCd, String documentId) {
798 return getActionRequestDAO().findByStatusAndDocId(statusCd, documentId);
799 }
800
801 public void alterActionRequested(List actionRequests, String actionRequestCd) {
802 for (Object actionRequest1 : actionRequests)
803 {
804 ActionRequestValue actionRequest = (ActionRequestValue) actionRequest1;
805
806 actionRequest.setActionRequested(actionRequestCd);
807 for (ActionItem item : actionRequest.getActionItems())
808 {
809 item.setActionRequestCd(actionRequestCd);
810 }
811
812 saveActionRequest(actionRequest);
813 }
814 }
815
816
817 public boolean isDuplicateRequest(ActionRequestValue actionRequest) {
818 List<ActionRequestValue> requests = findAllRootActionRequestsByDocumentId(actionRequest.getDocumentId());
819 for (ActionRequestValue existingRequest : requests) {
820 if (existingRequest.getStatus().equals(ActionRequestStatus.DONE.getCode())
821 && existingRequest.getRouteLevel().equals(actionRequest.getRouteLevel())
822 && ObjectUtils.equals(existingRequest.getPrincipalId(), actionRequest.getPrincipalId())
823 && ObjectUtils.equals(existingRequest.getGroupId(), actionRequest.getGroupId())
824 && ObjectUtils.equals(existingRequest.getRoleName(), actionRequest.getRoleName())
825 && ObjectUtils.equals(existingRequest.getQualifiedRoleName(), actionRequest.getQualifiedRoleName())
826 && existingRequest.getActionRequested().equals(actionRequest.getActionRequested())) {
827 return true;
828 }
829 }
830 return false;
831 }
832
833 public Recipient findDelegator(List actionRequests) {
834 Recipient delegator = null;
835 String requestCode = KewApiConstants.ACTION_REQUEST_FYI_REQ;
836 for (Object actionRequest1 : actionRequests)
837 {
838 ActionRequestValue actionRequest = (ActionRequestValue) actionRequest1;
839 ActionRequestValue delegatorRequest = findDelegatorRequest(actionRequest);
840 if (delegatorRequest != null)
841 {
842 if (ActionRequestValue.compareActionCode(delegatorRequest.getActionRequested(), requestCode, true) >= 0)
843 {
844 delegator = delegatorRequest.getRecipient();
845 requestCode = delegatorRequest.getActionRequested();
846 }
847 }
848 }
849 return delegator;
850 }
851
852 public Recipient findDelegator(ActionRequestValue actionRequest) {
853 ActionRequestValue delegatorRequest = findDelegatorRequest(actionRequest);
854 Recipient delegator = null;
855 if (delegatorRequest != null) {
856 delegator = delegatorRequest.getRecipient();
857 }
858 return delegator;
859 }
860
861 public ActionRequestValue findDelegatorRequest(ActionRequestValue actionRequest) {
862 ActionRequestValue parentRequest = actionRequest.getParentActionRequest();
863 if (parentRequest != null && !(parentRequest.isUserRequest() || parentRequest.isGroupRequest())) {
864 parentRequest = findDelegatorRequest(parentRequest);
865 }
866 return parentRequest;
867 }
868
869 public void deleteByDocumentId(String documentId) {
870 actionRequestDAO.deleteByDocumentId(documentId);
871 }
872
873 public void deleteByActionRequestId(String actionRequestId) {
874 actionRequestDAO.delete(actionRequestId);
875 }
876
877 public void validateActionRequest(ActionRequestValue actionRequest) {
878 LOG.debug("Enter validateActionRequest(..)");
879 List<WorkflowServiceErrorImpl> errors = new ArrayList<WorkflowServiceErrorImpl>();
880
881 String actionRequestCd = actionRequest.getActionRequested();
882 if (actionRequestCd == null || actionRequestCd.trim().equals("")) {
883 errors.add(new WorkflowServiceErrorImpl("ActionRequest cd null.", "actionrequest.actionrequestcd.empty",
884 actionRequest.getActionRequestId().toString()));
885 } else if (!KewApiConstants.ACTION_REQUEST_CD.containsKey(actionRequestCd)) {
886 errors.add(new WorkflowServiceErrorImpl("ActionRequest cd invalid.", "actionrequest.actionrequestcd.invalid",
887 actionRequest.getActionRequestId().toString()));
888 }
889
890 String documentId = actionRequest.getDocumentId();
891 if (documentId == null || StringUtils.isEmpty(documentId)) {
892 errors.add(new WorkflowServiceErrorImpl("ActionRequest Document id empty.", "actionrequest.documentid.empty",
893 actionRequest.getActionRequestId().toString()));
894 } else if (getRouteHeaderService().getRouteHeader(documentId) == null) {
895 errors.add(new WorkflowServiceErrorImpl("ActionRequest Document id invalid.",
896 "actionrequest.documentid.invalid", actionRequest.getActionRequestId().toString()));
897 }
898
899 String actionRequestStatus = actionRequest.getStatus();
900 if (actionRequestStatus == null || actionRequestStatus.trim().equals("")) {
901 errors.add(new WorkflowServiceErrorImpl("ActionRequest status null.", "actionrequest.actionrequeststatus.empty",
902 actionRequest.getActionRequestId().toString()));
903 } else if (ActionRequestStatus.fromCode(actionRequestStatus) == null) {
904 errors.add(new WorkflowServiceErrorImpl("ActionRequest status invalid.",
905 "actionrequest.actionrequeststatus.invalid", actionRequest.getActionRequestId().toString()));
906 }
907
908 if (actionRequest.getResponsibilityId() == null) {
909 errors.add(new WorkflowServiceErrorImpl("ActionRequest responsibility id null.",
910 "actionrequest.responsibilityid.empty", actionRequest.getActionRequestId().toString()));
911 }
912
913 Integer priority = actionRequest.getPriority();
914 if (priority == null) {
915 errors.add(new WorkflowServiceErrorImpl("ActionRequest priority null.", "actionrequest.priority.empty",
916 actionRequest.getActionRequestId().toString()));
917 }
918
919
920
921
922
923
924 Integer routeLevel = actionRequest.getRouteLevel();
925 if (routeLevel == null) {
926 errors.add(new WorkflowServiceErrorImpl("ActionRequest route level null.", "actionrequest.routelevel.empty",
927 actionRequest.getActionRequestId().toString()));
928 } else if (routeLevel < -1) {
929 errors.add(new WorkflowServiceErrorImpl("ActionRequest route level invalid.",
930 "actionrequest.routelevel.invalid", actionRequest.getActionRequestId().toString()));
931 }
932
933 Integer version = actionRequest.getDocVersion();
934 if (version == null) {
935 errors.add(new WorkflowServiceErrorImpl("ActionRequest doc version null.", "actionrequest.docversion.empty",
936 actionRequest.getActionRequestId().toString()));
937 }
938
939 if (actionRequest.getCreateDate() == null) {
940 errors.add(new WorkflowServiceErrorImpl("ActionRequest create date null.", "actionrequest.createdate.empty",
941 actionRequest.getActionRequestId().toString()));
942 }
943
944 String recipientType = actionRequest.getRecipientTypeCd();
945 if (recipientType != null && !recipientType.trim().equals("")) {
946 if (recipientType.equals(KewApiConstants.WORKGROUP)) {
947 String workgroupId = actionRequest.getGroupId();
948 if (workgroupId == null) {
949 errors.add(new WorkflowServiceErrorImpl("ActionRequest workgroup null.",
950 "actionrequest.workgroup.empty", actionRequest.getActionRequestId().toString()));
951 } else if (KimApiServiceLocator.getGroupService().getGroup(workgroupId) == null) {
952 errors.add(new WorkflowServiceErrorImpl("ActionRequest workgroup invalid.",
953 "actionrequest.workgroup.invalid", actionRequest.getActionRequestId().toString()));
954 }
955
956 }
957 if (recipientType.equals(KewApiConstants.PERSON)) {
958 String principalId = actionRequest.getPrincipalId();
959 if (principalId == null || principalId.trim().equals("")) {
960 errors.add(new WorkflowServiceErrorImpl("ActionRequest person id null.", "actionrequest.persosn.empty",
961 actionRequest.getActionRequestId().toString()));
962 } else {
963 Principal principal = KimApiServiceLocator.getIdentityService().getPrincipal(principalId);
964 if (principal == null) {
965 errors.add(new WorkflowServiceErrorImpl("ActionRequest person id invalid.",
966 "actionrequest.personid.invalid", actionRequest.getActionRequestId().toString()));
967 }
968 }
969
970 if (recipientType.equals(KewApiConstants.ROLE)
971 && (actionRequest.getRoleName() == null || actionRequest.getRoleName().trim().equals(""))) {
972 errors.add(new WorkflowServiceErrorImpl("ActionRequest role name null.", "actionrequest.rolename.null",
973 actionRequest.getActionRequestId().toString()));
974 }
975 }
976 LOG.debug("Exit validateActionRequest(..) ");
977 if (!errors.isEmpty()) {
978 throw new WorkflowServiceErrorException("ActionRequest Validation Error", errors);
979 }
980 }
981 }
982
983 public List getDelegateRequests(ActionRequestValue actionRequest) {
984 List<ActionRequestValue> delegateRequests = new ArrayList<ActionRequestValue>();
985 List requests = getTopLevelRequests(actionRequest);
986 for (Object request : requests)
987 {
988 ActionRequestValue parentActionRequest = (ActionRequestValue) request;
989 delegateRequests.addAll(parentActionRequest.getChildrenRequests());
990 }
991 return delegateRequests;
992 }
993
994 public List getTopLevelRequests(ActionRequestValue actionRequest) {
995 List<ActionRequestValue> topLevelRequests = new ArrayList<ActionRequestValue>();
996 if (actionRequest.isRoleRequest()) {
997 topLevelRequests.addAll(actionRequest.getChildrenRequests());
998 } else {
999 topLevelRequests.add(actionRequest);
1000 }
1001 return topLevelRequests;
1002 }
1003
1004 public boolean isValidActionRequestCode(String actionRequestCode) {
1005 return actionRequestCode != null && KewApiConstants.ACTION_REQUEST_CODES.containsKey(actionRequestCode);
1006 }
1007
1008 public boolean doesPrincipalHaveRequest(String principalId, String documentId) {
1009 if (getActionRequestDAO().doesDocumentHaveUserRequest(principalId, documentId)) {
1010 return true;
1011 }
1012
1013
1014 List<String> groupIds = getActionRequestDAO().getRequestGroupIds(documentId);
1015 for (String groupId : groupIds) {
1016 if (KimApiServiceLocator.getGroupService().isMemberOfGroup(principalId, groupId)) {
1017 return true;
1018 }
1019 }
1020 return false;
1021 }
1022
1023 }