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