1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.role.service.impl;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
20 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
21 import org.kuali.rice.kew.api.KewApiServiceLocator;
22 import org.kuali.rice.kew.api.action.RolePokerQueue;
23 import org.kuali.rice.kew.api.document.DocumentProcessingQueue;
24 import org.kuali.rice.kew.api.rule.RoleName;
25 import org.kuali.rice.kew.doctype.bo.DocumentType;
26 import org.kuali.rice.kew.engine.RouteContext;
27 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
28 import org.kuali.rice.kew.role.service.RoleService;
29 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
30 import org.kuali.rice.kew.rule.FlexRM;
31 import org.kuali.rice.kew.rule.bo.RuleTemplateAttributeBo;
32 import org.kuali.rice.kew.rule.bo.RuleTemplateBo;
33 import org.kuali.rice.kew.service.KEWServiceLocator;
34
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Set;
40
41
42
43
44
45
46 public class RoleServiceImpl implements RoleService {
47
48 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RoleServiceImpl.class);
49
50 public void reResolveRole(DocumentType documentType, String roleName) {
51 String infoString = "documentType="+(documentType == null ? null : documentType.getName())+", role="+roleName;
52 if (documentType == null ||
53 org.apache.commons.lang.StringUtils.isEmpty(roleName)) {
54 throw new IllegalArgumentException("Cannot pass null or empty arguments to reResolveQualifiedRole: "+infoString);
55 }
56 LOG.debug("Re-resolving role asynchronously for "+infoString);
57 Set<String> documentIds = new HashSet<String>();
58 findAffectedDocuments(documentType, roleName, null, documentIds);
59 LOG.debug(documentIds.size()+" documents were affected by this re-resolution, requeueing with the RolePokerQueue");
60 for (String documentId : documentIds) {
61 String applicationId = KEWServiceLocator.getRouteHeaderService().getApplicationIdByDocumentId(documentId);
62 RolePokerQueue rolePokerQueue = KewApiServiceLocator.getRolePokerQueue(documentId, applicationId);
63 rolePokerQueue.reResolveRole(documentId, roleName);
64 }
65 }
66
67 public void reResolveQualifiedRole(DocumentType documentType, String roleName, String qualifiedRoleNameLabel) {
68 String infoString = "documentType="+(documentType == null ? null : documentType.getName())+", role="+roleName+", qualifiedRole="+qualifiedRoleNameLabel;
69 if (documentType == null ||
70 org.apache.commons.lang.StringUtils.isEmpty(roleName) ||
71 org.apache.commons.lang.StringUtils.isEmpty(qualifiedRoleNameLabel)) {
72 throw new IllegalArgumentException("Cannot pass null or empty arguments to reResolveQualifiedRole: "+infoString);
73 }
74 LOG.debug("Re-resolving qualified role asynchronously for "+infoString);
75 Set<String> documentIds = new HashSet<String>();
76 findAffectedDocuments(documentType, roleName, qualifiedRoleNameLabel, documentIds);
77 LOG.debug(documentIds.size()+" documents were affected by this re-resolution, requeueing with the RolePokerQueue");
78 for (String documentId : documentIds) {
79 String applicationId = KEWServiceLocator.getRouteHeaderService().getApplicationIdByDocumentId(documentId);
80 RolePokerQueue rolePokerQueue = KewApiServiceLocator.getRolePokerQueue(documentId, applicationId);
81 rolePokerQueue.reResolveQualifiedRole(documentId, roleName, qualifiedRoleNameLabel);
82 }
83 }
84
85
86
87
88
89 public void reResolveQualifiedRole(DocumentRouteHeaderValue routeHeader, String roleName, String qualifiedRoleNameLabel) {
90 String infoString = "routeHeader="+(routeHeader == null ? null : routeHeader.getDocumentId())+", role="+roleName+", qualifiedRole="+qualifiedRoleNameLabel;
91 if (routeHeader == null ||
92 org.apache.commons.lang.StringUtils.isEmpty(roleName) ||
93 org.apache.commons.lang.StringUtils.isEmpty(qualifiedRoleNameLabel)) {
94 throw new IllegalArgumentException("Cannot pass null arguments to reResolveQualifiedRole: "+infoString);
95 }
96 LOG.debug("Re-resolving qualified role synchronously for "+infoString);
97 List<RouteNodeInstance> nodeInstances = findNodeInstances(routeHeader, roleName);
98 int requestsGenerated = 0;
99 if (!nodeInstances.isEmpty()) {
100 deletePendingRoleRequests(routeHeader.getDocumentId(), roleName, qualifiedRoleNameLabel);
101 for (RouteNodeInstance nodeInstance : nodeInstances) {
102 RuleTemplateBo ruleTemplate = nodeInstance.getRouteNode().getRuleTemplate();
103 FlexRM flexRM = new FlexRM();
104 RouteContext context = RouteContext.getCurrentRouteContext();
105 context.setDocument(routeHeader);
106 context.setNodeInstance(nodeInstance);
107 try {
108 List<ActionRequestValue> actionRequests = flexRM.getActionRequests(routeHeader, nodeInstance, ruleTemplate.getName());
109 for (ActionRequestValue actionRequest : actionRequests) {
110 if (roleName.equals(actionRequest.getRoleName()) && qualifiedRoleNameLabel.equals(actionRequest.getQualifiedRoleNameLabel())) {
111 actionRequest = KEWServiceLocator.getActionRequestService().initializeActionRequestGraph(actionRequest, routeHeader, nodeInstance);
112 KEWServiceLocator.getActionRequestService().saveActionRequest(actionRequest);
113 requestsGenerated++;
114 }
115 }
116 } catch (Exception e) {
117 RouteContext.clearCurrentRouteContext();
118 }
119
120 }
121 }
122 LOG.debug("Generated "+requestsGenerated+" action requests after re-resolve: "+infoString);
123 requeueDocument(routeHeader);
124 }
125
126 public void reResolveRole(DocumentRouteHeaderValue routeHeader, String roleName) {
127 String infoString = "routeHeader="+(routeHeader == null ? null : routeHeader.getDocumentId())+", role="+roleName;
128 if (routeHeader == null ||
129 org.apache.commons.lang.StringUtils.isEmpty(roleName)) {
130 throw new RiceIllegalArgumentException("Cannot pass null arguments to reResolveQualifiedRole: "+infoString);
131 }
132 LOG.debug("Re-resolving role synchronously for "+infoString);
133 List<RouteNodeInstance> nodeInstances = findNodeInstances(routeHeader, roleName);
134 int requestsGenerated = 0;
135 if (!nodeInstances.isEmpty()) {
136 deletePendingRoleRequests(routeHeader.getDocumentId(), roleName, null);
137 for (RouteNodeInstance nodeInstance : nodeInstances) {
138 RuleTemplateBo ruleTemplate = nodeInstance.getRouteNode().getRuleTemplate();
139 FlexRM flexRM = new FlexRM();
140 RouteContext context = RouteContext.getCurrentRouteContext();
141 context.setDocument(routeHeader);
142 context.setNodeInstance(nodeInstance);
143 try {
144 List<ActionRequestValue> actionRequests = flexRM.getActionRequests(routeHeader, nodeInstance, ruleTemplate.getName());
145 for (ActionRequestValue actionRequest : actionRequests) {
146 if (roleName.equals(actionRequest.getRoleName())) {
147 actionRequest = KEWServiceLocator.getActionRequestService().initializeActionRequestGraph(actionRequest, routeHeader, nodeInstance);
148 KEWServiceLocator.getActionRequestService().saveActionRequest(actionRequest);
149 requestsGenerated++;
150 }
151 }
152 } finally {
153 RouteContext.clearCurrentRouteContext();
154 }
155 }
156 }
157 LOG.debug("Generated "+requestsGenerated+" action requests after re-resolve: "+infoString);
158 requeueDocument(routeHeader);
159 }
160
161
162 private void findAffectedDocuments(DocumentType documentType, String roleName, String qualifiedRoleNameLabel, Set<String> documentIds) {
163 List<ActionRequestValue> pendingRequests = KEWServiceLocator.getActionRequestService().findPendingRootRequestsByDocumentType(documentType.getDocumentTypeId());
164 for (ActionRequestValue actionRequest : pendingRequests) {
165 if (roleName.equals(actionRequest.getRoleName()) &&
166 (qualifiedRoleNameLabel == null || qualifiedRoleNameLabel.equals(actionRequest.getQualifiedRoleNameLabel()))) {
167 documentIds.add(actionRequest.getDocumentId());
168 }
169 }
170 for (DocumentType childDocumentType : documentType.getChildrenDocTypes()) {
171 findAffectedDocuments(childDocumentType, roleName, qualifiedRoleNameLabel, documentIds);
172 }
173 }
174
175 private void deletePendingRoleRequests(String documentId, String roleName, String qualifiedRoleNameLabel) {
176 List<ActionRequestValue> pendingRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(documentId);
177 pendingRequests = KEWServiceLocator.getActionRequestService().getRootRequests(pendingRequests);
178 List<ActionRequestValue> requestsToDelete = new ArrayList<ActionRequestValue>();
179 for (ActionRequestValue actionRequest : pendingRequests) {
180 if (roleName.equals(actionRequest.getRoleName()) &&
181 (qualifiedRoleNameLabel == null || qualifiedRoleNameLabel.equals(actionRequest.getQualifiedRoleNameLabel()))) {
182 requestsToDelete.add(actionRequest);
183 }
184 }
185 LOG.debug("Deleting "+requestsToDelete.size()+" action requests for roleName="+roleName+", qualifiedRoleNameLabel="+qualifiedRoleNameLabel);
186 for (ActionRequestValue actionRequest : requestsToDelete) {
187 KEWServiceLocator.getActionRequestService().deleteActionRequestGraphNoOutbox(actionRequest);
188 }
189 }
190
191 private List<RouteNodeInstance> findNodeInstances(DocumentRouteHeaderValue routeHeader, String roleName) {
192 List<RouteNodeInstance> nodeInstances = new ArrayList<RouteNodeInstance>();
193 Collection<RouteNodeInstance> activeNodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(routeHeader.getDocumentId());
194 if (CollectionUtils.isEmpty(activeNodeInstances)) {
195 throw new IllegalStateException("Document does not currently have any active nodes so re-resolving is not legal.");
196 }
197 for (RouteNodeInstance activeNodeInstance : activeNodeInstances) {
198 RuleTemplateBo template = activeNodeInstance.getRouteNode().getRuleTemplate();
199 if (templateHasRole(template, roleName)) {
200 nodeInstances.add(activeNodeInstance);
201 }
202 }
203 if (nodeInstances.isEmpty()) {
204 throw new IllegalStateException("Could not locate given role to re-resolve: " + roleName);
205 }
206 return nodeInstances;
207 }
208
209 private boolean templateHasRole(RuleTemplateBo template, String roleName) {
210 List<RuleTemplateAttributeBo> templateAttributes = template.getRuleTemplateAttributes();
211 for (RuleTemplateAttributeBo templateAttribute : templateAttributes) {
212 List<RoleName> roleNames = KEWServiceLocator.getWorkflowRuleAttributeMediator().getRoleNames(templateAttribute);
213 for (RoleName role : roleNames) {
214 if (role.getLabel().equals(roleName)) {
215 return true;
216 }
217 }
218 }
219 return false;
220 }
221
222 protected void requeueDocument(DocumentRouteHeaderValue document) {
223 String applicationId = document.getDocumentType().getApplicationId();
224 DocumentProcessingQueue documentProcessingQueue = KewApiServiceLocator.getDocumentProcessingQueue(document.getDocumentId(), applicationId);
225 documentProcessingQueue.process(document.getDocumentId());
226 }
227
228 }