001 /** 002 * Copyright 2005-2013 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.rice.kew.impl.document; 017 018 import java.util.ArrayList; 019 import java.util.Collection; 020 import java.util.List; 021 022 import org.apache.commons.lang.StringUtils; 023 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException; 024 import org.kuali.rice.kew.actionrequest.ActionRequestValue; 025 import org.kuali.rice.kew.actionrequest.service.ActionRequestService; 026 import org.kuali.rice.kew.actionrequest.service.impl.NotificationSuppression; 027 import org.kuali.rice.kew.api.document.DocumentRefreshQueue; 028 import org.kuali.rice.kew.api.WorkflowRuntimeException; 029 import org.kuali.rice.kew.engine.OrchestrationConfig; 030 import org.kuali.rice.kew.engine.OrchestrationConfig.EngineCapability; 031 import org.kuali.rice.kew.engine.RouteHelper; 032 import org.kuali.rice.kew.engine.node.RouteNodeInstance; 033 import org.kuali.rice.kew.engine.node.service.RouteNodeService; 034 import org.kuali.rice.kew.service.KEWServiceLocator; 035 import org.kuali.rice.kew.util.PerformanceLogger; 036 037 038 /** 039 * A service which effectively "refreshes" and requeues a document. It first deletes any 040 * pending action requests on the documents and then requeues the document for standard routing. 041 * Addionally, it adds duplicate notification suppression state to RouteNodeInstanceS for 042 * which ActionRequestS will be regenerated. 043 * 044 * <p>Intended to be called async and wired that way in server/client spring beans.</p> 045 * 046 * @author Kuali Rice Team (rice.collab@kuali.org) 047 */ 048 public class DocumentRefreshQueueImpl implements DocumentRefreshQueue { 049 050 private RouteHelper helper = new RouteHelper(); 051 052 /** 053 * Requeues a document, and sets notification suppression data 054 * 055 * @see org.kuali.rice.kew.api.document.DocumentRefreshQueue#refreshDocument(java.lang.String) 056 */ 057 @Override 058 public void refreshDocument(String documentId) { 059 if (StringUtils.isBlank(documentId)) { 060 throw new RiceIllegalArgumentException("documentId is null or blank"); 061 } 062 063 PerformanceLogger performanceLogger = new PerformanceLogger(); 064 KEWServiceLocator.getRouteHeaderService().lockRouteHeader(documentId, true); 065 Collection<RouteNodeInstance> activeNodes = getRouteNodeService().getActiveNodeInstances(documentId); 066 List<ActionRequestValue> requestsToDelete = new ArrayList<ActionRequestValue>(); 067 068 NotificationSuppression notificationSuppression = new NotificationSuppression(); 069 070 for (RouteNodeInstance nodeInstance : activeNodes) { 071 // only "requeue" if we're dealing with a request activation node 072 if (helper.isRequestActivationNode(nodeInstance.getRouteNode())) { 073 List<ActionRequestValue> deletesForThisNode = 074 getActionRequestService().findPendingRootRequestsByDocIdAtRouteNode(documentId, nodeInstance.getRouteNodeInstanceId()); 075 076 for (ActionRequestValue deleteForThisNode : deletesForThisNode) { 077 // only delete the request if it was generated by a route module (or the rules system) 078 if (deleteForThisNode.isRouteModuleRequest()) { 079 requestsToDelete.add(deleteForThisNode); 080 081 // suppress duplicate notifications 082 notificationSuppression.addNotificationSuppression(nodeInstance, deleteForThisNode); 083 } 084 } 085 // this will trigger a regeneration of requests 086 nodeInstance.setInitial(true); 087 getRouteNodeService().save(nodeInstance); 088 } 089 } 090 for (ActionRequestValue requestToDelete : requestsToDelete) { 091 getActionRequestService().deleteActionRequestGraph(requestToDelete); 092 } 093 try { 094 OrchestrationConfig config = new OrchestrationConfig(EngineCapability.STANDARD); 095 KEWServiceLocator.getWorkflowEngineFactory().newEngine(config).process(documentId, null); 096 } catch (Exception e) { 097 throw new WorkflowRuntimeException(e); 098 } 099 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 }