View Javadoc

1   /**
2    * Copyright 2005-2011 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.impl.document;
17  
18  import java.util.ArrayList;
19  import java.util.Collection;
20  import java.util.List;
21  
22  import org.apache.commons.lang.StringUtils;
23  import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
24  import org.kuali.rice.kew.actionrequest.ActionRequestValue;
25  import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
26  import org.kuali.rice.kew.actionrequest.service.impl.NotificationSuppression;
27  import org.kuali.rice.kew.api.document.DocumentRefreshQueue;
28  import org.kuali.rice.kew.api.WorkflowRuntimeException;
29  import org.kuali.rice.kew.engine.OrchestrationConfig;
30  import org.kuali.rice.kew.engine.OrchestrationConfig.EngineCapability;
31  import org.kuali.rice.kew.engine.RouteHelper;
32  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
33  import org.kuali.rice.kew.engine.node.service.RouteNodeService;
34  import org.kuali.rice.kew.service.KEWServiceLocator;
35  import org.kuali.rice.kew.util.PerformanceLogger;
36  
37  
38  /**
39   * A service which effectively "refreshes" and requeues a document.  It first deletes any
40   * pending action requests on the documents and then requeues the document for standard routing.
41   * Addionally, it adds duplicate notification suppression state to RouteNodeInstanceS for 
42   * which ActionRequestS will be regenerated. 
43   * 
44   * <p>Intended to be called async and wired that way in server/client spring beans.</p>
45   * 
46   * @author Kuali Rice Team (rice.collab@kuali.org)
47   */
48  public class DocumentRefreshQueueImpl implements DocumentRefreshQueue {
49  	
50  	private RouteHelper helper = new RouteHelper();
51      
52  	/**
53  	 * Requeues a document, and sets notification suppression data
54  	 * 
55  	 * @see org.kuali.rice.kew.api.document.DocumentRefreshQueue#refreshDocument(java.lang.String)
56  	 */
57  	@Override
58  	public void refreshDocument(String documentId) {
59  		if (StringUtils.isBlank(documentId)) {
60              throw new RiceIllegalArgumentException("documentId is null or blank");
61          }
62  
63          PerformanceLogger performanceLogger = new PerformanceLogger();
64          KEWServiceLocator.getRouteHeaderService().lockRouteHeader(documentId, true);
65          Collection<RouteNodeInstance> activeNodes = getRouteNodeService().getActiveNodeInstances(documentId);
66          List<ActionRequestValue> requestsToDelete = new ArrayList<ActionRequestValue>();
67          
68  		NotificationSuppression notificationSuppression = new NotificationSuppression();
69  		
70          for (RouteNodeInstance nodeInstance : activeNodes) {
71              // only "requeue" if we're dealing with a request activation node
72              if (helper.isRequestActivationNode(nodeInstance.getRouteNode())) {
73              	List<ActionRequestValue> deletesForThisNode = 
74              		getActionRequestService().findPendingRootRequestsByDocIdAtRouteNode(documentId, nodeInstance.getRouteNodeInstanceId());
75              	
76              	for (ActionRequestValue deleteForThisNode : deletesForThisNode) {
77              		// only delete the request if it was generated by a route module (or the rules system)
78              		if (deleteForThisNode.isRouteModuleRequest()) {
79              			requestsToDelete.add(deleteForThisNode);
80  
81              			// suppress duplicate notifications
82              			notificationSuppression.addNotificationSuppression(nodeInstance, deleteForThisNode);
83              		}
84              	}
85                  // this will trigger a regeneration of requests
86                  nodeInstance.setInitial(true);
87                  getRouteNodeService().save(nodeInstance);
88              }
89          }
90          for (ActionRequestValue requestToDelete : requestsToDelete) {
91              getActionRequestService().deleteActionRequestGraph(requestToDelete);
92          }
93          try {
94              OrchestrationConfig config = new OrchestrationConfig(EngineCapability.STANDARD);
95          	KEWServiceLocator.getWorkflowEngineFactory().newEngine(config).process(documentId, null);
96          } catch (Exception e) {
97          	throw new WorkflowRuntimeException(e);
98          }
99          performanceLogger.log("Time to run DocumentRequeuer for document " + documentId);	
100 	}
101 
102     private ActionRequestService getActionRequestService() {
103         return KEWServiceLocator.getActionRequestService();
104     }
105     
106     private RouteNodeService getRouteNodeService() {
107         return KEWServiceLocator.getRouteNodeService();
108     }
109 }