Coverage Report - org.kuali.rice.ken.web.spring.AdministerNotificationRequestController
 
Classes in this File Line Coverage Branch Coverage Complexity
AdministerNotificationRequestController
0%
0/97
0%
0/40
2.238
AdministerNotificationRequestController$AdministerNotificationRequestCommand
0%
0/20
N/A
2.238
 
 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.web.spring;
 17  
 
 18  
 import java.util.Date;
 19  
 import java.util.HashMap;
 20  
 import java.util.List;
 21  
 import java.util.Map;
 22  
 
 23  
 import javax.servlet.ServletException;
 24  
 import javax.servlet.http.HttpServletRequest;
 25  
 import javax.servlet.http.HttpServletResponse;
 26  
 
 27  
 import org.apache.commons.lang.StringUtils;
 28  
 import org.apache.log4j.Logger;
 29  
 import org.kuali.rice.ken.bo.Notification;
 30  
 import org.kuali.rice.ken.bo.NotificationChannelReviewer;
 31  
 import org.kuali.rice.ken.document.kew.NotificationWorkflowDocument;
 32  
 import org.kuali.rice.ken.service.NotificationMessageContentService;
 33  
 import org.kuali.rice.ken.service.NotificationRecipientService;
 34  
 import org.kuali.rice.ken.service.NotificationWorkflowDocumentService;
 35  
 import org.kuali.rice.ken.util.NotificationConstants;
 36  
 import org.kuali.rice.ken.util.Util;
 37  
 import org.kuali.rice.kew.dto.NetworkIdDTO;
 38  
 import org.kuali.rice.kew.dto.WorkflowIdDTO;
 39  
 import org.kuali.rice.kew.service.WorkflowDocument;
 40  
 import org.kuali.rice.kim.bo.Person;
 41  
 import org.kuali.rice.kim.service.KIMServiceLocator;
 42  
 import org.kuali.rice.kim.util.KimConstants.KimGroupMemberTypes;
 43  
 import org.springframework.validation.BindException;
 44  
 import org.springframework.validation.ValidationUtils;
 45  
 import org.springframework.web.bind.ServletRequestBindingException;
 46  
 import org.springframework.web.servlet.ModelAndView;
 47  
 import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
 48  
 
 49  
 
 50  
 /**
 51  
  * Implements reviewer Approve/Disapprove and initiator Acknowledge of a Notification requests
 52  
  * sent to channels configured with reviewers
 53  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 54  
  */
 55  0
 public class AdministerNotificationRequestController extends MultiActionController {
 56  0
     private static final Logger LOG = Logger.getLogger(AdministerNotificationRequestController.class);
 57  
 
 58  
     /**
 59  
      * Command object for this controller
 60  
      */
 61  0
     public static class AdministerNotificationRequestCommand {
 62  
         // incoming
 63  
         private Long docId;
 64  
 
 65  
         // outgoing
 66  
         private NotificationWorkflowDocument document;
 67  
         private Notification notification;
 68  
         private String renderedContent;
 69  0
         private boolean valid = true;
 70  
         private String message;
 71  
 
 72  
         public Long getDocId() {
 73  0
             return docId;
 74  
         }
 75  
         public void setDocId(Long docId) {
 76  0
             this.docId = docId;
 77  0
         }
 78  
         public NotificationWorkflowDocument getDocument() {
 79  0
             return document;
 80  
         }
 81  
         public void setDocument(NotificationWorkflowDocument document) {
 82  0
             this.document = document;
 83  0
         }
 84  
         public Notification getNotification() {
 85  0
             return notification;
 86  
         }
 87  
         public void setNotification(Notification notification) {
 88  0
             this.notification = notification;
 89  0
         }
 90  
         public String getRenderedContent() {
 91  0
             return renderedContent;
 92  
         }
 93  
         public void setRenderedContent(String renderedContent) {
 94  0
             this.renderedContent = renderedContent;
 95  0
         }
 96  
         public boolean isValid() {
 97  0
             return valid;
 98  
         }
 99  
         public void setValid(boolean valid) {
 100  0
             this.valid = valid;
 101  0
         }
 102  
         public String getMessage() {
 103  0
             return message;
 104  
         }
 105  
         public void setMessage(String message) {
 106  0
             this.message = message;
 107  0
         }
 108  
     }
 109  
 
 110  
     protected NotificationMessageContentService messageContentService;
 111  
     protected NotificationWorkflowDocumentService workflowDocumentService;
 112  
     protected NotificationRecipientService recipientService;
 113  
 
 114  
     /**
 115  
      * Sets the messageContentService attribute value.
 116  
      * @param messageContentService the NotificationMessageContentService impl
 117  
      */
 118  
     public void setMessageContentService(
 119  
             NotificationMessageContentService notificationMessageContentService) {
 120  0
         this.messageContentService = notificationMessageContentService;
 121  0
     }
 122  
 
 123  
     /**
 124  
      * Sets the workflowDocumentService attribute value.
 125  
      * @param workflowDocumentService the NotificationWorkflowDocumentService impl
 126  
      */
 127  
     public void setWorkflowDocumentService(
 128  
             NotificationWorkflowDocumentService notificationWorkflowDocumentService) {
 129  0
         this.workflowDocumentService = notificationWorkflowDocumentService;
 130  0
     }
 131  
 
 132  
     /**
 133  
      * Sets the recipientService attribute value.
 134  
      * @param recipientService the NotificationRecipientService impl
 135  
      */
 136  
     public void setRecipientService(
 137  
             NotificationRecipientService notificationRecipientService) {
 138  0
         this.recipientService = notificationRecipientService;
 139  0
     }
 140  
 
 141  
     /**
 142  
      * Parses the serialized Notification xml from the workflow document application content into a reconstituted
 143  
      * Notification BO
 144  
      * @param document the WorkflowDocument
 145  
      * @return a Notification BO reconstituted from the serialized XML form in the workflow document
 146  
      * @throws Exception if parsing fails
 147  
      */
 148  
     private Notification retrieveNotificationForWorkflowDocument(WorkflowDocument document) throws Exception {
 149  0
         String notificationAsXml = document.getApplicationContent();
 150  
 
 151  
         //parse out the application content into a Notification BO
 152  0
         Notification notification = messageContentService.parseSerializedNotificationXml(notificationAsXml.getBytes());
 153  
 
 154  0
         return notification;
 155  
     }
 156  
 
 157  
     /**
 158  
      * View action that displays an approve/disapprove/acknowledge view
 159  
      * @param request the HttpServletRequest
 160  
      * @param response the HttpServletResponse
 161  
      * @param command the command object bound for this MultiActionController
 162  
      * @return a view ModelAndView
 163  
      */
 164  
     public ModelAndView view(HttpServletRequest request, HttpServletResponse response, AdministerNotificationRequestCommand command) {
 165  
         // obtain a workflow user object first
 166  0
         WorkflowIdDTO initiator = new WorkflowIdDTO(request.getRemoteUser());
 167  
 
 168  
         // now construct the workflow document, which will interact with workflow
 169  0
         if (command.getDocId() == null) {
 170  0
             throw new RuntimeException("An invalid document ID was recieved from KEW's action list.");
 171  
         }
 172  
 
 173  
         //check to see which view is being passed to us from the notification list - pop up or inline
 174  0
         String view = request.getParameter(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.COMMAND);
 175  0
         String standaloneWindow = "true";
 176  0
         if(view != null && view.equals(NotificationConstants.NOTIFICATION_DETAIL_VIEWS.INLINE)) {
 177  0
             standaloneWindow = "false";
 178  
         }
 179  
 
 180  
         NotificationWorkflowDocument document;
 181  0
         Map<String, Object> model = new HashMap<String, Object>();
 182  
         // set into model whether we are dealing with a pop up or an inline window
 183  0
         model.put(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW, standaloneWindow);
 184  
         try {
 185  0
             document = new NotificationWorkflowDocument(initiator, new Long(command.getDocId()));
 186  
 
 187  0
             Notification notification = retrieveNotificationForWorkflowDocument(document);
 188  
 
 189  
             // set up model
 190  0
             command.setDocument(document);
 191  0
             command.setNotification(notification);
 192  
             // render the event content according to registered XSLT stylesheet
 193  0
             command.setRenderedContent(Util.transformContent(notification));
 194  
 
 195  0
             LOG.info("notification auto remove date time: " + notification.getAutoRemoveDateTime());
 196  0
             if (document.stateIsApproved()) {
 197  0
                 command.setValid(false);
 198  0
                 command.setMessage("This notification request has been approved.");
 199  0
             } else if (document.stateIsDisapproved()) {
 200  0
                 command.setMessage("This notification request has been disapproved.");
 201  0
             } else if (notification.getAutoRemoveDateTime() != null && notification.getAutoRemoveDateTime().before(new Date(System.currentTimeMillis()))) {
 202  
                 /*if (!document.stateIsCanceled()) {
 203  
                 workflowDocumentService.terminateWorkflowDocument(new WorkflowDocument(new NetworkIdVO("notsys"), new Long(command.getDocId())));
 204  
                 }*/
 205  
                 // the autoremove date time has already passed...this notification request is null and void at this time
 206  0
                 boolean disapproved = document.stateIsDisapproved();
 207  0
                 if (!document.stateIsDisapproved()) {
 208  0
                     List<NotificationChannelReviewer> reviewers = notification.getChannel().getReviewers();
 209  0
                     String user = null;
 210  0
                     for (NotificationChannelReviewer reviewer: reviewers) {
 211  0
                         if (KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE.equals(reviewer.getReviewerType())) {
 212  0
                             if (reviewer.getReviewerId().equals(request.getRemoteUser())) {
 213  0
                                 user = request.getRemoteUser();
 214  
                             }
 215  0
                         } else if (KimGroupMemberTypes.GROUP_MEMBER_TYPE.equals(reviewer.getReviewerType())) {
 216  
                             // if it's a group
 217  0
                             String[] members = recipientService.getGroupMembers(reviewer.getReviewerId());
 218  0
                             for (String member: members) {
 219  0
                                 if (StringUtils.equals(member, request.getRemoteUser())) {
 220  0
                                     user = request.getRemoteUser();
 221  0
                                     break;
 222  
                                 }
 223  
                             }
 224  0
                         }
 225  
                     }
 226  
                     // if the current user is a reviewer, then disapprove as that user
 227  0
                     if (user != null) {
 228  0
                         new WorkflowDocument(new NetworkIdDTO(user), new Long(command.getDocId())).disapprove("Disapproving notification request.  Auto-remove datetime has already passed.");
 229  0
                         disapproved = true;
 230  
                     }
 231  
                 }
 232  0
                 command.setValid(false);
 233  0
                 if (disapproved) {
 234  0
                     command.setMessage("This notification request is no longer valid because the Auto-Remove date has already passed.  It has been disapproved.  Please refresh your action list.");
 235  
                 } else {
 236  0
                     command.setMessage("This notification request is no longer valid because the Auto-Remove date has already passed.");
 237  
                 }
 238  
             }
 239  
 
 240  0
             model.put(getCommandName(command), command);
 241  0
         } catch (Exception e) {
 242  0
             throw new RuntimeException(e);
 243  0
         }
 244  
 
 245  0
         return new ModelAndView("ViewNotificationRequestDetails", model);
 246  
     }
 247  
 
 248  
     /**
 249  
      * Approve action that approves a notification request
 250  
      * @param request the HttpServletRequest
 251  
      * @param response the HttpServletResponse
 252  
      * @param command the command object bound for this MultiActionController
 253  
      * @return a view ModelAndView
 254  
      * @throws ServletException if an error occurs during approval
 255  
      */
 256  
     public ModelAndView approve(HttpServletRequest request, HttpServletResponse response, AdministerNotificationRequestCommand command) throws ServletException {
 257  0
         administerEventNotificationMessage(request, response, command, "approve");
 258  0
         Map<String, Object> model = new HashMap<String, Object>();
 259  0
         model.put("workflowActionTaken", "Approved");
 260  0
         model.put(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW, request.getParameter(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW));
 261  0
         return new ModelAndView("SendNotificationRequestActionTakenWindow", model);
 262  
     }
 263  
 
 264  
     /**
 265  
      * Disapprove action that disapproves a notification request
 266  
      * @param request the HttpServletRequest
 267  
      * @param response the HttpServletResponse
 268  
      * @param command the command object bound for this MultiActionController
 269  
      * @return a view ModelAndView
 270  
      * @throws ServletException if an error occurs during disapproval
 271  
      */
 272  
     public ModelAndView disapprove(HttpServletRequest request, HttpServletResponse response, AdministerNotificationRequestCommand command) throws ServletException {
 273  0
         administerEventNotificationMessage(request, response, command, "disapprove");
 274  0
         Map<String, Object> model = new HashMap<String, Object>();
 275  0
         model.put("workflowActionTaken", "Disapproved");
 276  0
         model.put(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW, request.getParameter(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW));
 277  0
         return new ModelAndView("SendNotificationRequestActionTakenWindow", model);
 278  
     }
 279  
 
 280  
     /**
 281  
      * Acknowledge action that acknowledges a notification request disapproval
 282  
      * @param request the HttpServletRequest
 283  
      * @param response the HttpServletResponse
 284  
      * @param command the command object bound for this MultiActionController
 285  
      * @return a view ModelAndView
 286  
      * @throws ServletException if an error occurs during acknowledgement
 287  
      */
 288  
     public ModelAndView acknowledge(HttpServletRequest request, HttpServletResponse response, AdministerNotificationRequestCommand command) throws ServletException {
 289  0
         administerEventNotificationMessage(request, response, command, "acknowledge");
 290  0
         Map<String, Object> model = new HashMap<String, Object>();
 291  0
         model.put(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW, request.getParameter(NotificationConstants.NOTIFICATION_CONTROLLER_CONSTANTS.STANDALONE_WINDOW));
 292  0
         model.put("workflowActionTaken", "Acknowledged");
 293  0
         return new ModelAndView("SendNotificationRequestActionTakenWindow", model);
 294  
     }
 295  
 
 296  
     /**
 297  
      * This method handles approval/disapproval/acknowledgement of the notification request
 298  
      * @param request the HttpServletRequest
 299  
      * @param response the HttpServletResponse
 300  
      * @param command the command object bound for this MultiActionController
 301  
      * @throws ServletException
 302  
      */
 303  
     private void administerEventNotificationMessage(HttpServletRequest request, HttpServletResponse response, AdministerNotificationRequestCommand command, String action) throws ServletException {
 304  0
         LOG.debug("remoteUser: " + request.getRemoteUser());
 305  
 
 306  0
         BindException bindException = new BindException(command, "command");
 307  0
         ValidationUtils.rejectIfEmpty(bindException, "docId", "Document id must be specified");
 308  0
         if (bindException.hasErrors()) {
 309  0
             throw new ServletRequestBindingException("Document id must be specified", bindException);
 310  
         }
 311  
 
 312  
         // obtain a workflow user object first
 313  0
         WorkflowIdDTO user = new WorkflowIdDTO(request.getRemoteUser());
 314  
 
 315  
         try {
 316  
             // now construct the workflow document, which will interact with workflow
 317  0
             NotificationWorkflowDocument document = new NotificationWorkflowDocument(user, command.getDocId());
 318  
 
 319  0
             Notification notification = retrieveNotificationForWorkflowDocument(document);
 320  
 
 321  0
             String initiatorPrincipalId = document.getRouteHeader().getInitiatorPrincipalId();
 322  0
             Person initiator = KIMServiceLocator.getPersonService().getPerson(initiatorPrincipalId);
 323  0
             String notificationBlurb =  notification.getContentType().getName() + " notification submitted by " + initiator.getName() + " for channel " + notification.getChannel().getName();
 324  0
             if ("disapprove".equals(action)) {
 325  0
                 document.disapprove("User " + user.getWorkflowId() + " disapproving " + notificationBlurb);
 326  0
             } else if ("approve".equals(action)) {
 327  0
                 document.approve("User " + user.getWorkflowId() + " approving " + notificationBlurb);
 328  0
             } else if ("acknowledge".equals(action)) {
 329  0
                 document.acknowledge("User " + user.getWorkflowId() + " acknowledging " + notificationBlurb);
 330  
             }
 331  0
         } catch (Exception e) {
 332  0
             LOG.error("Exception occurred taking action on notification request", e);
 333  0
             throw new ServletException("Exception occurred taking action on notification request", e);
 334  0
         }
 335  0
     }
 336  
 }