View Javadoc
1   /**
2    * Copyright 2005-2016 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.deliverer.impl;
17  
18  import java.io.ByteArrayOutputStream;
19  import java.io.IOException;
20  import java.util.Properties;
21  
22  import org.kuali.rice.ken.bo.NotificationMessageDelivery;
23  import org.kuali.rice.ken.core.GlobalNotificationServiceLocator;
24  import org.kuali.rice.ken.deliverer.NotificationMessageDeliverer;
25  import org.kuali.rice.ken.exception.NotificationAutoRemoveException;
26  import org.kuali.rice.ken.exception.NotificationMessageDeliveryException;
27  import org.kuali.rice.ken.service.NotificationWorkflowDocumentService;
28  import org.kuali.rice.ken.util.NotificationConstants;
29  import org.kuali.rice.ken.util.Util;
30  import org.kuali.rice.kew.api.WorkflowDocument;
31  
32  /**
33   * This class is responsible for describing the default delivery mechanism for the system - the KEW
34   * Action List.
35   * @author Kuali Rice Team (rice.collab@kuali.org)
36   */
37  public class KEWActionListMessageDeliverer implements NotificationMessageDeliverer {
38      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KEWActionListMessageDeliverer.class);
39  
40      /**
41       * Property set in the attribute content that indicates the action received by workflow was
42       * initiated by the Notification System itself (and not an end user)
43       */
44      public static final String INTERNAL_COMMAND_FLAG = "internal_command";
45  
46      private NotificationWorkflowDocumentService notificationWorkflowDocumentService;
47  
48      /**
49       * Constructs a KEWActionListMessageDeliverer.java.
50       */
51      public KEWActionListMessageDeliverer() {
52          this.notificationWorkflowDocumentService = GlobalNotificationServiceLocator.getInstance()
53                  .getNotificationWorkflowDocumentService();
54      }
55  
56      /**
57       * This implementation leverages the workflow integration services to push this notification
58       * into the KEW action list.
59       * @see org.kuali.rice.ken.deliverer.NotificationMessageDeliverer#deliverMessage(org.kuali.rice.ken.bo.NotificationMessageDelivery)
60       */
61      public void deliverMessage(NotificationMessageDelivery messageDelivery) throws NotificationMessageDeliveryException {
62          // make the call to actually generate and ad-hoc route a workflow document
63          String documentId = notificationWorkflowDocumentService.createAndAdHocRouteNotificationWorkflowDocument(
64                  messageDelivery,
65                  Util.getNotificationSystemUser(),
66                  messageDelivery.getUserRecipientId(),
67                  NotificationConstants.KEW_CONSTANTS.GENERIC_DELIVERY_ANNOTATION);
68  
69          // now set the workflow doc id into the message delivery's delivery system id
70          messageDelivery.setDeliverySystemId(documentId);
71          LOG.debug("Message Delivery: " + messageDelivery.toString());
72      }
73  
74      /**
75       * This implementation does an auto-remove by "canceling" the workflow document associated with
76       * the message delivery record. This prevents the user from seeing the item in their list
77       * anymore.
78       * @see org.kuali.rice.ken.deliverer.NotificationMessageDeliverer#autoRemoveMessageDelivery(org.kuali.rice.ken.bo.NotificationMessageDelivery)
79       */
80      public void autoRemoveMessageDelivery(NotificationMessageDelivery messageDelivery)
81              throws NotificationAutoRemoveException {
82          // first retrieve the appropriate notification workflow document to "auto-remove" and proxy as the recipient
83          WorkflowDocument workflowDoc = null;
84          String sysId = messageDelivery.getDeliverySystemId();
85          if (sysId == null) {
86              LOG.error("NotificationMessageDelivery " + messageDelivery.getId()
87                      + " is missing delivery system id (workflow document id");
88              // there is no possibility for recovery, so since there is no id, we'll just log an error and return successfully instead
89              // of throwing an exception
90              return;
91          }
92  
93          workflowDoc = notificationWorkflowDocumentService.getNotificationWorkflowDocumentByDocumentId(
94                  messageDelivery.getUserRecipientId(), sysId);
95  
96          flagWorkflowDocument(workflowDoc);
97  
98          notificationWorkflowDocumentService.clearAllFyisAndAcknowledgeNotificationWorkflowDocument(
99                  messageDelivery.getUserRecipientId(), workflowDoc,
100                 NotificationConstants.KEW_CONSTANTS.GENERIC_AUTO_REMOVE_ANNOTATION);
101     }
102 
103     /**
104      * @see org.kuali.rice.ken.deliverer.NotificationMessageDeliverer#dismissMessageDelivery(org.kuali.rice.ken.bo.NotificationMessageDelivery,
105      *      java.lang.String, java.lang.String)
106      */
107     public void dismissMessageDelivery(NotificationMessageDelivery messageDelivery, String user, String cause) {
108         // TODO: move hardcoded web controller actions here...
109         LOG.info("Dismissing as user '" + user + "' workflow document '" + messageDelivery.getDeliverySystemId()
110                 + "' corresponding to message delivery #" + messageDelivery.getId() + " due to cause: " + cause);
111         if (NotificationConstants.AUTO_REMOVE_CAUSE.equals(cause)) {
112             // perform an auto-remove
113             // XXX: currently auto-removes are going through autoremove method
114         } else {
115             WorkflowDocument nwd;
116             nwd = notificationWorkflowDocumentService.getNotificationWorkflowDocumentByDocumentId(user,
117                     messageDelivery.getDeliverySystemId());
118 
119             flagWorkflowDocument(nwd);
120 
121             if (NotificationConstants.ACK_CAUSE.equals(cause)) {
122                 // moved from NotificationController, ack command
123                 /*
124                  * acknowledge using workflow docId
125                  */
126                 if (nwd.isAcknowledgeRequested()) {
127                     nwd.acknowledge("This notification has been acknowledged.");
128                     LOG.debug("acknowledged " + nwd.getTitle());
129                     LOG.debug("status display value: " + nwd.getStatus().getLabel());
130                 } else {
131                     LOG.debug("Acknowledgement was not needed for document " + nwd.getDocumentId());
132                 }
133             } else if (NotificationConstants.FYI_CAUSE.equals(cause)) {
134                 // moved from NotificationController, fyi command
135                 /*
136                  * FYI using workflow docId
137                  */
138                 if (nwd.isFYIRequested()) {
139                     nwd.fyi();
140                     LOG.debug("fyi " + nwd.getTitle());
141                     LOG.debug("status display value: " + nwd.getStatus().getLabel());
142                 } else {
143                     LOG.debug("FYI was not needed for document " + nwd.getDocumentId());
144                 }
145             }
146         }
147     }
148 
149     /**
150      * Marks the workflow document as originating from the Notification System, so that the
151      * Notification post-processor does not route the action back through the Notification System.
152      * @param doc the doc to monogram
153      */
154     protected void flagWorkflowDocument(WorkflowDocument doc) {
155         Properties p = new Properties();
156         p.setProperty(INTERNAL_COMMAND_FLAG, "true");
157         ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
158         try {
159             p.store(baos, null);
160         } catch (IOException ioe) {
161             throw new RuntimeException("Could not store properties", ioe);
162         }
163         doc.setAttributeContent("<whatever>" + new String(baos.toByteArray()) + "</whatever>");
164     }
165 }