Coverage Report - org.kuali.rice.ken.web.spring.SendEventNotificationMessageController
 
Classes in this File Line Coverage Branch Coverage Complexity
SendEventNotificationMessageController
0%
0/250
0%
0/118
6.833
 
 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.io.IOException;
 19  
 import java.sql.Timestamp;
 20  
 import java.text.ParseException;
 21  
 import java.util.Date;
 22  
 import java.util.HashMap;
 23  
 import java.util.List;
 24  
 import java.util.Map;
 25  
 
 26  
 import javax.servlet.ServletException;
 27  
 import javax.servlet.http.HttpServletRequest;
 28  
 import javax.servlet.http.HttpServletResponse;
 29  
 
 30  
 import org.apache.commons.lang.StringUtils;
 31  
 import org.apache.log4j.Logger;
 32  
 import org.kuali.rice.core.dao.GenericDao;
 33  
 import org.kuali.rice.ken.bo.Notification;
 34  
 import org.kuali.rice.ken.bo.NotificationChannel;
 35  
 import org.kuali.rice.ken.bo.NotificationChannelReviewer;
 36  
 import org.kuali.rice.ken.bo.NotificationContentType;
 37  
 import org.kuali.rice.ken.bo.NotificationPriority;
 38  
 import org.kuali.rice.ken.bo.NotificationProducer;
 39  
 import org.kuali.rice.ken.bo.NotificationRecipient;
 40  
 import org.kuali.rice.ken.bo.NotificationSender;
 41  
 import org.kuali.rice.ken.document.kew.NotificationWorkflowDocument;
 42  
 import org.kuali.rice.ken.exception.ErrorList;
 43  
 import org.kuali.rice.ken.service.NotificationChannelService;
 44  
 import org.kuali.rice.ken.service.NotificationMessageContentService;
 45  
 import org.kuali.rice.ken.service.NotificationRecipientService;
 46  
 import org.kuali.rice.ken.service.NotificationService;
 47  
 import org.kuali.rice.ken.service.NotificationWorkflowDocumentService;
 48  
 import org.kuali.rice.ken.util.NotificationConstants;
 49  
 import org.kuali.rice.ken.util.Util;
 50  
 import org.kuali.rice.kew.dto.WorkflowIdDTO;
 51  
 import org.kuali.rice.kew.rule.GenericAttributeContent;
 52  
 import org.kuali.rice.kim.util.KimConstants.KimGroupMemberTypes;
 53  
 import org.springframework.web.servlet.ModelAndView;
 54  
 
 55  
 
 56  
 /**
 57  
  * This class is the controller for sending Event notification messages via an end user interface.
 58  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 59  
  */
 60  0
 public class SendEventNotificationMessageController extends BaseSendNotificationController {
 61  
     /** Logger for this class and subclasses */
 62  0
     private static final Logger LOG = Logger
 63  
             .getLogger(SendEventNotificationMessageController.class);
 64  
 
 65  
     private static final String NONE_CHANNEL = "___NONE___";
 66  
     private static final long REASONABLE_IMMEDIATE_TIME_THRESHOLD = 1000 * 60 * 5; // <= 5 minutes is "immediate"
 67  
 
 68  
     /**
 69  
      * Returns whether the specified time is considered "in the future", based on some reasonable threshold
 70  
      * @param time the time to test
 71  
      * @return whether the specified time is considered "in the future", based on some reasonable threshold
 72  
      */
 73  
     private boolean timeIsInTheFuture(long time) {
 74  0
         boolean future = (time - System.currentTimeMillis()) > REASONABLE_IMMEDIATE_TIME_THRESHOLD;
 75  0
         LOG.info("Time: " + new Date(time) + " is in the future? " + future);
 76  0
         return future;
 77  
     }
 78  
 
 79  
     /**
 80  
      * Returns whether the specified Notification can be reasonably expected to have recipients.
 81  
      * This is determined on whether the channel has default recipients, is subscribably, and whether
 82  
      * the send date time is far enough in the future to expect that if there are no subscribers, there
 83  
      * may actually be some by the time the notification is sent.
 84  
      * @param notification the notification to test
 85  
      * @return whether the specified Notification can be reasonably expected to have recipients
 86  
      */
 87  
     private boolean hasPotentialRecipients(Notification notification) {
 88  0
         LOG.info("notification channel " + notification.getChannel() + " is subscribable: " + notification.getChannel().isSubscribable());
 89  0
         return notification.getChannel().getRecipientLists().size() > 0 ||
 90  
                notification.getChannel().getSubscriptions().size() > 0 ||
 91  
                (notification.getChannel().isSubscribable() && timeIsInTheFuture(notification.getSendDateTime().getTime()));
 92  
     }
 93  
 
 94  
     protected NotificationService notificationService;
 95  
 
 96  
     protected NotificationWorkflowDocumentService notificationWorkflowDocService;
 97  
 
 98  
     protected NotificationChannelService notificationChannelService;
 99  
 
 100  
     protected NotificationRecipientService notificationRecipientService;
 101  
 
 102  
     protected NotificationMessageContentService messageContentService;
 103  
 
 104  
     protected GenericDao businessObjectDao;
 105  
 
 106  
     /**
 107  
      * Set the NotificationService
 108  
      * @param notificationService
 109  
      */
 110  
     public void setNotificationService(NotificationService notificationService) {
 111  0
         this.notificationService = notificationService;
 112  0
     }
 113  
 
 114  
     /**
 115  
      * This method sets the NotificationWorkflowDocumentService
 116  
      * @param s
 117  
      */
 118  
     public void setNotificationWorkflowDocumentService(
 119  
             NotificationWorkflowDocumentService s) {
 120  0
         this.notificationWorkflowDocService = s;
 121  0
     }
 122  
 
 123  
     /**
 124  
      * Sets the notificationChannelService attribute value.
 125  
      * @param notificationChannelService The notificationChannelService to set.
 126  
      */
 127  
     public void setNotificationChannelService(
 128  
             NotificationChannelService notificationChannelService) {
 129  0
         this.notificationChannelService = notificationChannelService;
 130  0
     }
 131  
 
 132  
     /**
 133  
      * Sets the notificationRecipientService attribute value.
 134  
      * @param notificationRecipientService
 135  
      */
 136  
     public void setNotificationRecipientService(
 137  
             NotificationRecipientService notificationRecipientService) {
 138  0
         this.notificationRecipientService = notificationRecipientService;
 139  0
     }
 140  
 
 141  
     /**
 142  
      * Sets the messageContentService attribute value.
 143  
      * @param messageContentService
 144  
      */
 145  
     public void setMessageContentService(
 146  
             NotificationMessageContentService notificationMessageContentService) {
 147  0
         this.messageContentService = notificationMessageContentService;
 148  0
     }
 149  
 
 150  
     /**
 151  
      * Sets the businessObjectDao attribute value.
 152  
      * @param businessObjectDao The businessObjectDao to set.
 153  
      */
 154  
     public void setBusinessObjectDao(GenericDao businessObjectDao) {
 155  0
         this.businessObjectDao = businessObjectDao;
 156  0
     }
 157  
 
 158  
     /**
 159  
      * Handles the display of the form for sending an event notification message
 160  
      * @param request : a servlet request
 161  
      * @param response : a servlet response
 162  
      * @throws ServletException : an exception
 163  
      * @throws IOException : an exception
 164  
      * @return a ModelAndView object
 165  
      */
 166  
     public ModelAndView sendEventNotificationMessage(
 167  
             HttpServletRequest request, HttpServletResponse response)
 168  
             throws ServletException, IOException {
 169  0
         String view = "SendEventNotificationMessage";
 170  0
         LOG.debug("remoteUser: " + request.getRemoteUser());
 171  
 
 172  0
         Map<String, Object> model = setupModelForSendEventNotification(request);
 173  0
         model.put("errors", new ErrorList()); // need an empty one so we don't have an NPE
 174  
 
 175  0
         return new ModelAndView(view, model);
 176  
     }
 177  
 
 178  
     /**
 179  
      * This method prepares the model used for the send event notification message form.
 180  
      * @param request
 181  
      * @return Map<String, Object>
 182  
      */
 183  
     private Map<String, Object> setupModelForSendEventNotification(
 184  
             HttpServletRequest request) {
 185  0
         Map<String, Object> model = new HashMap<String, Object>();
 186  0
         model.put("defaultSender", request.getRemoteUser());
 187  0
         model.put("channels", notificationChannelService
 188  
                 .getAllNotificationChannels());
 189  0
         model.put("priorities", businessObjectDao
 190  
                 .findAll(NotificationPriority.class));
 191  
         // set sendDateTime to current datetime if not provided
 192  0
         String sendDateTime = request.getParameter("sendDateTime");
 193  0
         String currentDateTime = Util.getCurrentDateTime();
 194  0
         if (StringUtils.isEmpty(sendDateTime)) {
 195  0
             sendDateTime = currentDateTime;
 196  
         }
 197  0
         model.put("sendDateTime", sendDateTime);
 198  
 
 199  
         // retain the original date time or set to current if
 200  
         // it was not in the request
 201  0
         if (request.getParameter("originalDateTime") == null) {
 202  0
            model.put("originalDateTime", currentDateTime);
 203  
         } else {
 204  0
            model.put("originalDateTime", request.getParameter("originalDateTime"));
 205  
         }
 206  0
         model.put("summary", request.getParameter("summary"));
 207  0
         model.put("description", request.getParameter("description"));
 208  0
         model.put("location", request.getParameter("location"));
 209  0
         model.put("startDateTime", request.getParameter("startDateTime"));
 210  0
         model.put("stopDateTime", request.getParameter("stopDateTime"));
 211  
 
 212  0
         model.put("userRecipients", request.getParameter("userRecipients"));
 213  0
         model.put("workgroupRecipients", request.getParameter("workgroupRecipients"));
 214  0
         model.put("workgroupNamespaceCodes", request.getParameter("workgroupNamespaceCodes"));
 215  
 
 216  0
         return model;
 217  
     }
 218  
 
 219  
     /**
 220  
      * This method handles submitting the actual event notification message.
 221  
      * @param request
 222  
      * @param response
 223  
      * @return ModelAndView
 224  
      * @throws ServletException
 225  
      * @throws IOException
 226  
      */
 227  
     public ModelAndView submitEventNotificationMessage(
 228  
             HttpServletRequest request, HttpServletResponse response)
 229  
             throws ServletException, IOException {
 230  0
         LOG.debug("remoteUser: " + request.getRemoteUser());
 231  
 
 232  
         // obtain a workflow user object first
 233  0
         WorkflowIdDTO initiator = new WorkflowIdDTO(request.getRemoteUser());
 234  
 
 235  
         // now construct the workflow document, which will interact with workflow
 236  
         NotificationWorkflowDocument document;
 237  0
         Map<String, Object> model = new HashMap<String, Object>();
 238  
         String view;
 239  
         try {
 240  0
             document = new NotificationWorkflowDocument(
 241  
                     initiator,
 242  
                     NotificationConstants.KEW_CONSTANTS.SEND_NOTIFICATION_REQ_DOC_TYPE);
 243  
 
 244  
             //parse out the application content into a Notification BO
 245  0
             Notification notification = populateNotificationInstance(request, model);
 246  
 
 247  
             // now get that content in an understandable XML format and pass into document
 248  0
             String notificationAsXml = messageContentService
 249  
                     .generateNotificationMessage(notification);
 250  
 
 251  0
             Map<String, String> attrFields = new HashMap<String,String>();
 252  0
             List<NotificationChannelReviewer> reviewers = notification.getChannel().getReviewers();
 253  0
             int ui = 0;
 254  0
             int gi = 0;
 255  0
             for (NotificationChannelReviewer reviewer: reviewers) {
 256  
                 String prefix;
 257  
                 int index;
 258  0
                 if (KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE.equals(reviewer.getReviewerType())) {
 259  0
                     prefix = "user";
 260  0
                     index = ui;
 261  0
                     ui++;
 262  0
                 } else if (KimGroupMemberTypes.GROUP_MEMBER_TYPE.equals(reviewer.getReviewerType())) {
 263  0
                     prefix = "group";
 264  0
                     index = gi;
 265  0
                     gi++;
 266  
                 } else {
 267  0
                     LOG.error("Invalid type for reviewer " + reviewer.getReviewerId() + ": " + reviewer.getReviewerType());
 268  0
                     continue;
 269  
                 }
 270  0
                 attrFields.put(prefix + index, reviewer.getReviewerId());
 271  0
             }
 272  0
             GenericAttributeContent gac = new GenericAttributeContent("channelReviewers");
 273  0
             document.getDocumentContent().setApplicationContent(notificationAsXml);
 274  0
             document.getDocumentContent().setAttributeContent("<attributeContent>" + gac.generateContent(attrFields) + "</attributeContent>");
 275  
 
 276  0
             document.setTitle(notification.getTitle());
 277  
 
 278  0
             document.routeDocument("This message was submitted via the event notification message submission form by user "
 279  
                             + initiator.getWorkflowId());
 280  
 
 281  0
             view = "SendEventNotificationMessage";
 282  
             
 283  
             // This ain't pretty, but it gets the job done for now.
 284  0
             ErrorList el = new ErrorList();
 285  0
             el.addError("Notification(s) sent.");
 286  0
             model.put("errors", el);
 287  
             
 288  0
         } catch (ErrorList el) {
 289  
             // route back to the send form again
 290  0
             Map<String, Object> model2 = setupModelForSendEventNotification(request);
 291  0
             model.putAll(model2);
 292  0
             model.put("errors", el);
 293  
 
 294  0
             view = "SendEventNotificationMessage";
 295  0
         } catch (Exception e) {
 296  0
             throw new RuntimeException(e);
 297  0
         }
 298  
 
 299  0
         return new ModelAndView(view, model);
 300  
     }
 301  
 
 302  
     /**
 303  
      * This method creates a new Notification instance from the event form values.
 304  
      * @param request
 305  
      * @param model
 306  
      * @return Notification
 307  
      * @throws IllegalArgumentException
 308  
      */
 309  
     private Notification populateNotificationInstance(
 310  
             HttpServletRequest request, Map<String, Object> model)
 311  
             throws IllegalArgumentException, ErrorList {
 312  0
         ErrorList errors = new ErrorList();
 313  
 
 314  0
         Notification notification = new Notification();
 315  
 
 316  
         // grab data from form
 317  
         // channel name
 318  0
         String channelName = request.getParameter("channelName");
 319  0
         if (StringUtils.isEmpty(channelName) || StringUtils.equals(channelName, NONE_CHANNEL)) {
 320  0
             errors.addError("You must choose a channel.");
 321  
         } else {
 322  0
             model.put("channelName", channelName);
 323  
         }
 324  
 
 325  
         // priority name
 326  0
         String priorityName = request.getParameter("priorityName");
 327  0
         if (StringUtils.isEmpty(priorityName)) {
 328  0
             errors.addError("You must choose a priority.");
 329  
         } else {
 330  0
             model.put("priorityName", priorityName);
 331  
         }
 332  
 
 333  
         // sender names
 334  0
         String senderNames = request.getParameter("senderNames");
 335  0
         String[] senders = null;
 336  0
         if (StringUtils.isEmpty(senderNames)) {
 337  0
             errors.addError("You must enter at least one sender.");
 338  
         } else {
 339  0
             senders = StringUtils.split(senderNames, ",");
 340  
 
 341  0
             model.put("senderNames", senderNames);
 342  
         }
 343  
 
 344  
         // delivery type
 345  0
         String deliveryType = request.getParameter("deliveryType");
 346  0
         if (StringUtils.isEmpty(deliveryType)) {
 347  0
             errors.addError("You must choose a type.");
 348  
         } else {
 349  0
             if (deliveryType
 350  
                     .equalsIgnoreCase(NotificationConstants.DELIVERY_TYPES.FYI)) {
 351  0
                 deliveryType = NotificationConstants.DELIVERY_TYPES.FYI;
 352  
             } else {
 353  0
                 deliveryType = NotificationConstants.DELIVERY_TYPES.ACK;
 354  
             }
 355  0
             model.put("deliveryType", deliveryType);
 356  
         }
 357  
 
 358  
         //get datetime when form was initially rendered
 359  0
         String originalDateTime = request.getParameter("originalDateTime");
 360  0
         Date origdate = null;
 361  0
         Date senddate = null;
 362  0
         Date removedate = null;
 363  
         try {
 364  0
             origdate = Util.parseUIDateTime(originalDateTime);
 365  0
         } catch (ParseException pe) {
 366  0
             errors.addError("Original date is invalid.");
 367  0
         }
 368  
         // send date time
 369  0
         String sendDateTime = request.getParameter("sendDateTime");
 370  0
         if (StringUtils.isBlank(sendDateTime)) {
 371  0
             sendDateTime = Util.getCurrentDateTime();
 372  
         }
 373  
 
 374  
         try {
 375  0
             senddate = Util.parseUIDateTime(sendDateTime);
 376  0
         } catch (ParseException pe) {
 377  0
             errors.addError("You specified an invalid Send Date/Time.  Please use the calendar picker.");
 378  0
         }
 379  
 
 380  0
         if(senddate != null && senddate.before(origdate)) {
 381  0
             errors.addError("Send Date/Time cannot be in the past.");
 382  
         }
 383  
 
 384  0
         model.put("sendDateTime", sendDateTime);
 385  
 
 386  
         // auto remove date time
 387  0
         String autoRemoveDateTime = request.getParameter("autoRemoveDateTime");
 388  0
         if (StringUtils.isNotBlank(autoRemoveDateTime)) {
 389  
             try {
 390  0
                 removedate = Util.parseUIDateTime(autoRemoveDateTime);
 391  0
             } catch (ParseException pe) {
 392  0
                 errors.addError("You specified an invalid Auto-Remove Date/Time.  Please use the calendar picker.");
 393  0
             }
 394  
 
 395  0
             if(removedate != null) {
 396  0
                 if(removedate.before(origdate)) {
 397  0
                     errors.addError("Auto-Remove Date/Time cannot be in the past.");
 398  0
                 } else if (senddate != null && removedate.before(senddate)){
 399  0
                     errors.addError("Auto-Remove Date/Time cannot be before the Send Date/Time.");
 400  
                 }
 401  
             }
 402  
         }
 403  
 
 404  0
         model.put("autoRemoveDateTime", autoRemoveDateTime);
 405  
 
 406  
         // user recipient names
 407  0
         String[] userRecipients = parseUserRecipients(request);
 408  
 
 409  
         // workgroup recipient names
 410  0
         String[] workgroupRecipients = parseWorkgroupRecipients(request);
 411  
 
 412  
         // workgroup namespace names
 413  0
         String[] workgroupNamespaceCodes = parseWorkgroupNamespaceCodes(request);
 414  
         
 415  
         // title
 416  0
         String title = request.getParameter("title");
 417  0
         if (!StringUtils.isEmpty(title)) {
 418  0
             model.put("title", title);
 419  
         } else {
 420  0
             errors.addError("You must fill in a title");
 421  
         }
 422  
 
 423  
         // message
 424  0
         String message = request.getParameter("message");
 425  0
         if (StringUtils.isEmpty(message)) {
 426  0
             errors.addError("You must fill in a message.");
 427  
         } else {
 428  0
             model.put("message", message);
 429  
         }
 430  
 
 431  
         // all event fields are mandatory for event type
 432  
 
 433  
         // start date time
 434  0
         String startDateTime = request.getParameter("startDateTime");
 435  0
         if (StringUtils.isEmpty(startDateTime)) {
 436  0
             errors.addError("You must fill in a start date/time.");
 437  
         } else {
 438  0
             model.put("startDateTime", startDateTime);
 439  
         }
 440  
 
 441  
         // stop date time
 442  0
         String stopDateTime = request.getParameter("stopDateTime");
 443  0
         if (StringUtils.isEmpty(stopDateTime)) {
 444  0
             errors.addError("You must fill in a stop date/time.");
 445  
         } else {
 446  0
             model.put("stopDateTime", stopDateTime);
 447  
         }
 448  
 
 449  
         // summary
 450  0
         String summary = request.getParameter("summary");
 451  0
         if (StringUtils.isEmpty(summary)) {
 452  0
             errors.addError("You must fill in a summary.");
 453  
         } else {
 454  0
             model.put("summary", summary);
 455  
         }
 456  
 
 457  
         // description
 458  0
         String description = request.getParameter("description");
 459  0
         if (StringUtils.isEmpty(description)) {
 460  0
             errors.addError("You must fill in a description.");
 461  
         } else {
 462  0
             model.put("description", description);
 463  
         }
 464  
 
 465  
         // location
 466  0
         String location = request.getParameter("location");
 467  0
         if (StringUtils.isEmpty(location)) {
 468  0
             errors.addError("You must fill in a location.");
 469  
         } else {
 470  0
             model.put("location", location);
 471  
         }
 472  
 
 473  
         // stop processing if there are errors
 474  0
         if (errors.getErrors().size() > 0) {
 475  0
             throw errors;
 476  
         }
 477  
 
 478  
         // now populate the notification BO instance
 479  0
         NotificationChannel channel = Util.retrieveFieldReference("channel",
 480  
                 "name", channelName, NotificationChannel.class,
 481  
                 businessObjectDao);
 482  0
         notification.setChannel(channel);
 483  
 
 484  0
         NotificationPriority priority = Util.retrieveFieldReference("priority",
 485  
                 "name", priorityName, NotificationPriority.class,
 486  
                 businessObjectDao);
 487  0
         notification.setPriority(priority);
 488  
 
 489  0
         NotificationContentType contentType = Util.retrieveFieldReference(
 490  
                 "contentType", "name",
 491  
                 NotificationConstants.CONTENT_TYPES.EVENT_CONTENT_TYPE,
 492  
                 NotificationContentType.class, businessObjectDao);
 493  0
         notification.setContentType(contentType);
 494  
 
 495  0
         NotificationProducer producer = Util
 496  
                 .retrieveFieldReference(
 497  
                         "producer",
 498  
                         "name",
 499  
                         NotificationConstants.KEW_CONSTANTS.NOTIFICATION_SYSTEM_USER_NAME,
 500  
                         NotificationProducer.class, businessObjectDao);
 501  0
         notification.setProducer(producer);
 502  
 
 503  0
         for (String senderName : senders) {
 504  0
             if (StringUtils.isEmpty(senderName)) {
 505  0
                 errors.addError("A sender's name cannot be blank.");
 506  
             } else {
 507  0
                 NotificationSender ns = new NotificationSender();
 508  0
                 ns.setSenderName(senderName.trim());
 509  0
                 notification.addSender(ns);
 510  
             }
 511  
         }
 512  
 
 513  0
         boolean recipientsExist = false;
 514  
 
 515  0
         if (userRecipients != null && userRecipients.length > 0) {
 516  0
             recipientsExist = true;
 517  0
             for (String userRecipientId : userRecipients) {
 518  0
                 if (isUserRecipientValid(userRecipientId, errors)) {
 519  0
                         NotificationRecipient recipient = new NotificationRecipient();
 520  0
                         recipient.setRecipientType(KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE);
 521  0
                         recipient.setRecipientId(userRecipientId);
 522  0
                         notification.addRecipient(recipient);
 523  
                 }
 524  
             }
 525  
         }
 526  
 
 527  0
         if (workgroupRecipients != null && workgroupRecipients.length > 0) {
 528  0
             recipientsExist = true;
 529  0
             if (workgroupNamespaceCodes != null && workgroupNamespaceCodes.length > 0) {
 530  0
                     if (workgroupNamespaceCodes.length == workgroupRecipients.length) {
 531  0
                             for (int i = 0; i < workgroupRecipients.length; i++) {
 532  0
                                     if (isWorkgroupRecipientValid(workgroupRecipients[i], workgroupNamespaceCodes[i], errors)) {
 533  0
                                             NotificationRecipient recipient = new NotificationRecipient();
 534  0
                                             recipient.setRecipientType(KimGroupMemberTypes.GROUP_MEMBER_TYPE);
 535  0
                                             recipient.setRecipientId(
 536  
                                                             getIdentityManagementService().getGroupByName(workgroupNamespaceCodes[i], workgroupRecipients[i]).getGroupId());
 537  0
                                             notification.addRecipient(recipient);
 538  
                                     }
 539  
                             }
 540  
                     } else {
 541  0
                             errors.addError("The number of groups must match the number of namespace codes");
 542  
                     }
 543  
             } else {
 544  0
                         errors.addError("You must specify a namespace code for every group name");
 545  
                 }
 546  0
         } else if (workgroupNamespaceCodes != null && workgroupNamespaceCodes.length > 0) {
 547  0
                 errors.addError("You must specify a group name for every namespace code");
 548  
         }
 549  
 
 550  
         // check to see if there were any errors
 551  0
         if (errors.getErrors().size() > 0) {
 552  0
             throw errors;
 553  
         }
 554  
 
 555  0
         notification.setTitle(title);
 556  
 
 557  0
         notification.setDeliveryType(deliveryType);
 558  
 
 559  0
         Date startDate = null;
 560  0
         Date stopDate = null;
 561  
         // simpledateformat is not threadsafe, have to sync and validate
 562  0
         Date d = null;
 563  0
         if (StringUtils.isNotBlank(sendDateTime)) {
 564  
             try {
 565  0
                 d = Util.parseUIDateTime(sendDateTime);
 566  0
             } catch (ParseException pe) {
 567  0
                 errors.addError("You specified an invalid send date and time.  Please use the calendar picker.");
 568  0
             }
 569  0
             notification.setSendDateTime(new Timestamp(d.getTime()));
 570  
         }
 571  
 
 572  0
         Date d2 = null;
 573  0
         if (StringUtils.isNotBlank(autoRemoveDateTime)) {
 574  
             try {
 575  0
                 d2 = Util.parseUIDateTime(autoRemoveDateTime);
 576  0
                 if (d2.before(d)) {
 577  0
                     errors.addError("Auto Remove Date/Time cannot be before Send Date/Time.");
 578  
                 }
 579  0
             } catch (ParseException pe) {
 580  0
                 errors.addError("You specified an invalid auto-remove date and time.  Please use the calendar picker.");
 581  0
             }
 582  0
             notification.setAutoRemoveDateTime(new Timestamp(d2.getTime()));
 583  
         }
 584  
 
 585  0
         if (StringUtils.isNotBlank(startDateTime)) {
 586  
             try {
 587  0
                 startDate = Util.parseUIDateTime(startDateTime);
 588  0
             } catch (ParseException pe) {
 589  0
                 errors.addError("You specified an invalid start date and time.  Please use the calendar picker.");
 590  0
             }
 591  
         }
 592  
 
 593  0
         if (StringUtils.isNotBlank(stopDateTime)) {
 594  
             try {
 595  0
                 stopDate = Util.parseUIDateTime(stopDateTime);
 596  0
             } catch (ParseException pe) {
 597  0
                 errors.addError("You specified an invalid stop date and time.  Please use the calendar picker.");
 598  0
             }
 599  
         }
 600  
 
 601  0
         if(stopDate != null && startDate != null) {
 602  0
             if (stopDate.before(startDate)) {
 603  0
                 errors.addError("Event Stop Date/Time cannot be before Event Start Date/Time.");
 604  
             }
 605  
         }
 606  
 
 607  0
         if (!recipientsExist && !hasPotentialRecipients(notification)) {
 608  0
             errors.addError("You must specify at least one user or group recipient.");
 609  
         }
 610  
 
 611  
         // check to see if there were any errors
 612  0
         if (errors.getErrors().size() > 0) {
 613  0
             throw errors;
 614  
         }
 615  
 
 616  0
         notification
 617  
                 .setContent(NotificationConstants.XML_MESSAGE_CONSTANTS.CONTENT_EVENT_OPEN
 618  
                         + NotificationConstants.XML_MESSAGE_CONSTANTS.MESSAGE_OPEN
 619  
                         + message
 620  
                         + NotificationConstants.XML_MESSAGE_CONSTANTS.MESSAGE_CLOSE
 621  
                         + "<event>\n"
 622  
                         + "  <summary>" + summary + "</summary>\n"
 623  
                         + "  <description>" + description + "</description>\n"
 624  
                         + "  <location>" + location + "</location>\n"
 625  
                         + "  <startDateTime>" + Util.toUIDateTimeString(startDate) + "</startDateTime>\n"
 626  
                         + "  <stopDateTime>" + Util.toUIDateTimeString(stopDate) + "</stopDateTime>\n"
 627  
                         + "</event>"
 628  
                         + NotificationConstants.XML_MESSAGE_CONSTANTS.CONTENT_CLOSE);
 629  
 
 630  0
         return notification;
 631  
     }
 632  
 }