Coverage Report - org.kuali.rice.ken.service.impl.NotificationMessageDeliveryResolverServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
NotificationMessageDeliveryResolverServiceImpl
0%
0/67
0%
0/20
3
 
 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.service.impl;
 17  
 
 18  
 import java.sql.Timestamp;
 19  
 import java.util.ArrayList;
 20  
 import java.util.Collection;
 21  
 import java.util.HashSet;
 22  
 import java.util.Iterator;
 23  
 import java.util.List;
 24  
 import java.util.concurrent.ExecutorService;
 25  
 
 26  
 import org.kuali.rice.core.dao.GenericDao;
 27  
 import org.kuali.rice.ken.bo.Notification;
 28  
 import org.kuali.rice.ken.bo.NotificationMessageDelivery;
 29  
 import org.kuali.rice.ken.bo.NotificationRecipient;
 30  
 import org.kuali.rice.ken.bo.NotificationRecipientList;
 31  
 import org.kuali.rice.ken.bo.UserChannelSubscription;
 32  
 import org.kuali.rice.ken.deliverer.impl.KEWActionListMessageDeliverer;
 33  
 import org.kuali.rice.ken.exception.NotificationMessageDeliveryException;
 34  
 import org.kuali.rice.ken.service.NotificationMessageDeliveryResolverService;
 35  
 import org.kuali.rice.ken.service.NotificationRecipientService;
 36  
 import org.kuali.rice.ken.service.NotificationService;
 37  
 import org.kuali.rice.ken.service.ProcessingResult;
 38  
 import org.kuali.rice.ken.service.UserPreferenceService;
 39  
 import org.kuali.rice.ken.util.NotificationConstants;
 40  
 import org.kuali.rice.kim.util.KimConstants.KimGroupMemberTypes;
 41  
 import org.springframework.transaction.PlatformTransactionManager;
 42  
 
 43  
 
 44  
 /**
 45  
  * This is the default out-of-the-box implementation that leverages the status flag on a notification (RESOLVED versus UNRESOLVED) to determine whether
 46  
  * the notification's message deliveries need to be resolved or not.  This also looks at the start and auto remove
 47  
  * dates and times.
 48  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 49  
  */
 50  0
 public class NotificationMessageDeliveryResolverServiceImpl extends ConcurrentJob<Notification> implements NotificationMessageDeliveryResolverService {
 51  0
     private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
 52  
         .getLogger(NotificationMessageDeliveryResolverServiceImpl.class);
 53  
 
 54  
     private NotificationRecipientService notificationRecipientService;
 55  
     private GenericDao businessObjectDao;
 56  
     private UserPreferenceService userPreferenceService;
 57  
     private NotificationService notificationService;
 58  
 
 59  
     /**
 60  
      * Constructs a NotificationMessageDeliveryDispatchServiceImpl instance.
 61  
      * @param notificationRecipientService
 62  
      * @param businessObjectDao
 63  
      * @param txManager
 64  
      * @param executor
 65  
      * @param userPreferenceService
 66  
      */
 67  
     public NotificationMessageDeliveryResolverServiceImpl(NotificationService notificationService, NotificationRecipientService notificationRecipientService,
 68  
             GenericDao businessObjectDao, PlatformTransactionManager txManager, ExecutorService executor,
 69  
             UserPreferenceService userPreferenceService) {
 70  0
         super(txManager, executor);
 71  0
         this.notificationService = notificationService;
 72  0
         this.notificationRecipientService = notificationRecipientService;
 73  0
         this.businessObjectDao = businessObjectDao;
 74  0
         this.userPreferenceService = userPreferenceService;
 75  0
     }
 76  
 
 77  
     /**
 78  
      * Obtains and marks as taken all unresolved (and untaken) notifications
 79  
      * @return a collection of available Notifications to process
 80  
      */
 81  
     @Override
 82  
     protected Collection<Notification> takeAvailableWorkItems() {
 83  0
         Collection<Notification> nots = notificationService.takeNotificationsForResolution();
 84  0
         LOG.debug("Took " + nots.size() + " notifications");
 85  0
         for (Notification not: nots) {
 86  0
             LOG.debug("Took notification: " + not.getId() + " " + not.getTitle());
 87  
         }
 88  0
         return nots;
 89  
     }
 90  
 
 91  
 
 92  
     /**
 93  
      * This method is responsible for building out the complete recipient list, which will resolve all members for groups, and add
 94  
      * them to the official list only if they are not already in the list.
 95  
      * @param notification
 96  
      * @return HashSet<String>
 97  
      */
 98  
     private HashSet<String> buildCompleteRecipientList(Notification notification) {
 99  0
         HashSet<String> completeRecipientList = new HashSet<String>(notification.getRecipients().size());
 100  
 
 101  
         // process the list that came in with the notification request
 102  0
            for (int i = 0; i < notification.getRecipients().size(); i++) {
 103  0
                NotificationRecipient recipient = notification.getRecipient(i);
 104  0
                if (KimGroupMemberTypes.GROUP_MEMBER_TYPE.equals(recipient.getRecipientType())) {
 105  
                    // resolve group's users
 106  0
                    String[] groupMembers = notificationRecipientService.getGroupMembers(recipient.getRecipientId());
 107  0
                    for(int j = 0; j < groupMembers.length; j++) {
 108  0
                        completeRecipientList.add(groupMembers[j]);
 109  
                    }
 110  0
                } else {  // just a user, so add to the list
 111  0
                    completeRecipientList.add(recipient.getRecipientId());
 112  
                }
 113  
            }
 114  
 
 115  
            // now process the default recipient lists that are associated with the channel
 116  0
            Iterator<NotificationRecipientList> i = notification.getChannel().getRecipientLists().iterator();
 117  0
            while (i.hasNext()) {
 118  0
                NotificationRecipientList listRecipient  = i.next();
 119  0
                if (KimGroupMemberTypes.GROUP_MEMBER_TYPE.equals(listRecipient.getRecipientType())) {
 120  
                    // resolve group's users
 121  0
                    String[] groupMembers = notificationRecipientService.getGroupMembers(listRecipient.getRecipientId());
 122  0
                    for (int j = 0; j < groupMembers.length; j++) {
 123  0
                        completeRecipientList.add(groupMembers[j]);
 124  
                    }
 125  0
                } else {  // just a user, so add to the list
 126  0
                    completeRecipientList.add(listRecipient.getRecipientId());
 127  
                }
 128  0
            }
 129  
 
 130  
            // now process the subscribers that are associated with the channel
 131  0
            List<UserChannelSubscription> subscriptions = notification.getChannel().getSubscriptions();
 132  0
            for (UserChannelSubscription subscription: subscriptions) {
 133  
                // NOTE: at this time channel subscriptions are USER-only - GROUP is not supported
 134  
                // this could be implemented by adding a recipientType/userType column as we do in
 135  
                // other recipient/user-related tables/BOs
 136  0
                completeRecipientList.add(subscription.getUserId());
 137  
            }
 138  
 
 139  0
            return completeRecipientList;
 140  
     }
 141  
 
 142  
     /**
 143  
      * Generates all message deliveries for a given notification and save thems to the database.
 144  
      * Updates each Notification record to indicate it has been resolved.
 145  
      * Should be performed within a separate transaction
 146  
      * @param notification the Notification for which to generate message deliveries
 147  
      * @return a count of the number of message deliveries generated
 148  
      */
 149  
     /* Perform within transaction */
 150  
     @Override
 151  
     protected Collection<Object> processWorkItems(Collection<Notification> notifications) {
 152  0
         List<Object> successes = new ArrayList<Object>();
 153  
 
 154  
         // because this concurrent job does not performed grouping of work items, there should only
 155  
         // ever be one notification object per work unit anyway...
 156  0
         for (Notification notification: notifications) {
 157  
             // now figure out each unique recipient for this notification
 158  0
             HashSet<String> uniqueRecipients = buildCompleteRecipientList(notification);
 159  
 
 160  
             // now for each unique recipient, figure out each delivery end point and create a NotificationMessageDelivery record
 161  0
             Iterator<String> j = uniqueRecipients.iterator();
 162  0
             while(j.hasNext()) {
 163  0
                 String userRecipientId = j.next();
 164  
 
 165  0
                 NotificationMessageDelivery defaultMessageDelivery = new NotificationMessageDelivery();
 166  0
                 defaultMessageDelivery.setMessageDeliveryStatus(NotificationConstants.MESSAGE_DELIVERY_STATUS.UNDELIVERED);
 167  0
                 defaultMessageDelivery.setNotification(notification);
 168  0
                 defaultMessageDelivery.setUserRecipientId(userRecipientId);
 169  
 
 170  
                 //now save that delivery end point; this record will be later processed by the dispatch service which will actually deliver it
 171  0
                 businessObjectDao.save(defaultMessageDelivery);
 172  
 
 173  
                 try {
 174  0
                     new KEWActionListMessageDeliverer().deliverMessage(defaultMessageDelivery);
 175  0
                 } catch (NotificationMessageDeliveryException e) {
 176  0
                     throw new RuntimeException(e);
 177  0
                 }
 178  
 
 179  
                 // we have no delivery stage any more, anything we send to KCB needs to be considered "delivered" from
 180  
                 // the perspective of KEN
 181  0
                 defaultMessageDelivery.setMessageDeliveryStatus(NotificationConstants.MESSAGE_DELIVERY_STATUS.DELIVERED);
 182  0
                 businessObjectDao.save(defaultMessageDelivery);
 183  
 
 184  0
                 successes.add(defaultMessageDelivery);
 185  
 
 186  
                 // also, update the status of the notification so that it's message deliveries are not resolved again
 187  0
                 notification.setProcessingFlag(NotificationConstants.PROCESSING_FLAGS.RESOLVED);
 188  
                 // unlock the record now
 189  0
                 notification.setLockedDate(null);
 190  0
                 businessObjectDao.save(notification);
 191  0
             }
 192  
 
 193  0
         }
 194  
 
 195  0
         return successes;
 196  
     }
 197  
 
 198  
     /**
 199  
      * @see org.kuali.rice.ken.service.impl.ConcurrentJob#unlockWorkItem(java.lang.Object)
 200  
      */
 201  
     @Override
 202  
     protected void unlockWorkItem(Notification notification) {
 203  0
         LOG.debug("Unlocking notification: " + notification.getId() + " " + notification.getTitle());
 204  0
         notificationService.unlockNotification(notification);
 205  0
     }
 206  
 
 207  
     /**
 208  
      * This method is responsible for resolving the list of NotificationMessageDelivery records for a given notification.  This service will look
 209  
      * at all notifications that are ready to be delivered and will "explode" out specific message delivery records for given delivery end points.
 210  
      * @see org.kuali.rice.ken.service.NotificationMessageDeliveryResolverService#resolveNotificationMessageDeliveries()
 211  
      */
 212  
     public ProcessingResult resolveNotificationMessageDeliveries() {
 213  0
         LOG.debug("[" + new Timestamp(System.currentTimeMillis()).toString() + "] STARTING RESOLUTION OF NOTIFICATION MESSAGE DELIVERIES");
 214  
 
 215  0
         ProcessingResult result = run();
 216  
 
 217  0
         LOG.debug("[" + new Timestamp(System.currentTimeMillis()).toString() + "] FINISHED RESOLUTION OF NOTIFICATION MESSAGE DELIVERIES - " +
 218  
                   "Message Delivery End Points Resolved = " + result.getSuccesses().size());
 219  
 
 220  0
         return result;
 221  
     }
 222  
 }