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