Projet

Général

Profil

Bug #6130 » ICal4JICalCodec.java

Sebastien Vuillet, 17/12/2014 19:45

 
/**
* Copyright (C) 2000 - 2013 Silverpeas
*
* 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.
*
* As a special exception to the terms and conditions of version 3.0 of the GPL, you may
* redistribute this Program in connection with Free/Libre Open Source Software ("FLOSS")
* applications as described in Silverpeas's FLOSS exception. You should have received a copy of the
* text describing the FLOSS exception, and it is also available here:
* "http://www.silverpeas.org/docs/core/legal/floss_exception.html"
*
* 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 com.silverpeas.export.ical.ical4j;

import java.io.ByteArrayOutputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Named;

import com.silverpeas.calendar.CalendarEvent;
import com.silverpeas.calendar.CalendarEventRecurrence;
import com.silverpeas.calendar.Datable;
import com.silverpeas.export.EncodingException;
import com.silverpeas.export.ical.ICalCodec;

import net.fortuna.ical4j.data.CalendarOutputter;
import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.Date;
import net.fortuna.ical4j.model.DateList;
import net.fortuna.ical4j.model.Recur;
import net.fortuna.ical4j.model.TextList;
import net.fortuna.ical4j.model.component.VEvent;
import net.fortuna.ical4j.model.property.Attendee;
import net.fortuna.ical4j.model.property.CalScale;
import net.fortuna.ical4j.model.property.Categories;
import net.fortuna.ical4j.model.property.Clazz;
import net.fortuna.ical4j.model.property.Description;
import net.fortuna.ical4j.model.property.ExDate;
import net.fortuna.ical4j.model.property.Location;
import net.fortuna.ical4j.model.property.Priority;
import net.fortuna.ical4j.model.property.ProdId;
import net.fortuna.ical4j.model.property.RRule;
import net.fortuna.ical4j.model.property.Uid;
import net.fortuna.ical4j.model.property.Url;
import net.fortuna.ical4j.model.property.Version;
import net.fortuna.ical4j.util.UidGenerator;
import org.apache.commons.lang3.CharEncoding;
import org.apache.tika.io.IOUtils;

import static com.silverpeas.export.ical.ical4j.ICal4JDateCodec.anICal4JDateCodec;
import static com.silverpeas.export.ical.ical4j.ICal4JRecurrenceCodec.anICal4JRecurrenceCodec;

/**
* An iCal encoder/decoder by using the iCal4J library.
*/
@Named("iCalCodec")
public class ICal4JICalCodec implements ICalCodec {

private UidGenerator generator = new UidGenerator(new OffLineInetAddressHostInfo(), Uid.UID);

@Override
@SuppressWarnings("unchecked")
public String encode(List<CalendarEvent> events) {

if (events == null || events.isEmpty()) {
throw new IllegalArgumentException("The calendar events must be defined to encode them");
}
Calendar calendarIcs = new Calendar();
calendarIcs.getProperties().add(new ProdId("-//Silverpeas//iCal4j 1.1//FR"));
calendarIcs.getProperties().add(Version.VERSION_2_0);
calendarIcs.getProperties().add(CalScale.GREGORIAN);
List<VEvent> iCalEvents = new ArrayList<VEvent>();
ByteArrayOutputStream output = new ByteArrayOutputStream(10240);
for (CalendarEvent event : events) {
Date startDate = anICal4JDateCodec().encode(event.getStartDate());
Date endDate = anICal4JDateCodec().encode(event.getEndDate());
VEvent iCalEvent;
if (event.isOnAllDay() && startDate.equals(endDate)) {
iCalEvent = new VEvent(startDate, event.getTitle());
} else {
iCalEvent = new VEvent(startDate, endDate, event.getTitle());
}

// Generate UID
iCalEvent.getProperties().add(generator.generateUid());

// Add recurring data if any
if (event.isRecurring()) {
CalendarEventRecurrence eventRecurrence = event.getRecurrence();
Recur recur = anICal4JRecurrenceCodec().encode(eventRecurrence);
iCalEvent.getProperties().add(new RRule(recur));
iCalEvent.getProperties().add(exceptionDatesFrom(eventRecurrence));
}
// Add Description
iCalEvent.getProperties().add(new Html(event.getDescription()));
// Add Classification
iCalEvent.getProperties().add(new Clazz(event.getAccessLevel()));
// Add Priority
iCalEvent.getProperties().add(new Priority(event.getPriority()));

// Add location if any
if (!event.getLocation().isEmpty()) {
iCalEvent.getProperties().add(new Location(event.getLocation()));
}

// Add event URL if any
if (event.getUrl() != null) {
try {
iCalEvent.getProperties().add(new Url(event.getUrl().toURI()));
} catch (URISyntaxException ex) {
throw new EncodingException(ex.getMessage(), ex);
}
}

// Add Categories
TextList categoryList = new TextList(event.getCategories().asArray());
if (!categoryList.isEmpty()) {
iCalEvent.getProperties().add(new Categories(categoryList));
}
// Add attendees
for (String attendee : event.getAttendees().asList()) {
try {
iCalEvent.getProperties().add(new Attendee(attendee));
} catch (URISyntaxException ex) {
throw new EncodingException("Malformed attendee URI: " + attendee, ex);
}
}

iCalEvents.add(iCalEvent);
}
calendarIcs.getComponents().addAll(iCalEvents);
CalendarOutputter outputter = new CalendarOutputter();
try {
outputter.output(calendarIcs, output);
return output.toString(CharEncoding.UTF_8);
} catch (Exception ex) {
throw new EncodingException("The encoding of the events in iCal formatted text has failed!",
ex);
} finally {
IOUtils.closeQuietly(output);
}
}

private ExDate exceptionDatesFrom(final CalendarEventRecurrence recurrence) {
List<Datable<?>> exceptionDates = recurrence.getExceptionDates();
DateList exDatesList = new DateList();
ICal4JDateCodec dateCodec = ICal4JDateCodec.anICal4JDateCodec();
for (Datable<?> anExceptionDate : exceptionDates) {
exDatesList.add(dateCodec.encode(anExceptionDate));
}
return new ExDate(exDatesList);
}
}
(1-1/2)