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    }