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