001 /** 002 * Copyright 2005-2013 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.rice.ken.service.impl; 017 018 import org.kuali.rice.core.api.util.RiceConstants; 019 import org.kuali.rice.core.framework.persistence.dao.GenericDao; 020 import org.kuali.rice.ken.bo.NotificationBo; 021 import org.kuali.rice.ken.bo.NotificationMessageDelivery; 022 import org.kuali.rice.ken.dao.NotificationMessegeDeliveryDao; 023 import org.kuali.rice.ken.service.NotificationMessageDeliveryService; 024 import org.kuali.rice.ken.util.NotificationConstants; 025 026 import java.sql.Timestamp; 027 import java.util.Collection; 028 import java.util.HashMap; 029 import java.util.Map; 030 031 //import org.kuali.rice.core.jpa.criteria.Criteria; 032 033 /** 034 * NotificationService implementation - this is the default out-of-the-box implementation of the service that uses the 035 * businessObjectDao to get at the data via our OOTB DBMS. 036 * @author Kuali Rice Team (rice.collab@kuali.org) 037 */ 038 public class NotificationMessageDeliveryServiceImpl implements NotificationMessageDeliveryService { 039 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger 040 .getLogger(NotificationMessageDeliveryServiceImpl.class); 041 042 private GenericDao businessObjectDao; 043 private NotificationMessegeDeliveryDao ntdDao; 044 045 /** 046 * Constructs a NotificationServiceImpl class instance. 047 * @param businessObjectDao 048 */ 049 public NotificationMessageDeliveryServiceImpl(GenericDao businessObjectDao, NotificationMessegeDeliveryDao ntdDao) { 050 this.businessObjectDao = businessObjectDao; 051 this.ntdDao = ntdDao; 052 } 053 054 /** 055 * This is the default implementation that uses the businessObjectDao. 056 * @param id 057 * @return NotificationMessageDelivery 058 */ 059 public NotificationMessageDelivery getNotificationMessageDelivery(Long id) { 060 HashMap<String, Long> primaryKeys = new HashMap<String, Long>(); 061 primaryKeys.put(NotificationConstants.BO_PROPERTY_NAMES.ID, id); 062 063 return (NotificationMessageDelivery) businessObjectDao.findByPrimaryKey(NotificationMessageDelivery.class, primaryKeys); 064 } 065 066 /** 067 * @see org.kuali.rice.ken.service.NotificationMessageDeliveryService#getNotificationMessageDeliveryByDelivererId(java.lang.String) 068 */ 069 //switch to JPA criteria 070 public NotificationMessageDelivery getNotificationMessageDeliveryByDelivererId(String id) { 071 Map<String, Object> c = new HashMap<String, Object>(); 072 c.put(NotificationConstants.BO_PROPERTY_NAMES.DELIVERY_SYSTEM_ID, id); 073 Collection<NotificationMessageDelivery> results = businessObjectDao.findMatching(NotificationMessageDelivery.class, c); 074 075 if (results == null || results.size() == 0) return null; 076 if (results.size() > 1) { 077 throw new RuntimeException("More than one message delivery found with the following delivery system id: " + id); 078 } 079 return results.iterator().next(); 080 } 081 082 /** 083 * @see org.kuali.rice.ken.service.NotificationMessageDeliveryService#getNotificationMessageDeliveries() 084 */ 085 public Collection<NotificationMessageDelivery> getNotificationMessageDeliveries() { 086 return businessObjectDao.findAll(NotificationMessageDelivery.class); 087 } 088 089 /** 090 * @see org.kuali.rice.ken.service.NotificationMessageDeliveryService#getNotificationMessageDeliveries(java.lang.Long, java.lang.String) 091 */ 092 //switch to JPA criteria 093 public Collection<NotificationMessageDelivery> getNotificationMessageDeliveries(NotificationBo notification, String userRecipientId) { 094 095 Map<String, Object> c = new HashMap<String, Object>(); 096 c.put(NotificationConstants.BO_PROPERTY_NAMES.NOTIFICATION, notification.getId()); 097 c.put(NotificationConstants.BO_PROPERTY_NAMES.USER_RECIPIENT_ID, userRecipientId); 098 099 return businessObjectDao.findMatching(NotificationMessageDelivery.class, c); 100 } 101 102 /** 103 * This method is responsible for atomically finding all untaken, undelivered messagedeliveries, marking them as taken 104 * and returning them to the caller for processing. 105 * NOTE: it is important that this method execute in a SEPARATE dedicated transaction; either the caller should 106 * NOT be wrapped by Spring declarative transaction and this service should be wrapped (which is the case), or 107 * the caller should arrange to invoke this from within a newly created transaction). 108 109 * @return a list of available message deliveries that have been marked as taken by the caller 110 */ 111 //switch to JPA criteria 112 public Collection<NotificationMessageDelivery> takeMessageDeliveriesForDispatch() { 113 // DO WITHIN TRANSACTION: get all untaken messagedeliveries, and mark as "taken" so no other thread/job takes them 114 // need to think about durability of work list 115 116 // get all undelivered message deliveries 117 Collection<NotificationMessageDelivery> messageDeliveries = ntdDao.getUndeliveredMessageDelivers(businessObjectDao); 118 119 120 LOG.debug("Retrieved " + messageDeliveries.size() + " available message deliveries: " + System.currentTimeMillis()); 121 122 // mark messageDeliveries as taken 123 for (NotificationMessageDelivery delivery: messageDeliveries) { 124 delivery.setLockedDateValue(new Timestamp(System.currentTimeMillis())); 125 businessObjectDao.save(delivery); 126 } 127 return messageDeliveries; 128 } 129 130 /** 131 * This method is responsible for atomically finding all untaken message deliveries that are ready to be autoremoved, 132 * marking them as taken and returning them to the caller for processing. 133 * NOTE: it is important that this method execute in a SEPARATE dedicated transaction; either the caller should 134 * NOT be wrapped by Spring declarative transaction and this service should be wrapped (which is the case), or 135 * the caller should arrange to invoke this from within a newly created transaction). 136 * @return a list of notifications to be autoremoved that have been marked as taken by the caller 137 */ 138 public Collection<NotificationMessageDelivery> takeMessageDeliveriesForAutoRemoval() { 139 // get all UNDELIVERED/DELIVERED notification notification message delivery records with associated notifications that have and autoRemovalDateTime <= current 140 Collection<NotificationMessageDelivery> messageDeliveries = ntdDao.getMessageDeliveriesForAutoRemoval(new Timestamp(System.currentTimeMillis()), businessObjectDao); 141 142 for (NotificationMessageDelivery d: messageDeliveries) { 143 d.setLockedDateValue(new Timestamp(System.currentTimeMillis())); 144 businessObjectDao.save(d); 145 } 146 147 return messageDeliveries; 148 149 } 150 151 /** 152 * Unlocks the specified messageDelivery object 153 * @param messageDelivery the message delivery to unlock 154 */ 155 public void unlockMessageDelivery(NotificationMessageDelivery messageDelivery) { 156 Map<String, Long> c = new HashMap<String, Long>(); 157 c.put(NotificationConstants.BO_PROPERTY_NAMES.DELIVERY_SYSTEM_ID, messageDelivery.getId()); 158 159 Collection<NotificationMessageDelivery> deliveries = businessObjectDao.findMatching(NotificationMessageDelivery.class, c, true, RiceConstants.NO_WAIT); 160 if (deliveries == null || deliveries.size() == 0) { 161 throw new RuntimeException("NotificationMessageDelivery #" + messageDelivery.getId() + " not found to unlock"); 162 } 163 164 NotificationMessageDelivery d = deliveries.iterator().next(); 165 d.setLockedDateValue(null); 166 167 businessObjectDao.save(d); 168 } 169 }