View Javadoc

1   /**
2    * Copyright 2005-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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   * @author Kuali Rice Team (rice.collab@kuali.org)
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       * route level and then filters in the approriate ones.
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     // search the document type and all its children
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 }