/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/calendar/trunk/calendar-impl/impl/src/java/org/sakaiproject/calendar/impl/readers/OutlookReader.java $ * $Id: OutlookReader.java 105079 2012-02-24 23:08:11Z ottenhoff@longsight.com $ *********************************************************************************** * * Copyright (c) 2003, 2004, 2005, 2006, 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.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; 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 a comma (or other separator other than a double-quote) delimited * file. */ public class OutlookReader extends CSVReader { private ResourceLoader rb = new ResourceLoader("calendar"); // // Commented out lines are present in the import file, but we are // currently ignoring them. They are here for reference/future use. // public final String SUBJECT_HEADER = "Subject"; public final String START_DATE_HEADER = "Start Date"; public final String START_TIME_HEADER = "Start Time"; public final String END_DATE_HEADER = "End Date"; public final String END_TIME_HEADER = "End Time"; public final String ALL_DAY_EVENT_HEADER = "All day event"; // FALSE/TRUE public final String DESCRIPTION_HEADER = "Description"; public final String LOCATION_HEADER = "Location"; /** * Default constructor */ public OutlookReader() { super(); } /** * Import a CSV file from a stream and callback on each row. * @param stream Stream of CSV (or other delimited data) * @param handler Callback for each row. */ public void importStreamFromDelimitedFile( InputStream stream, ReaderImportRowHandler handler) throws ImportException { BufferedReader bufferedReader = getReader(stream); ColumnHeader columnDescriptionArray[] = null; // Set out delimiter to be a comma. setColumnDelimiter(","); int lineNumber = 1; boolean readDone = false; while (!readDone) { try { // Prepare the column map on the first line. String lineBuffer = bufferedReader.readLine(); // See if we have exhausted the input if (lineBuffer == null) { break; } if (columnDescriptionArray == null) { columnDescriptionArray = buildColumnDescriptionArray( parseLineFromDelimitedFile(lineBuffer)); // Immediately start the next loop, don't do any more // processing. lineNumber++; continue; } else { lineBuffer = lineBuffer.trim(); // If we have continuation lines, concatenate those. if ( !lineBuffer.endsWith("\"") || lineBuffer.endsWith(",\"") ) { String lineRead = bufferedReader.readLine(); //we need a string buffer StringBuffer sb = new StringBuffer(lineBuffer); while ( lineRead != null ) { sb.append("\n" + lineRead); if ( lineRead.startsWith("\"") ) { break; } lineRead = bufferedReader.readLine(); } lineBuffer = sb.toString(); } handler.handleRow( processLine( columnDescriptionArray, lineNumber, parseLineFromDelimitedFile(lineBuffer))); } } catch (IOException e) { // We'll get an exception when we've exhauster readDone = true; } // If we get this far, increment the line counter. lineNumber++; } } /* (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 { setColumnDelimiter(","); Iterator it = events.iterator(); // // 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(GenericCalendarImporter.START_TIME_PROPERTY_NAME); 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 { throw new ImportException( rb.getString("err_no_stime") ); } Date endTime = (Date) eventProperties.get(GenericCalendarImporter.END_TIME_PROPERTY_NAME); 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 ); } else { throw new ImportException( rb.getString("err_no_etime") ); } Date startDate = (Date) eventProperties.get(GenericCalendarImporter.DATE_PROPERTY_NAME); // 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) ); Date endDate = (Date) eventProperties.get(GenericCalendarImporter.ENDS_PROPERTY_NAME); // if the source time zone were known, this would be // a good place to set it: startCal.setTimeZone() GregorianCalendar endCal = new GregorianCalendar(); if ( endDate != null ) endCal.setTimeInMillis( endDate.getTime() ); endTimeBreakdown.setYear( endCal.get(Calendar.YEAR) ); endTimeBreakdown.setMonth( endCal.get(Calendar.MONTH)+1 ); endTimeBreakdown.setDay( endCal.get(Calendar.DAY_OF_MONTH) ); eventProperties.put( GenericCalendarImporter.ACTUAL_TIMERANGE, getTimeService().newTimeRange( getTimeService().newTimeLocal(startTimeBreakdown), getTimeService().newTimeLocal(endTimeBreakdown), true, false)); } return events; } /* (non-Javadoc) * @see org.sakaiproject.tool.calendar.schedimportreaders.Reader#getDefaultColumnMap() */ public Map getDefaultColumnMap() { // // Commented out properties are ones that we could set, but are // currently not being used. They might be in the future. // Map columnHeaderMap = new HashMap(); columnHeaderMap.put(SUBJECT_HEADER, GenericCalendarImporter.TITLE_PROPERTY_NAME); columnHeaderMap.put(DESCRIPTION_HEADER, GenericCalendarImporter.DESCRIPTION_PROPERTY_NAME); columnHeaderMap.put(START_DATE_HEADER, GenericCalendarImporter.DATE_PROPERTY_NAME); columnHeaderMap.put(START_TIME_HEADER, GenericCalendarImporter.START_TIME_PROPERTY_NAME); columnHeaderMap.put(END_TIME_HEADER, GenericCalendarImporter.END_TIME_PROPERTY_NAME); columnHeaderMap.put(LOCATION_HEADER, GenericCalendarImporter.LOCATION_PROPERTY_NAME); columnHeaderMap.put(END_DATE_HEADER, GenericCalendarImporter.ENDS_PROPERTY_NAME); // This is one that we use only for conversion. columnHeaderMap.put(ALL_DAY_EVENT_HEADER, ALL_DAY_EVENT_HEADER); return columnHeaderMap; } }