Java tutorial
/********************************************************************************** * $URL$ * $Id$ *********************************************************************************** * * Copyright (c) 2007, 2008 The Sakai Foundation * * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.calendar.impl.readers; import java.io.InputStream; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import net.fortuna.ical4j.data.CalendarBuilder; import net.fortuna.ical4j.model.Component; import net.fortuna.ical4j.model.component.VEvent; import net.fortuna.ical4j.model.property.DateProperty; import net.fortuna.ical4j.util.CompatibilityHints; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.calendar.impl.GenericCalendarImporter; import org.sakaiproject.exception.ImportException; import org.sakaiproject.time.api.TimeBreakdown; import org.sakaiproject.util.ResourceLoader; /** * This class parses an import file from iCalendar. */ public class IcalendarReader extends Reader { private ResourceLoader rb = new ResourceLoader("calendar"); private static Log M_log = LogFactory.getLog(IcalendarReader.class); private Map<String, String> defaultHeaderMap = getDefaultColumnMap(); private static final String CONTACT_SECTION_HEADER = "Contacts"; private static final String TODO_SECTION_HEADER = "Todos"; private static final String EVENT_SECTION_HEADER = "Events"; /** * Default constructor */ public IcalendarReader() { super(); } /* (non-Javadoc) * @see org.sakaiproject.tool.calendar.ImportReader#importStreamFromDelimitedFile(java.io.InputStream, org.sakaiproject.tool.calendar.ImportReader.ReaderImportRowHandler) */ public void importStreamFromDelimitedFile(InputStream stream, ReaderImportRowHandler handler) throws ImportException//, IOException, ParserException { try { ColumnHeader columnDescriptionArray[] = null; String descriptionColumns[] = { "Summary", "Description", "Start Date", "Start Time", "Duration", "Location" }; int lineNumber = 1; String durationformat = ""; String requireValues = ""; // column map stuff trimLeadingTrailingQuotes(descriptionColumns); columnDescriptionArray = buildColumnDescriptionArray(descriptionColumns); // enable "relaxed parsing"; read file using LF instead of CRLF CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_UNFOLDING, true); CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING, true); CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_OUTLOOK_COMPATIBILITY, true); CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION, true); CalendarBuilder builder = new CalendarBuilder(); net.fortuna.ical4j.model.Calendar calendar = builder.build(stream); for (Iterator i = calendar.getComponents("VEVENT").iterator(); i.hasNext();) { Component component = (Component) i.next(); // Find event duration DateProperty dtstartdate; DateProperty dtenddate; if (component instanceof VEvent) { VEvent vEvent = (VEvent) component; dtstartdate = vEvent.getStartDate(); dtenddate = vEvent.getEndDate(true); } else { dtstartdate = (DateProperty) component.getProperty("DTSTART"); dtenddate = (DateProperty) component.getProperty("DTEND"); } if (component.getProperty("SUMMARY") == null) { M_log.warn("IcalendarReader: SUMMARY is required; event not imported"); continue; } String summary = component.getProperty("SUMMARY").getValue(); if (component.getProperty("RRULE") != null) { M_log.warn("IcalendarReader: Re-occuring events not supported: " + summary); continue; } else if (dtstartdate == null || dtenddate == null) { M_log.warn("IcalendarReader: DTSTART/DTEND required: " + summary); continue; } int durationsecs = (int) ((dtenddate.getDate().getTime() - dtstartdate.getDate().getTime()) / 1000); int durationminutes = (durationsecs / 60) % 60; int durationhours = (durationsecs / (60 * 60)) % 24; // Put duration in proper format (hh:mm or mm) if less than 1 hour if (durationminutes < 10) { durationformat = "0" + durationminutes; } else { durationformat = "" + durationminutes; } if (durationhours != 0) { durationformat = durationhours + ":" + durationformat; } String description = ""; if (component.getProperty("DESCRIPTION") != null) description = component.getProperty("DESCRIPTION").getValue(); String location = ""; if (component.getProperty("LOCATION") != null) location = component.getProperty("LOCATION").getValue(); String columns[] = { component.getProperty("SUMMARY").getValue(), description, DateFormat.getDateInstance(DateFormat.SHORT, rb.getLocale()).format(dtstartdate.getDate()), DateFormat.getTimeInstance(DateFormat.SHORT, rb.getLocale()).format(dtstartdate.getDate()), durationformat, location }; // Remove trailing/leading quotes from all columns. //trimLeadingTrailingQuotes(columns); handler.handleRow(processLine(columnDescriptionArray, lineNumber, columns)); lineNumber++; } // end for } catch (Exception e) { M_log.warn(".importSteamFromDelimitedFile(): ", e); } } // end importStreamFromDelimitedFile /* (non-Javadoc) * @see org.sakaiproject.tool.calendar.schedimportreaders.Reader#filterEvents(java.util.List, java.lang.String[]) */ public List filterEvents(List events, String[] customFieldNames) throws ImportException { Iterator it = events.iterator(); int lineNumber = 1; // // Convert the date/time fields as they appear in the Outlook import to // be a synthesized start/end timerange. // while (it.hasNext()) { Map eventProperties = (Map) it.next(); Date startTime = (Date) eventProperties .get(defaultHeaderMap.get(GenericCalendarImporter.START_TIME_DEFAULT_COLUMN_HEADER)); TimeBreakdown startTimeBreakdown = null; if (startTime != null) { // if the source time zone were known, this would be // a good place to set it: startCal.setTimeZone() GregorianCalendar startCal = new GregorianCalendar(); startCal.setTimeInMillis(startTime.getTime()); startTimeBreakdown = getTimeService().newTimeBreakdown(0, 0, 0, startCal.get(Calendar.HOUR_OF_DAY), startCal.get(Calendar.MINUTE), startCal.get(Calendar.SECOND), 0); } else { Integer line = Integer.valueOf(lineNumber); String msg = (String) rb.getFormattedMessage("err_no_stime_on", new Object[] { line }); throw new ImportException(msg); } Integer durationInMinutes = (Integer) eventProperties .get(defaultHeaderMap.get(GenericCalendarImporter.DURATION_DEFAULT_COLUMN_HEADER)); if (durationInMinutes == null) { Integer line = Integer.valueOf(lineNumber); String msg = (String) rb.getFormattedMessage("err_no_dtime_on", new Object[] { line }); throw new ImportException(msg); } Date endTime = new Date(startTime.getTime() + (durationInMinutes.longValue() * 60 * 1000)); TimeBreakdown endTimeBreakdown = null; if (endTime != null) { // if the source time zone were known, this would be // a good place to set it: endCal.setTimeZone() GregorianCalendar endCal = new GregorianCalendar(); endCal.setTimeInMillis(endTime.getTime()); endTimeBreakdown = getTimeService().newTimeBreakdown(0, 0, 0, endCal.get(Calendar.HOUR_OF_DAY), endCal.get(Calendar.MINUTE), endCal.get(Calendar.SECOND), 0); } Date startDate = (Date) eventProperties .get(defaultHeaderMap.get(GenericCalendarImporter.DATE_DEFAULT_COLUMN_HEADER)); // if the source time zone were known, this would be // a good place to set it: startCal.setTimeZone() GregorianCalendar startCal = new GregorianCalendar(); if (startDate != null) startCal.setTimeInMillis(startDate.getTime()); startTimeBreakdown.setYear(startCal.get(Calendar.YEAR)); startTimeBreakdown.setMonth(startCal.get(Calendar.MONTH) + 1); startTimeBreakdown.setDay(startCal.get(Calendar.DAY_OF_MONTH)); endTimeBreakdown.setYear(startCal.get(Calendar.YEAR)); endTimeBreakdown.setMonth(startCal.get(Calendar.MONTH) + 1); endTimeBreakdown.setDay(startCal.get(Calendar.DAY_OF_MONTH)); eventProperties.put(GenericCalendarImporter.ACTUAL_TIMERANGE, getTimeService().newTimeRange(getTimeService().newTimeLocal(startTimeBreakdown), getTimeService().newTimeLocal(endTimeBreakdown), true, false)); lineNumber++; } return events; } /* (non-Javadoc) * @see org.sakaiproject.tool.calendar.schedimportreaders.Reader#getDefaultColumnMap() */ public Map<String, String> getDefaultColumnMap() { Map<String, String> columnHeaderMap = new HashMap<String, String>(); columnHeaderMap.put(GenericCalendarImporter.TITLE_DEFAULT_COLUMN_HEADER, GenericCalendarImporter.TITLE_PROPERTY_NAME); columnHeaderMap.put(GenericCalendarImporter.DESCRIPTION_DEFAULT_COLUMN_HEADER, GenericCalendarImporter.DESCRIPTION_PROPERTY_NAME); columnHeaderMap.put(GenericCalendarImporter.DATE_DEFAULT_COLUMN_HEADER, GenericCalendarImporter.DATE_PROPERTY_NAME); columnHeaderMap.put(GenericCalendarImporter.START_TIME_DEFAULT_COLUMN_HEADER, GenericCalendarImporter.START_TIME_PROPERTY_NAME); columnHeaderMap.put(GenericCalendarImporter.DURATION_DEFAULT_COLUMN_HEADER, GenericCalendarImporter.DURATION_PROPERTY_NAME); //columnHeaderMap.put(ITEM_HEADER, GenericCalendarImporter.ITEM_TYPE_PROPERTY_NAME); columnHeaderMap.put(GenericCalendarImporter.LOCATION_DEFAULT_COLUMN_HEADER, GenericCalendarImporter.LOCATION_PROPERTY_NAME); return columnHeaderMap; } }