net.frontlinesms.plugins.reminders.RemindersThinletTabController.java Source code

Java tutorial

Introduction

Here is the source code for net.frontlinesms.plugins.reminders.RemindersThinletTabController.java

Source

/*
 * FrontlineSMS <http://www.frontlinesms.com>
 * Copyright 2007, 2008 kiwanja
 * 
 * This file is part of FrontlineSMS.
 * 
 * FrontlineSMS is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * 
 * FrontlineSMS 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 Lesser
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with FrontlineSMS. If not, see <http://www.gnu.org/licenses/>.
 */
package net.frontlinesms.plugins.reminders;

import java.util.Date;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.text.DateFormat;

import net.frontlinesms.EmailServerHandler;
import net.frontlinesms.FrontlineSMS;
import net.frontlinesms.FrontlineUtils;
import net.frontlinesms.data.repository.ContactDao;
import net.frontlinesms.data.repository.EmailDao;
import net.frontlinesms.plugins.BasePluginThinletTabController;
import net.frontlinesms.ui.Icon;
import net.frontlinesms.ui.ThinletUiEventHandler;
import net.frontlinesms.ui.UiGeneratorController;
import net.frontlinesms.ui.handler.ComponentPagingHandler;
import net.frontlinesms.ui.handler.PagedComponentItemProvider;
import net.frontlinesms.ui.handler.PagedListDetails;
import net.frontlinesms.ui.i18n.InternationalisationUtils;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;

import thinlet.Thinlet;
import thinlet.ThinletText;

import net.frontlinesms.plugins.reminders.data.domain.ExpiredReminder;
import net.frontlinesms.plugins.reminders.data.domain.Reminder;
import net.frontlinesms.plugins.reminders.data.domain.Reminder.Status;
import net.frontlinesms.plugins.reminders.data.repository.ReminderDao;

import net.frontlinesms.data.domain.Contact;
import net.frontlinesms.data.domain.Email;
import net.frontlinesms.data.domain.EmailAccount;
import net.frontlinesms.data.events.EntityDeleteWarning;
import net.frontlinesms.events.EventObserver;
import net.frontlinesms.events.FrontlineEventNotification;

/*
 * RemindersThinletTabController
 * @author Dale Zak
 * 
 * see {@link "http://www.frontlinesms.net"} for more details. 
 * copyright owned by Kiwanja.net
 */
public class RemindersThinletTabController extends BasePluginThinletTabController<RemindersPluginController>
        implements ThinletUiEventHandler, EventObserver, PagedComponentItemProvider, RemindersCallback {

    private static Logger LOG = FrontlineUtils.getLogger(RemindersThinletTabController.class);

    private static final String TAB_XML = "/ui/plugins/reminders/remindersTab.xml";

    /**
     * FrontlineSMS
     */
    private FrontlineSMS frontlineController;

    /**
     * ApplicationContext
     */
    private ApplicationContext applicationContext;

    /**
     * ReminderDao
     */
    private final ReminderDao reminderDao;

    /**
     * ContactDao
     */
    private final ContactDao contactDao;

    /**
     * EmailDao
     */
    private final EmailDao emailDao;

    /**
     * EmailServerHandler
     */
    private final EmailServerHandler emailManager;

    /**
     * Reminders pager
     */
    private ComponentPagingHandler pagerReminders;

    private Object tabComponent;
    private Object tableReminders;
    private Object panelTableReminders;
    private Object menuReminders;
    private Object toolbarReminders;

    private static final String TAB_MENU_CREATE = "menuCreateReminder";
    private static final String TAB_MENU_SEND = "menuSendReminder";
    private static final String TAB_MENU_EDIT = "menuEditReminder";
    private static final String TAB_MENU_DELETE = "menuDeleteReminder";

    private static final String TAB_TOOLBAR_CREATE = "buttonCreateReminder";
    private static final String TAB_TOOLBAR_SEND = "buttonSendReminder";
    private static final String TAB_TOOLBAR_EDIT = "buttonEditReminder";
    private static final String TAB_TOOLBAR_DELETE = "buttonDeleteReminder";

    /**
     * RemindersThinletTabController
     * @param pluginController RemindersPluginController
     * @param uiController UiGeneratorController
     * @param applicationContext ApplicationContext
     */
    public RemindersThinletTabController(RemindersPluginController pluginController,
            UiGeneratorController uiController, ApplicationContext applicationContext) {
        super(pluginController, uiController);
        this.applicationContext = applicationContext;

        this.tabComponent = uiController.loadComponentFromFile(TAB_XML, this);
        super.setTabComponent(this.tabComponent);

        this.reminderDao = (ReminderDao) applicationContext.getBean("reminderDao");
        this.contactDao = this.ui.getFrontlineController().getContactDao();
        this.emailDao = this.ui.getFrontlineController().getEmailDao();
        this.emailManager = this.ui.getFrontlineController().getEmailServerHandler();

        this.menuReminders = this.ui.find(this.tabComponent, "menuReminders");
        this.toolbarReminders = this.ui.find(this.tabComponent, "toolbarReminders");

        this.tableReminders = this.ui.find(this.tabComponent, "tableReminders");
        this.pagerReminders = new ComponentPagingHandler(this.ui, this, tableReminders);

        this.panelTableReminders = this.ui.find(this.tabComponent, "panelTableReminders");
        this.ui.add(this.panelTableReminders, this.pagerReminders.getPanel());

        this.pagerReminders.setCurrentPage(0);
        this.pagerReminders.refresh();
    }

    /**
     * The ScheduledExecutorService provider used for scheduling tasks
     */
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    /**
     * Hashmap to store Reminders to allow cancelling of scheduled tasks
     */
    private final HashMap<Reminder, ScheduledFuture<?>> futures = new HashMap<Reminder, ScheduledFuture<?>>();

    /**
     * Hashmap to store expired Reminders to allow cancelling of expiry tasks
     */
    private final HashMap<Reminder, ScheduledFuture<?>> expired = new HashMap<Reminder, ScheduledFuture<?>>();

    public void notify(FrontlineEventNotification notification) {
        if (notification instanceof EntityDeleteWarning<?>) {
            Object entity = ((EntityDeleteWarning<?>) notification).getDatabaseEntity();
            if (entity instanceof EmailAccount) {
                EmailAccount deletedEmailAccount = (EmailAccount) entity;
                for (Reminder reminder : reminderDao.getAllReminders()) {
                    EmailAccount reminderEmailAccount = reminder.getEmailAccount();
                    if (reminderEmailAccount != null && reminderEmailAccount.equals(deletedEmailAccount)) {
                        LOG.debug("WARNING, email account " + deletedEmailAccount.getAccountName()
                                + " will be deleted!!");
                        try {
                            reminder.setEmailAccount(null);
                            reminderDao.updateReminder(reminder);
                        } catch (Exception ex) {
                            LOG.error("Error removing email account from Reminder", ex);
                        }
                    }
                }
            }
        }
    }

    /**
     * Schedule a Reminder
     */
    public void scheduleReminder(Reminder reminder) {
        LOG.debug("Callback.scheduleReminder: " + reminder);
        if (reminder != null && reminder.getStatus() != Status.SENT) {
            Calendar start = (Calendar) reminder.getStartCalendar().clone();
            Calendar end = reminder.getEndCalendar();
            Calendar now = Calendar.getInstance();
            if (reminder.getPeriod() > 0) {
                while (start.before(now)) {
                    start.add(Calendar.MILLISECOND, (int) reminder.getPeriod());
                }
                LOG.debug("Reminder Scheduled: " + reminder);
                long startDelay = start.getTimeInMillis() - now.getTimeInMillis();
                ScheduledFuture<?> future = this.scheduler.scheduleAtFixedRate(reminder, startDelay,
                        reminder.getPeriod(), TimeUnit.MILLISECONDS);
                this.futures.put(reminder, future);

                LOG.debug("Expiry Scheduled: " + reminder.getEndCalendar().getTime());
                long endDelay = end.getTimeInMillis() - now.getTimeInMillis();
                ExpiredReminder expiredReminder = new ExpiredReminder(reminder);
                ScheduledFuture<?> expiry = this.scheduler.schedule(expiredReminder, endDelay,
                        TimeUnit.MILLISECONDS);
                this.expired.put(reminder, expiry);
            } else {
                LOG.debug("Reminder Scheduled: " + reminder);
                long startDelay = start.getTimeInMillis() - now.getTimeInMillis();
                ScheduledFuture<?> future = this.scheduler.schedule(reminder, startDelay, TimeUnit.MILLISECONDS);
                this.futures.put(reminder, future);
            }
        }
    }

    /**
     * Stop a Reminder
     */
    public void stopReminder(Reminder reminder) {
        LOG.debug("Callback.stopReminder: " + reminder);
        if (reminder != null && this.futures.containsKey(reminder)) {
            ScheduledFuture<?> future = this.futures.get(reminder);
            if (future != null) {
                boolean result = future.cancel(true);
                LOG.debug("Future Cancel: " + result);
            }
            ScheduledFuture<?> expiry = this.expired.get(reminder);
            if (expiry != null) {
                boolean result = expiry.cancel(true);
                LOG.debug("Expiry Cancel: " + result);
            }
        }
    }

    /**
     * Refresh Reminders
     */
    public void refreshReminders(Reminder reminder) {
        LOG.debug("Callback.refreshReminders: " + reminder);
        if (reminder != null) {
            this.reminderDao.updateReminder(reminder);
        }
        this.pagerReminders.refresh();
    }

    /**
     * Send a collection of Reminders
     * @param list
     */
    public void sendReminder(Object list) {
        for (Object selected : this.ui.getSelectedItems(list)) {
            sendReminder((Reminder) this.ui.getAttachedObject(selected, Reminder.class));
        }
    }

    /**
     * Send a Reminder
     */
    public void sendReminder(Reminder reminder) {
        LOG.debug("sendReminder: " + reminder);
        LOG.debug("sendReminder: " + reminder);
        if (reminder != null) {
            if (reminder.getType() == Reminder.Type.EMAIL) {
                if (reminder.getEmailAccount() != null) {
                    for (String contactName : reminder.getRecipientsArray()) {
                        LOG.debug("Sending EMAIL");
                        Contact contact = this.contactDao.getContactByName(contactName);
                        Email email = new Email(reminder.getEmailAccount(), contact.getEmailAddress(),
                                reminder.getSubject(), reminder.getContent());
                        this.emailDao.saveEmail(email);
                        this.emailManager.sendEmail(email);
                    }
                    this.ui.setStatus(
                            InternationalisationUtils.getI18NString(RemindersConstants.EMAIL_REMINDER_SENT));
                } else {
                    this.ui.alert(
                            InternationalisationUtils.getI18NString(RemindersConstants.MISSING_EMAIL_ACCOUNT));
                }
            } else if (reminder.getType() == Reminder.Type.MESSAGE) {
                for (String contactName : reminder.getRecipientsArray()) {
                    Contact contact = this.contactDao.getContactByName(contactName);
                    if (contact != null) {
                        LOG.debug("Sending MESSAGE");
                        this.frontlineController.sendTextMessage(contact.getPhoneNumber(), reminder.getContent());
                    }
                }
                this.ui.setStatus(InternationalisationUtils.getI18NString(RemindersConstants.SMS_REMINDER_SENT));
            }
            Calendar now = Calendar.getInstance();
            if (now.equals(reminder.getEndCalendar())) {
                LOG.debug("now == end: " + reminder);
                reminder.setStatus(Reminder.Status.SENT);
            } else if (now.after(reminder.getEndCalendar())) {
                LOG.debug("now > end: " + reminder);
                reminder.setStatus(Reminder.Status.SENT);
            }
            this.reminderDao.updateReminder(reminder);
        }
        this.pagerReminders.refresh();
    }

    /**
     * Cancel all Reminders
     */
    public void cancelAllReminders() {
        LOG.debug("Callback.cancelAllReminders");
        if (this.scheduler != null) {
            this.scheduler.shutdownNow();
        }
    }

    /**
     * Set Front
     * @param frontlineController FrontlineSMS
     */
    public void setFrontline(FrontlineSMS frontlineController) {
        this.frontlineController = frontlineController;
        this.frontlineController.getEventBus().registerObserver(this);
    }

    /**
     * Get Thinlet tab
     * @return
     */
    public Object getTab() {
        return super.getTabComponent();
    }

    /**
     * Remove reminders
     */
    public void removeSelectedFromReminderList() {
        LOG.debug("removeSelectedFromReminderList");
        final Object[] selected = this.ui.getSelectedItems(this.tableReminders);
        for (Object o : selected) {
            Reminder reminder = this.ui.getAttachedObject(o, Reminder.class);
            LOG.debug("Deleting Reminder:" + reminder);
            if (reminder != null) {
                this.reminderDao.deleteReminder(reminder);
                if (reminder.getType() == Reminder.Type.EMAIL) {
                    this.ui.setStatus(
                            InternationalisationUtils.getI18NString(RemindersConstants.EMAIL_REMINDER_CREATED));
                } else {
                    this.ui.setStatus(
                            InternationalisationUtils.getI18NString(RemindersConstants.SMS_REMINDER_CREATED));
                }
            }
        }
        this.ui.removeConfirmationDialog();
        this.pagerReminders.refresh();
        this.enableOptions(this.tableReminders, this.menuReminders, this.toolbarReminders);
    }

    /**
     * Enable menu options and buttons accordingly
     * @param list
     * @param popup
     * @param toolbar
     */
    public void enableOptions(Object list, Object popup, Object toolbar) {
        Object[] selectedItems = this.ui.getSelectedItems(list);
        boolean hasSelection = selectedItems.length > 0;
        for (Object item : this.ui.getItems(popup)) {
            String name = this.ui.getString(item, Thinlet.NAME);
            if (TAB_MENU_CREATE.equals(name)) {
                this.ui.setEnabled(item, true);
            } else if (TAB_MENU_EDIT.equals(name)) {
                this.ui.setEnabled(item, hasSelection);
            } else if (TAB_MENU_DELETE.equals(name)) {
                this.ui.setEnabled(item, hasSelection);
            } else if (TAB_MENU_SEND.equals(name)) {
                this.ui.setEnabled(item, hasSelection);
            }
        }
        for (Object item : this.ui.getItems(toolbar)) {
            String name = this.ui.getString(item, Thinlet.NAME);
            if (TAB_TOOLBAR_CREATE.equals(name)) {
                this.ui.setEnabled(item, true);
            } else if (TAB_TOOLBAR_EDIT.equals(name)) {
                this.ui.setEnabled(item, hasSelection);
            } else if (TAB_TOOLBAR_DELETE.equals(name)) {
                this.ui.setEnabled(item, hasSelection);
            } else if (TAB_TOOLBAR_SEND.equals(name)) {
                this.ui.setEnabled(item, hasSelection);
            }
        }
    }

    /**
     * Show Reminders create / edit dialog
     */
    public void showReminderDialog() {
        showReminderDialog(null);
    }

    /**
     * Show Reminders create / edit dialog
     * @param reminderList
     */
    public void showReminderDialog(Object reminderList) {
        RemindersDialogHandler dialogHandler = new RemindersDialogHandler(this.ui, this.applicationContext, this);
        dialogHandler.setFrontline(this.frontlineController);
        if (reminderList != null) {
            final Object selected = this.ui.getSelectedItem(reminderList);
            Reminder reminder = this.ui.getAttachedObject(selected, Reminder.class);
            dialogHandler.init(reminder);
        } else {
            dialogHandler.init(null);
        }
    }

    /**
     * Populate reminders table
     */
    public PagedListDetails getListDetails(Object list, int startIndex, int limit) {
        LOG.debug("getListDetails:" + this.ui.getName(list));
        List<Reminder> reminders = this.reminderDao.getAllReminders(startIndex, limit);
        Object[] listItems = toThinletReminders(reminders);
        return new PagedListDetails(listItems.length, listItems);
    }

    /**
     * Convert collection of reminders to table rows
     * @param reminders collection of reminders
     * @return collection of table rows
     */
    private Object[] toThinletReminders(List<Reminder> reminders) {
        Object[] components = new Object[reminders.size()];
        for (int i = 0; i < components.length; i++) {
            Reminder r = reminders.get(i);
            components[i] = getReminderRow(r);
        }
        return components;
    }

    /**
     * Get table row
     * @param reminder Reminder
     * @return table row
     */
    private Object getReminderRow(Reminder reminder) {
        Object row = this.ui.createTableRow(reminder);

        if (reminder.getStatus() == Reminder.Status.SENT) {
            Object statusCell = this.ui.createTableCell("");
            this.ui.setIcon(statusCell, Icon.TICK);
            this.ui.setChoice(statusCell, ThinletText.ALIGNMENT, ThinletText.CENTER);
            this.ui.add(row, statusCell);
        } else {
            this.ui.add(row, this.ui.createTableCell(""));
        }

        Object typeCell = this.ui.createTableCell("");
        if (reminder.getType() == Reminder.Type.EMAIL) {
            this.ui.setIcon(typeCell, Icon.EMAIL);
        } else {
            this.ui.setIcon(typeCell, Icon.SMS);
        }
        this.ui.setChoice(typeCell, ThinletText.ALIGNMENT, ThinletText.CENTER);
        this.ui.add(row, typeCell);

        Object occuranceCell = this.ui.createTableCell(reminder.getOccurrenceLabel());
        this.ui.setChoice(occuranceCell, ThinletText.ALIGNMENT, ThinletText.CENTER);
        this.ui.add(row, occuranceCell);

        DateFormat dateFormat = InternationalisationUtils.getDatetimeFormat();

        if (reminder.getStartDate() > 0) {
            Date startdate = new Date(reminder.getStartDate());
            this.ui.add(row, this.ui.createTableCell(dateFormat.format(startdate)));
        } else {
            this.ui.add(row, this.ui.createTableCell(""));
        }

        if (reminder.getEndDate() > 0) {
            Date enddate = new Date(reminder.getEndDate());
            this.ui.add(row, this.ui.createTableCell(dateFormat.format(enddate)));
        } else {
            this.ui.add(row, this.ui.createTableCell(""));
        }

        this.ui.add(row, this.ui.createTableCell(reminder.getRecipients()));
        this.ui.add(row, this.ui.createTableCell(reminder.getSubject()));
        this.ui.add(row, this.ui.createTableCell(reminder.getContent()));

        return row;
    }

}