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 }