/* * * Copyright (C) 2007-2015 Licensed to the Comunes Association (CA) under * one or more contributor license agreements (see COPYRIGHT for details). * The CA licenses this file to you under the GNU Affero General Public * License version 3, (the "License"); you may not use this file except in * compliance with the License. This file is part of kune. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package cc.kune.core.server.notifier; import java.util.Collection; import java.util.concurrent.ConcurrentLinkedQueue; import cc.kune.core.server.utils.FormattedString; import cc.kune.core.shared.dto.EmailNotificationFrequency; import com.google.inject.Inject; import com.google.inject.Singleton; // TODO: Auto-generated Javadoc /** * The Class PendingNotificationSender is used to store and send pending * notifications via cron tasks. * * @author vjrj@ourproject.org (Vicente J. Ruiz Jurado) */ @Singleton public class PendingNotificationSender { /** The Constant NO_NEXT. */ private static final Collection<PendingNotificationProvider> NO_NEXT = null; // FIXME this should be in DB so we'll don't lose them in server restarts /** The daily pend notif. list */ private final ConcurrentLinkedQueue<PendingNotificationProvider> dailyPendNotif; // FIXME this should be in DB so we'll don't lose them in server restarts /** The houry pend notif. list */ private final ConcurrentLinkedQueue<PendingNotificationProvider> hourlyPendNotif; /** The immediate pend notif. list */ private final ConcurrentLinkedQueue<PendingNotificationProvider> immediatePendNotif; /** The sender. */ private final NotificationSender sender; /** * Instantiates a new pending notifications manager. * * @param sender * the sender */ @Inject public PendingNotificationSender(final NotificationSender sender) { this.sender = sender; immediatePendNotif = new ConcurrentLinkedQueue<PendingNotificationProvider>(); hourlyPendNotif = new ConcurrentLinkedQueue<PendingNotificationProvider>(); dailyPendNotif = new ConcurrentLinkedQueue<PendingNotificationProvider>(); // immediatePendNotif = Collections.synchronizedSet(new // LinkedHashSet<PendingNotificationProvider>()); // hourlyPendNotif = Collections.synchronizedSet(new // LinkedHashSet<PendingNotificationProvider>()); // dailyPendNotif = Collections.synchronizedSet(new // LinkedHashSet<PendingNotificationProvider>()); } /** * Adds the. * * @param type * the type * @param subjectPrefix * the subject prefix * @param subject * the subject * @param body * the body * @param isHtml * the is html * @param forceSend * the force send * @param to * the to */ public void add(final NotificationType type, final String subjectPrefix, final FormattedString subject, final FormattedString body, final boolean isHtml, final boolean forceSend, final Addressee to) { add(new PendingNotificationProvider() { @Override public PendingNotification get() { return new PendingNotification(type, subjectPrefix, subject, body, isHtml, forceSend, new SimpleDestinationProvider(to)); } }); } /** * Adds the. * * @param type * the type * @param subjectPrefix * the subject prefix * @param subject * the subject * @param body * the body * @param isHtml * the is html * @param forceSend * the force send * @param dest * the dest */ public void add(final NotificationType type, final String subjectPrefix, final FormattedString subject, final FormattedString body, final boolean isHtml, final boolean forceSend, final DestinationProvider dest) { add(new PendingNotificationProvider() { @Override public PendingNotification get() { return new PendingNotification(type, subjectPrefix, subject, body, isHtml, forceSend, dest); } }); } /** * Adds a pending notification. * * @param notificationProv * the notification prov */ public void add(final PendingNotificationProvider notificationProv) { if (!immediatePendNotif.contains(notificationProv) && !hourlyPendNotif.contains(notificationProv)) { // If we have send a similar notification this hour just ignore immediatePendNotif.add(notificationProv); } } /** * Gets the daily pending notifications count. * * @return the daily count */ public int getDailyCount() { return dailyPendNotif.size(); } /** * Gets the hourly pending notifications count. * * @return the hourly count */ public int getHourlyCount() { return hourlyPendNotif.size(); } /** * Gets the immediate pending notifications count. * * @return the immediate count */ public int getImmediateCount() { return immediatePendNotif.size(); } /** * Send some list of notifications (called vía cron). * * @param list * the list to process * @param nextList * the next list to store (we have a list of Users some that wants an * immediate notification and other that want periodical * notifications instead. * @param currentFreq * The current frequency of notifications, that is, we'll send * notifications only to users with this frequency configured */ private void send(final Collection<PendingNotificationProvider> list, final Collection<PendingNotificationProvider> nextList, final EmailNotificationFrequency currentFreq) { // http://en.wikipedia.org/wiki/Thread_pool_pattern while (!list.isEmpty()) { final PendingNotificationProvider notificationProv = ((ConcurrentLinkedQueue<PendingNotificationProvider>) list).poll(); final PendingNotification notification = notificationProv.get(); if (!notification.equals(PendingNotification.NONE)) { sender.send(notification, currentFreq); if (!notification.isForceSend() && nextList != NO_NEXT) { // Forced Send, are send immediately (independent of how User has its // notification configured)! if (!nextList.contains(notificationProv)) { // We only add to the next queue if does not exists nextList.add(notificationProv); } } } } } /** * Send daily notifications. */ public void sendDailyNotifications() { send(dailyPendNotif, NO_NEXT, EmailNotificationFrequency.daily); } /** * Send hourly notifications. */ public void sendHourlyNotifications() { send(hourlyPendNotif, dailyPendNotif, EmailNotificationFrequency.hourly); } /** * Send immediate notifications. */ public void sendImmediateNotifications() { send(immediatePendNotif, hourlyPendNotif, EmailNotificationFrequency.immediately); } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return "pendingNotifications: [" + getImmediateCount() + ", " + getHourlyCount() + ", " + getDailyCount() + "]"; } }