View Javadoc

1   /*
2    * Copyright 2007 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.ken.postprocessor.kew;
17  
18  import java.io.ByteArrayInputStream;
19  import java.io.IOException;
20  import java.rmi.RemoteException;
21  import java.util.Properties;
22  
23  import org.apache.log4j.Logger;
24  import org.kuali.rice.ken.bo.NotificationMessageDelivery;
25  import org.kuali.rice.ken.core.GlobalNotificationServiceLocator;
26  import org.kuali.rice.ken.deliverer.impl.KEWActionListMessageDeliverer;
27  import org.kuali.rice.ken.service.NotificationMessageDeliveryService;
28  import org.kuali.rice.ken.service.NotificationService;
29  import org.kuali.rice.ken.util.NotificationConstants;
30  import org.kuali.rice.ken.util.Util;
31  import org.kuali.rice.kew.dto.ActionTakenEventDTO;
32  import org.kuali.rice.kew.dto.AfterProcessEventDTO;
33  import org.kuali.rice.kew.dto.BeforeProcessEventDTO;
34  import org.kuali.rice.kew.dto.DeleteEventDTO;
35  import org.kuali.rice.kew.dto.DocumentLockingEventDTO;
36  import org.kuali.rice.kew.dto.DocumentRouteLevelChangeDTO;
37  import org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO;
38  import org.kuali.rice.kew.dto.NetworkIdDTO;
39  import org.kuali.rice.kew.exception.WorkflowException;
40  import org.kuali.rice.kew.postprocessor.PostProcessorRemote;
41  import org.kuali.rice.kew.service.WorkflowDocument;
42  import org.kuali.rice.kew.util.KEWConstants;
43  
44  
45  /**
46   * This class is the post processor that gets run when workflow state changes occur for the 
47   * underlying core NotificationDocumentType that all notifications go into KEW as.  This class is responsible for changing 
48   * the state of the associated notification message delivery record after someone FYIs or ACKs their notification 
49   * in the KEW Action List.
50   * @author Kuali Rice Team (rice.collab@kuali.org)
51   */
52  public class NotificationPostProcessor implements PostProcessorRemote {
53      private static final Logger LOG = Logger.getLogger(NotificationPostProcessor.class);
54  
55      NotificationService notificationService;
56      NotificationMessageDeliveryService msgDeliverySvc;
57  
58      /**
59       * Constructs a NotificationPostProcessor instance.
60       */
61      public NotificationPostProcessor() {
62          this.msgDeliverySvc = GlobalNotificationServiceLocator.getInstance().getNotificationMessageDeliveryService();
63          this.notificationService = GlobalNotificationServiceLocator.getInstance().getNotificationService();
64      }
65  
66      /**
67       * Need to intercept ACKNOWLEDGE or FYI actions taken on notification workflow documents and set the local state of the 
68       * Notification to REMOVED as well.
69       * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#doActionTaken(org.kuali.rice.kew.dto.ActionTakenEventDTO)
70       */
71      public boolean doActionTaken(ActionTakenEventDTO event) throws RemoteException {
72          LOG.debug("ENTERING NotificationPostProcessor.doActionTaken() for Notification action item with route header ID: " + event.getRouteHeaderId());
73  
74          // NOTE: this action could be happening because the user initiated it via KEW, OR because a dismiss or autoremove action
75          // has been invoked programmatically and the KEWActionListMessageDeliverer is taking an action...so there is a risk of being
76          // invoked recursively (which will lead to locking issues and other problems).  We therefore mark the document in the KEWActionList
77          // MessageDeliverer before performing an action, so that we can detect this scenario here, and avoid invoking KEN again.
78  
79          LOG.debug("ACTION TAKEN=" + event.getActionTaken().getActionTaken());
80  
81          String actionTakenCode = event.getActionTaken().getActionTaken();
82  
83          Properties p = new Properties();
84          WorkflowDocument doc;
85          try {
86              doc = new WorkflowDocument(event.getActionTaken().getPrincipalId(), event.getRouteHeaderId());
87          } catch (WorkflowException we) {
88              throw new RuntimeException("Could not create document", we);
89          }
90          try {
91              p.load(new ByteArrayInputStream(doc.getAttributeContent().getBytes()));
92          } catch (IOException ioe) {
93              throw new RuntimeException(ioe);
94          }
95          String internalCommand = p.getProperty(KEWActionListMessageDeliverer.INTERNAL_COMMAND_FLAG);
96  
97          if (Boolean.valueOf(internalCommand)) {
98              LOG.info("Internal command detected by NotificationPostProcessor - will not invoke KEN");
99              return true;
100         }
101         
102         LOG.info("NotificationPostProcessor detected end-user action " + event.getActionTaken().getActionTaken() + " on document " + event.getActionTaken().getRouteHeaderId());
103 
104         if(actionTakenCode.equals(KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD) || actionTakenCode.equals(KEWConstants.ACTION_TAKEN_FYI_CD)) {
105             LOG.debug("User has taken either acknowledge or fy action (action code=" + actionTakenCode + 
106                     ") for Notification action item with route header ID: " + event.getRouteHeaderId() + 
107             ".  We are now changing the status of the associated NotificationMessageDelivery to REMOVED.");
108 
109             try {
110                 NotificationMessageDelivery nmd = msgDeliverySvc.getNotificationMessageDeliveryByDelivererId(event.getRouteHeaderId());
111 
112                 if (nmd == null) {
113                     throw new RuntimeException("Could not find message delivery from workflow document " + event.getRouteHeaderId() + " to dismiss");
114                 }
115 
116                 //get the id of the associated notification message delivery record
117                 String cause;
118                 if (KEWConstants.ACTION_TAKEN_ACKNOWLEDGED_CD.equals(actionTakenCode)) {
119                     cause = NotificationConstants.ACK_CAUSE;
120                 } else if (KEWConstants.ACTION_TAKEN_FYI_CD.equals(actionTakenCode)) {
121                     cause = NotificationConstants.FYI_CAUSE;
122                 } else {
123                     cause = "unknown";
124                 }
125 
126                 LOG.info("Dismissing message id " + nmd.getId() + " due to cause: " + cause);
127                 notificationService.dismissNotificationMessageDelivery(nmd.getId(),
128                         Util.getNotificationSystemUser(),
129                         cause);
130             } catch(Exception e) {
131                 throw new RuntimeException("Error dismissing message", e);
132             }
133         }
134 
135         LOG.debug("LEAVING NotificationPostProcessor.doActionTaken() for Notification action item with route header ID: " + event.getRouteHeaderId());
136         return true;
137     }
138 
139     /**
140      * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#doDeleteRouteHeader(org.kuali.rice.kew.dto.DeleteEventDTO)
141      */
142     public boolean doDeleteRouteHeader(DeleteEventDTO arg0) throws RemoteException {
143         return true;
144     }
145 
146     /**
147      * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#doRouteLevelChange(org.kuali.rice.kew.dto.DocumentRouteLevelChangeDTO)
148      */
149     public boolean doRouteLevelChange(DocumentRouteLevelChangeDTO arg0) throws RemoteException {
150         return true;
151     }
152 
153     /**
154      * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#doRouteStatusChange(org.kuali.rice.kew.dto.DocumentRouteStatusChangeDTO)
155      */
156     public boolean doRouteStatusChange(DocumentRouteStatusChangeDTO arg0) throws RemoteException {
157         return true;
158     }
159 
160     /**
161      * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#beforeProcess(org.kuali.rice.kew.dto.BeforeProcessEventDTO)
162      */
163     public boolean beforeProcess(BeforeProcessEventDTO beforeProcessEvent) throws Exception {
164         return true;
165     }
166 
167     /**
168      * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#afterProcess(org.kuali.rice.kew.dto.AfterProcessEventDTO)
169      */
170     public boolean afterProcess(AfterProcessEventDTO afterProcessEvent) throws Exception {
171         return true;
172     }
173 
174     /**
175      * @see org.kuali.rice.kew.postprocessor.PostProcessorRemote#getDocumentIdsToLock(org.kuali.rice.kew.dto.DocumentLockingEventDTO)
176      */
177 	public Long[] getDocumentIdsToLock(DocumentLockingEventDTO documentLockingEvent) throws Exception {
178 		return null;
179 	}
180     
181     
182     
183     
184 }