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