/* * Copyright (C) 2010-2012 Stichting Akvo (Akvo Foundation) * * This file is part of Akvo FLOW. * * Akvo FLOW is free software: you can redistribute it and modify it under the terms of * the GNU Affero General Public License (AGPL) as published by the Free Software Foundation, * either version 3 of the License or any later version. * * Akvo FLOW 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 included below for more details. * * The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>. */ package com.gallatinsystems.notification.helper; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.gallatinsystems.notification.NotificationRequest; import com.gallatinsystems.notification.dao.NotificationSubscriptionDao; import com.gallatinsystems.notification.domain.NotificationSubscription; import com.google.appengine.api.taskqueue.Queue; import com.google.appengine.api.taskqueue.QueueFactory; import com.google.appengine.api.taskqueue.TaskOptions; /** * Finds current notification subscriptions from the data store and spawns async jobs to generate * data and send the notification. To use this class you must define a queue called notification * * @author Christopher Fagiani */ public class NotificationHelper { private static final String UNSPECIFIED = "unspecified"; private static final String QUEUE_NAME = "notification"; private static final String PROCESSOR_URL = "/notificationprocessor"; private String notificationType; private Long subscriptionEntityId; private Long notificationEntityId; private NotificationSubscriptionDao notificationDao; public NotificationHelper(String type, Long subEntityId) { this(type, subEntityId, subEntityId); } public NotificationHelper(String type, Long subEntityId, Long notifEntityId) { notificationDao = new NotificationSubscriptionDao(); notificationType = type; this.subscriptionEntityId = subEntityId; notificationEntityId = subEntityId; if (notificationEntityId == null) { notificationEntityId = subscriptionEntityId; } } /** * this method will find all unexpired notification subscriptions, collate them and then * generate messages that will be placed on the notification processor queue (so the actual * notification can be handled by the appropriate notification handler class). */ public void execute() { // find all notifications that have not yet expired List<NotificationSubscription> subs = notificationDao .listSubscriptions(subscriptionEntityId, notificationType, true); // group the subs by entity id and type Map<String, Map<Long, List<NotificationSubscription>>> subMap = collateSubscriptions(subs); if (subMap != null) { // now spawn a notification job for each notificationType/entity // combo Queue queue = QueueFactory.getQueue(QUEUE_NAME); for (Entry<String, Map<Long, List<NotificationSubscription>>> entry : subMap .entrySet()) { for (Entry<Long, List<NotificationSubscription>> notifEntry : entry .getValue().entrySet()) { StringBuilder builder = new StringBuilder(); StringBuilder optBuilder = new StringBuilder(); if (notifEntry.getValue() != null && notifEntry.getValue().size() > 0) { for (int i = 0; i < notifEntry.getValue().size(); i++) { if (i > 0) { builder.append(NotificationRequest.DELIMITER); optBuilder .append(NotificationRequest.DELIMITER); } builder.append(notifEntry.getValue().get(i) .getNotificationDestination()); String opt = notifEntry.getValue().get(i) .getNotificationOption(); optBuilder.append(opt != null ? opt : UNSPECIFIED); } // now dump the item on the queue TaskOptions opts = TaskOptions.Builder .withUrl(PROCESSOR_URL) .param(NotificationRequest.DEST_PARAM, builder.toString()) .param(NotificationRequest.DEST_OPT_PARAM, optBuilder.toString()) .param(NotificationRequest.SUB_ENTITY_PARAM, notifEntry.getKey().toString()) .param(NotificationRequest.TYPE_PARAM, entry.getKey()); if (notificationEntityId != null) { opts.param(NotificationRequest.NOTIF_ENTITY_PARAM, notificationEntityId.toString()); } queue.add(opts); } } } } } /** * this method will collate subscriptions based on notification type and delivery type. this * allows us to reduce processing by generating a list of all addresses to be notified via a * specific delivery mechanism * * @param subs * @return */ private Map<String, Map<Long, List<NotificationSubscription>>> collateSubscriptions( List<NotificationSubscription> subs) { Map<String, Map<Long, List<NotificationSubscription>>> subMap = new HashMap<String, Map<Long, List<NotificationSubscription>>>(); if (subs != null) { for (NotificationSubscription sub : subs) { Map<Long, List<NotificationSubscription>> tempMap = subMap .get(sub.getNotificationType()); if (tempMap == null) { tempMap = new HashMap<Long, List<NotificationSubscription>>(); subMap.put(sub.getNotificationType(), tempMap); } List<NotificationSubscription> tempList = tempMap.get(sub .getEntityId()); if (tempList == null) { tempList = new ArrayList<NotificationSubscription>(); tempMap.put(sub.getEntityId(), tempList); } tempList.add(sub); } } return subMap; } }