001 /* 002 * Copyright 2007 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.ken.postprocessor.kew; 017 018 import java.io.ByteArrayInputStream; 019 import java.io.IOException; 020 import java.rmi.RemoteException; 021 import java.util.Properties; 022 023 import org.apache.log4j.Logger; 024 import org.kuali.rice.ken.bo.NotificationMessageDelivery; 025 import org.kuali.rice.ken.core.GlobalNotificationServiceLocator; 026 import org.kuali.rice.ken.deliverer.impl.KEWActionListMessageDeliverer; 027 import org.kuali.rice.ken.service.NotificationMessageDeliveryService; 028 import org.kuali.rice.ken.service.NotificationService; 029 import org.kuali.rice.ken.util.NotificationConstants; 030 import org.kuali.rice.ken.util.Util; 031 import org.kuali.rice.kew.api.WorkflowDocument; 032 import org.kuali.rice.kew.api.WorkflowDocumentFactory; 033 import org.kuali.rice.kew.dto.ActionTakenEventDTO; 034 import org.kuali.rice.kew.dto.AfterProcessEventDTO; 035 import org.kuali.rice.kew.dto.BeforeProcessEventDTO; 036 import org.kuali.rice.kew.dto.DeleteEventDTO; 037 import org.kuali.rice.kew.dto.DocumentLockingEventDTO; 038 import org.kuali.rice.kew.dto.DocumentRouteLevelChangeDTO; 039 import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO; 040 import org.kuali.rice.kew.postprocessor.PostProcessorRemote; 041 import org.kuali.rice.kew.util.KEWConstants; 042 043 044 /** 045 * This class is the post processor that gets run when workflow state changes occur for the 046 * underlying core NotificationDocumentType that all notifications go into KEW as. This class is responsible for changing 047 * the state of the associated notification message delivery record after someone FYIs or ACKs their notification 048 * in the KEW Action List. 049 * @author Kuali Rice Team (rice.collab@kuali.org) 050 */ 051 public class NotificationPostProcessor implements PostProcessorRemote { 052 private static final Logger LOG = Logger.getLogger(NotificationPostProcessor.class); 053 054 NotificationService notificationService; 055 NotificationMessageDeliveryService msgDeliverySvc; 056 057 /** 058 * Constructs a NotificationPostProcessor instance. 059 */ 060 public NotificationPostProcessor() { 061 this.msgDeliverySvc = GlobalNotificationServiceLocator.getInstance().getNotificationMessageDeliveryService(); 062 this.notificationService = GlobalNotificationServiceLocator.getInstance().getNotificationService(); 063 } 064 065 /** 066 * Need to intercept ACKNOWLEDGE or FYI actions taken on notification workflow documents and set the local state of the 067 * Notification to REMOVED as well. 068 * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#doActionTaken(org.kuali.rice.kew.dto.ActionTakenEventDTO) 069 */ 070 public boolean doActionTaken(ActionTakenEventDTO event) throws RemoteException { 071 LOG.debug("ENTERING NotificationPostProcessor.doActionTaken() for Notification action item with document ID: " + event.getDocumentId()); 072 073 // NOTE: this action could be happening because the user initiated it via KEW, OR because a dismiss or autoremove action 074 // has been invoked programmatically and the KEWActionListMessageDeliverer is taking an action...so there is a risk of being 075 // invoked recursively (which will lead to locking issues and other problems). We therefore mark the document in the KEWActionList 076 // MessageDeliverer before performing an action, so that we can detect this scenario here, and avoid invoking KEN again. 077 078 LOG.debug("ACTION TAKEN=" + event.getActionTaken().getActionTaken()); 079 080 String actionTakenCode = event.getActionTaken().getActionTaken(); 081 082 Properties p = new Properties(); 083 WorkflowDocument doc = WorkflowDocumentFactory.loadDocument(event.getActionTaken().getPrincipalId(), event.getDocumentId()); 084 try { 085 p.load(new ByteArrayInputStream(doc.getAttributeContent().getBytes())); 086 } catch (IOException ioe) { 087 throw new RuntimeException(ioe); 088 } 089 String internalCommand = p.getProperty(KEWActionListMessageDeliverer.INTERNAL_COMMAND_FLAG); 090 091 if (Boolean.valueOf(internalCommand)) { 092 LOG.info("Internal command detected by NotificationPostProcessor - will not invoke KEN"); 093 return true; 094 } 095 096 LOG.info("NotificationPostProcessor detected end-user action " + event.getActionTaken().getActionTaken() + " on document " + event.getActionTaken().getDocumentId()); 097 098 if(actionTakenCode.equals(KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD) || actionTakenCode.equals(KEWConstants.ACTION_TAKEN_FYI_CD)) { 099 LOG.debug("User has taken either acknowledge or fy action (action code=" + actionTakenCode + 100 ") for Notification action item with document ID: " + event.getDocumentId() + 101 ". We are now changing the status of the associated NotificationMessageDelivery to REMOVED."); 102 103 try { 104 NotificationMessageDelivery nmd = msgDeliverySvc.getNotificationMessageDeliveryByDelivererId(event.getDocumentId()); 105 106 if (nmd == null) { 107 throw new RuntimeException("Could not find message delivery from workflow document " + event.getDocumentId() + " to dismiss"); 108 } 109 110 //get the id of the associated notification message delivery record 111 String cause; 112 if (KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD.equals(actionTakenCode)) { 113 cause = NotificationConstants.ACK_CAUSE; 114 } else if (KEWConstants.ACTION_TAKEN_FYI_CD.equals(actionTakenCode)) { 115 cause = NotificationConstants.FYI_CAUSE; 116 } else { 117 cause = "unknown"; 118 } 119 120 LOG.info("Dismissing message id " + nmd.getId() + " due to cause: " + cause); 121 notificationService.dismissNotificationMessageDelivery(nmd.getId(), 122 Util.getNotificationSystemUser(), 123 cause); 124 } catch(Exception e) { 125 throw new RuntimeException("Error dismissing message", e); 126 } 127 } 128 129 LOG.debug("LEAVING NotificationPostProcessor.doActionTaken() for Notification action item with document ID: " + event.getDocumentId()); 130 return true; 131 } 132 133 /** 134 * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#doDeleteRouteHeader(org.kuali.rice.kew.dto.DeleteEventDTO) 135 */ 136 public boolean doDeleteRouteHeader(DeleteEventDTO arg0) throws RemoteException { 137 return true; 138 } 139 140 /** 141 * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#doRouteLevelChange(org.kuali.rice.kew.dto.DocumentRouteLevelChangeDTO) 142 */ 143 public boolean doRouteLevelChange(DocumentRouteLevelChangeDTO arg0) throws RemoteException { 144 return true; 145 } 146 147 /** 148 * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#doRouteStatusChange(org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO) 149 */ 150 public boolean doRouteStatusChange(DocumentRouteStatusChangeDTO arg0) throws RemoteException { 151 return true; 152 } 153 154 /** 155 * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#beforeProcess(org.kuali.rice.kew.dto.BeforeProcessEventDTO) 156 */ 157 public boolean beforeProcess(BeforeProcessEventDTO beforeProcessEvent) throws Exception { 158 return true; 159 } 160 161 /** 162 * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#afterProcess(org.kuali.rice.kew.dto.AfterProcessEventDTO) 163 */ 164 public boolean afterProcess(AfterProcessEventDTO afterProcessEvent) throws Exception { 165 return true; 166 } 167 168 /** 169 * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#getDocumentIdsToLock(org.kuali.rice.kew.dto.DocumentLockingEventDTO) 170 */ 171 public String[] getDocumentIdsToLock(DocumentLockingEventDTO documentLockingEvent) throws Exception { 172 return null; 173 } 174 175 176 177 178 }