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