org.jasig.schedassist.impl.events.AutomaticAttendeeRemovalApplicationListener.java Source code

Java tutorial

Introduction

Here is the source code for org.jasig.schedassist.impl.events.AutomaticAttendeeRemovalApplicationListener.java

Source

/**
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.jasig.schedassist.impl.events;

import java.text.SimpleDateFormat;
import java.util.List;

import net.fortuna.ical4j.model.Parameter;
import net.fortuna.ical4j.model.Property;
import net.fortuna.ical4j.model.component.VEvent;
import net.fortuna.ical4j.model.parameter.Cn;
import net.fortuna.ical4j.model.property.Location;
import net.fortuna.ical4j.model.property.Summary;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.schedassist.impl.owner.OwnerDao;
import org.jasig.schedassist.impl.reminder.IReminder;
import org.jasig.schedassist.impl.reminder.ReminderService;
import org.jasig.schedassist.model.AvailableBlock;
import org.jasig.schedassist.model.AvailableBlockBuilder;
import org.jasig.schedassist.model.ICalendarAccount;
import org.jasig.schedassist.model.IScheduleOwner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.MessageSource;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * {@link ApplicationListener} for {@link AutomaticAttendeeRemovalEvent}s.
 * Sends email notifications asynchronously when events occur.
 * 
 * @author Nicholas Blair, nblair@doit.wisc.edu
 * @version $Id: AutomaticAttendeeRemovalApplicationListener.java $
 */
@Component
public class AutomaticAttendeeRemovalApplicationListener
        implements ApplicationListener<AutomaticAttendeeRemovalEvent> {

    private Log LOG = LogFactory.getLog(this.getClass());
    private MailSender mailSender;
    private MessageSource messageSource;
    private OwnerDao ownerDao;
    private ReminderService reminderService;
    private String noReplyFromAddress;

    /**
     * @param mailSender the mailSender to set
     */
    @Autowired
    public void setMailSender(MailSender mailSender) {
        this.mailSender = mailSender;
    }

    /**
     * @param messageSource the messageSource to set
     */
    @Autowired
    public void setMessageSource(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    /**
     * @param ownerDao the ownerDao to set
     */
    @Autowired
    public void setOwnerDao(OwnerDao ownerDao) {
        this.ownerDao = ownerDao;
    }

    /**
     * @param reminderService the reminderService to set
     */
    @Autowired
    public void setReminderService(ReminderService reminderService) {
        this.reminderService = reminderService;
    }

    /**
     * @param noReplyFromAddress the noReplyFromAddress to set
     */
    @Value("${reminder.noReplyFromAddress}")
    public void setNoReplyFromAddress(String noReplyFromAddress) {
        this.noReplyFromAddress = noReplyFromAddress;
    }

    /* (non-Javadoc)
     * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
     */
    @Async
    @Override
    public void onApplicationEvent(AutomaticAttendeeRemovalEvent event) {
        ICalendarAccount owner = event.getOwner();
        VEvent vevent = event.getEvent();
        Property removedAttendee = event.getRemoved();
        String removedAttendeeEmail = removedAttendee.getValue()
                .substring(EmailNotificationApplicationListener.MAILTO_PREFIX.length());

        deleteEventReminder(owner, vevent, removedAttendeeEmail);

        SimpleMailMessage message = new SimpleMailMessage();
        if (!EmailNotificationApplicationListener.isEmailAddressValid(owner.getEmailAddress())) {
            message.setFrom(noReplyFromAddress);
        } else {
            message.setFrom(owner.getEmailAddress());
        }
        message.setTo(removedAttendeeEmail);

        Summary summary = vevent.getSummary();
        if (summary != null) {
            message.setSubject(summary.getValue() + " has been updated");
        } else {
            LOG.warn("event is missing summary: " + event);
            message.setSubject("Appointment has been updated");
        }
        message.setText(constructMessageBody(vevent, removedAttendee, owner.getDisplayName()));

        LOG.debug("sending message: " + message.toString());
        mailSender.send(message);
        LOG.debug("message successfully sent");
    }

    /**
     * Delete the {@link IReminder} for the event, if found
     * @param ownerAccount
     * @param event
     */
    protected void deleteEventReminder(ICalendarAccount ownerAccount, VEvent event,
            String removedAttendeeEmailAddress) {
        if (ownerAccount == null || event == null) {
            return;
        }
        // locateOwner is not going to return null here
        // reminders are deleted in cascade when an owner unregisters, nor would the application be evaluating a non-owner's calendar data for automatic cancellation
        IScheduleOwner owner = ownerDao.locateOwner(ownerAccount);
        // intentionally uses the AvailableBlockBuilder directly and avoids the AvailableScheduleDao
        // avoids the problem if the owner deleted the block from their schedule after the visitor creates the event but before the reminder is sent
        AvailableBlock appointmentBlock = AvailableBlockBuilder.createBlock(event.getStartDate().getDate(),
                event.getEndDate().getDate());
        List<IReminder> reminders = reminderService.getReminders(owner, appointmentBlock);

        for (IReminder reminder : reminders) {
            if (reminder.getRecipient().getEmailAddress().equals(removedAttendeeEmailAddress)) {
                reminderService.deleteEventReminder(reminder);
                LOG.info("successfully deleted reminder " + reminder
                        + " for automatically removed attendee with email address " + removedAttendeeEmailAddress
                        + ", owner=" + ownerAccount);
                return;
            }
        }
        if (reminders.size() > 0) {
            LOG.warn("did not find a matching reminder for " + removedAttendeeEmailAddress + " in " + reminders);
        }
    }

    /**
     * 
     * @param event
     * @param removedAttendee
     * @param ownerName
     * @return
     */
    protected String constructMessageBody(VEvent event, Property removedAttendee, String ownerName) {
        StringBuilder body = new StringBuilder();
        Parameter cn = removedAttendee.getParameter(Cn.CN);

        body.append(this.messageSource.getMessage("automatic.attendee.remove.notify.introduction",
                new String[] { cn.getValue() }, null));

        body.append(EmailNotificationApplicationListener.NEWLINE);
        body.append(EmailNotificationApplicationListener.NEWLINE);
        Summary summary = event.getSummary();
        if (summary != null) {
            body.append(
                    this.messageSource.getMessage("notify.email.title", new String[] { summary.getValue() }, null));
            body.append(EmailNotificationApplicationListener.NEWLINE);
        }
        SimpleDateFormat df = new SimpleDateFormat("EEE, MMM d, yyyy");
        SimpleDateFormat tf = new SimpleDateFormat("h:mm a");
        body.append(df.format(event.getStartDate().getDate()));
        body.append(EmailNotificationApplicationListener.NEWLINE);
        body.append(this.messageSource.getMessage("notify.email.time", new String[] {
                tf.format(event.getStartDate().getDate()), tf.format(event.getEndDate(true).getDate()) }, null));
        Location location = event.getLocation();
        if (location != null) {
            body.append(EmailNotificationApplicationListener.NEWLINE);
            body.append(this.messageSource.getMessage("notify.email.location", new String[] { location.getValue() },
                    null));
        }
        body.append(EmailNotificationApplicationListener.NEWLINE);
        body.append(EmailNotificationApplicationListener.NEWLINE);

        body.append(this.messageSource.getMessage("automatic.attendee.remove.notify.footer", null, null));

        return body.toString();
    }
}