fr.paris.lutece.plugins.workflow.modules.appointment.service.ICalService.java Source code

Java tutorial

Introduction

Here is the source code for fr.paris.lutece.plugins.workflow.modules.appointment.service.ICalService.java

Source

/*
 * Copyright (c) 2002-2014, Mairie de Paris
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice
 *     and the following disclaimer.
 *
 *  2. Redistributions in binary form must reproduce the above copyright notice
 *     and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *
 *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * License 1.0
 */
package fr.paris.lutece.plugins.workflow.modules.appointment.service;

import fr.paris.lutece.plugins.appointment.business.Appointment;
import fr.paris.lutece.plugins.appointment.business.calendar.AppointmentSlot;
import fr.paris.lutece.plugins.appointment.business.calendar.AppointmentSlotHome;
import fr.paris.lutece.portal.service.mail.MailService;
import fr.paris.lutece.portal.service.spring.SpringContextService;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import net.fortuna.ical4j.model.ComponentList;
import net.fortuna.ical4j.model.DateTime;
import net.fortuna.ical4j.model.Dur;
import net.fortuna.ical4j.model.Parameter;
import net.fortuna.ical4j.model.ParameterFactoryRegistry;
import net.fortuna.ical4j.model.Property;
import net.fortuna.ical4j.model.TimeZone;
import net.fortuna.ical4j.model.TimeZoneRegistry;
import net.fortuna.ical4j.model.TimeZoneRegistryFactory;
import net.fortuna.ical4j.model.component.Observance;
//import net.fortuna.ical4j.model.TimeZone;
import net.fortuna.ical4j.model.component.VEvent;
import net.fortuna.ical4j.model.component.VTimeZone;
import net.fortuna.ical4j.model.parameter.Cn;
import net.fortuna.ical4j.model.parameter.PartStat;
import net.fortuna.ical4j.model.parameter.Role;
import net.fortuna.ical4j.model.parameter.Rsvp;
import net.fortuna.ical4j.model.parameter.XParameter;
import net.fortuna.ical4j.model.property.Attendee;
import net.fortuna.ical4j.model.property.CalScale;
import net.fortuna.ical4j.model.property.Description;
import net.fortuna.ical4j.model.property.DtEnd;
import net.fortuna.ical4j.model.property.Location;
import net.fortuna.ical4j.model.property.Method;
import net.fortuna.ical4j.model.property.Organizer;
import net.fortuna.ical4j.model.property.ProdId;
import net.fortuna.ical4j.model.property.TzName;
import net.fortuna.ical4j.model.property.TzOffsetFrom;
import net.fortuna.ical4j.model.property.TzOffsetTo;
import net.fortuna.ical4j.model.property.Uid;
import net.fortuna.ical4j.model.property.Version;
import net.fortuna.ical4j.model.property.TzNameFactory;

import org.apache.commons.lang.StringUtils;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
//import java.util.TimeZone;

/**
 * Service to send iCal appointments by email
 */
public class ICalService {
    /**
     * The name of the bean of this service
     */
    public static final String BEAN_NAME = "workflow-appointment.iCalService";
    private static final String PROPERTY_MAIL_LIST_SEPARATOR = "mail.list.separator";
    private static final String PROPERTY_ICAL_PRODID = "workflow-appointment.ical.prodid";
    private static final String PROPERTY_TIMEZONE = "workflow-appointment.server.timezone";
    private static final String CONSTANT_MAILTO = "MAILTO:";

    /**
     * Get an instance of the service
     * @return An instance of the bean of this service
     */
    public static ICalService getService() {
        return SpringContextService.getBean(BEAN_NAME);
    }

    /**
     * Send an appointment to a user by email.
     * @param strEmailAttendee Comma separated list of users that will attend
     *            the appointment
     * @param strEmailOptionnal Comma separated list of users that will be
     *            invited to the appointment, but who are not required.
     * @param strSubject The subject of the appointment.
     * @param strBodyContent The body content that describes the appointment
     * @param strLocation The location of the appointment
     * @param strSenderName The name of the sender
     * @param strSenderEmail The email of the sender
     * @param appointment The appointment
     * @param bCreate True to notify the creation of the appointment, false to
     *            notify its removal
     */
    public void sendAppointment(String strEmailAttendee, String strEmailOptionnal, String strSubject,
            String strBodyContent, String strLocation, String strSenderName, String strSenderEmail,
            Appointment appointment, boolean bCreate) {

        AppointmentSlot slot = AppointmentSlotHome.findByPrimaryKey(appointment.getIdSlot());
        Calendar calendarStart = new GregorianCalendar(Locale.FRENCH);

        calendarStart.setTime(appointment.getDateAppointment());
        calendarStart.add(Calendar.HOUR, slot.getStartingHour());
        calendarStart.add(Calendar.MINUTE, slot.getStartingMinute());

        int nAppDurationMinutes = ((slot.getEndingHour() - slot.getStartingHour()) * 60)
                + (slot.getEndingMinute() - slot.getStartingMinute());
        int nDurationAppointmentHours = nAppDurationMinutes / 60;
        int nDurationAppointmentMinutes = nAppDurationMinutes % 60;

        int nDurationAppointmentDays = nDurationAppointmentHours / 24;
        nDurationAppointmentHours %= 24;

        //       Dur duration = new Dur( nDurationAppointmentDays, nDurationAppointmentHours, nDurationAppointmentMinutes, 0 );

        //        TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry();
        //        TimeZone timezone = registry.getTimeZone("Europe/Paris");

        DateTime beginningDateTime = new DateTime(calendarStart.getTimeInMillis());
        beginningDateTime.setTimeZone(getParisZone());

        Calendar endCal = new GregorianCalendar();
        endCal.setTimeInMillis(calendarStart.getTimeInMillis());
        endCal.add(Calendar.MINUTE, nAppDurationMinutes);

        DateTime endingDateTime = new DateTime(endCal.getTimeInMillis());
        endingDateTime.setTimeZone(getParisZone());

        VEvent event = new VEvent(beginningDateTime, endingDateTime,
                (strSubject != null) ? strSubject : StringUtils.EMPTY);

        calendarStart.add(Calendar.MINUTE, nAppDurationMinutes);

        //  event.getProperties(  ).add( new DtEnd( endingDateTime ) );

        try {
            event.getProperties()
                    .add(new Uid(Appointment.APPOINTMENT_RESOURCE_TYPE + appointment.getIdAppointment()));

            String strEmailSeparator = AppPropertiesService.getProperty(PROPERTY_MAIL_LIST_SEPARATOR, ";");
            if (StringUtils.isNotEmpty(strEmailAttendee)) {
                StringTokenizer st = new StringTokenizer(strEmailAttendee, strEmailSeparator);

                while (st.hasMoreTokens()) {
                    addAttendee(event, st.nextToken(), true);
                }
            }

            if (StringUtils.isNotEmpty(strEmailOptionnal)) {
                StringTokenizer st = new StringTokenizer(strEmailOptionnal, strEmailSeparator);

                while (st.hasMoreTokens()) {
                    addAttendee(event, st.nextToken(), false);
                }
            }

            Organizer organizer = new Organizer(strSenderEmail);
            organizer.getParameters().add(new Cn(strSenderName));
            event.getProperties().add(organizer);
            event.getProperties().add(new Location(strLocation));
            event.getProperties().add(new Description(strBodyContent));
        } catch (URISyntaxException e) {
            AppLogService.error(e.getMessage(), e);
        }

        net.fortuna.ical4j.model.Calendar iCalendar = new net.fortuna.ical4j.model.Calendar();
        iCalendar.getProperties().add(bCreate ? Method.REQUEST : Method.CANCEL);
        iCalendar.getProperties().add(new ProdId(AppPropertiesService.getProperty(PROPERTY_ICAL_PRODID)));
        iCalendar.getProperties().add(Version.VERSION_2_0);
        iCalendar.getProperties().add(CalScale.GREGORIAN);

        iCalendar.getComponents().add(event);

        MailService.sendMailCalendar(strEmailAttendee, strEmailOptionnal, null, strSenderName, strSenderEmail,
                (strSubject != null) ? strSubject : StringUtils.EMPTY, strBodyContent, iCalendar.toString(),
                bCreate);
    }

    /**
     * Add an attendee to an event
     * @param event The event to add the attendee to
     * @param strEmail The email of the user
     * @param bRequired True if the presence of the user is mandatory, false if
     *            it is optional
     */
    private void addAttendee(VEvent event, String strEmail, boolean bRequired) {
        Attendee attendee = new Attendee(URI.create(CONSTANT_MAILTO + strEmail));
        attendee.getParameters().add(bRequired ? Role.REQ_PARTICIPANT : Role.OPT_PARTICIPANT);
        attendee.getParameters().add(PartStat.NEEDS_ACTION);
        attendee.getParameters().add(Rsvp.FALSE);
        event.getProperties().add(attendee);
    }

    /**
     * Get  TimeZone
     * @return Paris TimeZone
     */
    private static TimeZone getParisZone() {
        TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry();
        String strZone = "\"Romance Standard Time\"";
        if (AppPropertiesService.getProperty(PROPERTY_TIMEZONE) != null
                && AppPropertiesService.getProperty(PROPERTY_TIMEZONE).trim().length() > 0)
            strZone = AppPropertiesService.getProperty(PROPERTY_TIMEZONE).trim();
        TimeZone timezone = registry.getTimeZone(strZone);
        return timezone;
    }

    /**
     * Get infos from TimeZone
     * @return VtimeZone
     */
    private static VTimeZone getTimeZone() {
        VTimeZone tz = getParisZone().getVTimeZone();

        Observance tmpobs = tz.getApplicableObservance(
                (new net.fortuna.ical4j.model.Date(GregorianCalendar.getInstance().getTimeInMillis())));
        if (tmpobs != null) {
            tz.getObservances().clear();
            tz.getObservances().add(tmpobs);
        }

        return tz;
    }
}