001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/calendar/tags/sakai_2-4-1/calendar-impl/impl/src/java/org/sakaiproject/calendar/impl/readers/OutlookReader.java $
003: * $Id: OutlookReader.java 22253 2007-03-07 14:04:18Z bkirschn@umich.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.calendar.impl.readers;
021:
022: import java.io.BufferedReader;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.util.Date;
026: import java.util.Calendar;
027: import java.util.GregorianCalendar;
028: import java.util.HashMap;
029: import java.util.Iterator;
030: import java.util.List;
031: import java.util.Map;
032:
033: import org.sakaiproject.calendar.impl.GenericCalendarImporter;
034: import org.sakaiproject.exception.ImportException;
035: import org.sakaiproject.time.api.TimeBreakdown;
036: import org.sakaiproject.util.ResourceLoader;
037:
038: /**
039: * This class parses a comma (or other separator other than a double-quote) delimited
040: * file.
041: */
042: public class OutlookReader extends CSVReader {
043: private ResourceLoader rb = new ResourceLoader("calendarimpl");
044:
045: //
046: // Commented out lines are present in the import file, but we are
047: // currently ignoring them. They are here for reference/future use.
048: //
049: public final String SUBJECT_HEADER = "Subject";
050: public final String START_DATE_HEADER = "Start Date";
051: public final String START_TIME_HEADER = "Start Time";
052: public final String END_DATE_HEADER = "End Date";
053: public final String END_TIME_HEADER = "End Time";
054: public final String ALL_DAY_EVENT_HEADER = "All day event"; // FALSE/TRUE
055: public final String DESCRIPTION_HEADER = "Description";
056: public final String LOCATION_HEADER = "Location";
057:
058: /**
059: * Default constructor
060: */
061: public OutlookReader() {
062: super ();
063: }
064:
065: /**
066: * Import a CSV file from a stream and callback on each row.
067: * @param stream Stream of CSV (or other delimited data)
068: * @param handler Callback for each row.
069: */
070: public void importStreamFromDelimitedFile(InputStream stream,
071: ReaderImportRowHandler handler) throws ImportException {
072: BufferedReader bufferedReader = getReader(stream);
073:
074: ColumnHeader columnDescriptionArray[] = null;
075:
076: // Set out delimiter to be a comma.
077: setColumnDelimiter(",");
078:
079: int lineNumber = 1;
080:
081: boolean readDone = false;
082:
083: while (!readDone) {
084: try {
085: // Prepare the column map on the first line.
086: String lineBuffer = bufferedReader.readLine();
087:
088: // See if we have exhausted the input
089: if (lineBuffer == null) {
090: break;
091: }
092:
093: if (columnDescriptionArray == null) {
094: columnDescriptionArray = buildColumnDescriptionArray(parseLineFromDelimitedFile(lineBuffer));
095:
096: // Immediately start the next loop, don't do any more
097: // processing.
098: lineNumber++;
099: continue;
100: } else {
101: lineBuffer = lineBuffer.trim();
102:
103: // If we have continuation lines, concatenate those.
104: if (!lineBuffer.endsWith("\"")
105: || lineBuffer.endsWith(",\"")) {
106: String lineRead = bufferedReader.readLine();
107:
108: while (lineRead != null) {
109: lineBuffer += "\n" + lineRead;
110:
111: if (lineRead.startsWith("\"")) {
112: break;
113: }
114:
115: lineRead = bufferedReader.readLine();
116: }
117: }
118:
119: handler.handleRow(processLine(
120: columnDescriptionArray, lineNumber,
121: parseLineFromDelimitedFile(lineBuffer)));
122: }
123: } catch (IOException e) {
124: // We'll get an exception when we've exhauster
125: readDone = true;
126: }
127:
128: // If we get this far, increment the line counter.
129: lineNumber++;
130: }
131: }
132:
133: /* (non-Javadoc)
134: * @see org.sakaiproject.tool.calendar.schedimportreaders.Reader#filterEvents(java.util.List, java.lang.String[])
135: */
136: public List filterEvents(List events, String[] customFieldNames)
137: throws ImportException {
138: setColumnDelimiter(",");
139:
140: Iterator it = events.iterator();
141:
142: //
143: // Convert the date/time fields as they appear in the Outlook import to
144: // be a synthesized start/end timerange.
145: //
146: while (it.hasNext()) {
147: Map eventProperties = (Map) it.next();
148:
149: Date startTime = (Date) eventProperties
150: .get(GenericCalendarImporter.START_TIME_PROPERTY_NAME);
151: TimeBreakdown startTimeBreakdown = null;
152:
153: if (startTime != null) {
154: // if the source time zone were known, this would be
155: // a good place to set it: startCal.setTimeZone()
156: GregorianCalendar startCal = new GregorianCalendar();
157: startCal.setTimeInMillis(startTime.getTime());
158: startTimeBreakdown = getTimeService().newTimeBreakdown(
159: 0, 0, 0, startCal.get(Calendar.HOUR_OF_DAY),
160: startCal.get(Calendar.MINUTE),
161: startCal.get(Calendar.SECOND), 0);
162: } else {
163: throw new ImportException(rb.getString("err_no_stime"));
164: }
165:
166: Date endTime = (Date) eventProperties
167: .get(GenericCalendarImporter.END_TIME_PROPERTY_NAME);
168: TimeBreakdown endTimeBreakdown = null;
169:
170: if (endTime != null) {
171: // if the source time zone were known, this would be
172: // a good place to set it: endCal.setTimeZone()
173: GregorianCalendar endCal = new GregorianCalendar();
174: endCal.setTimeInMillis(endTime.getTime());
175: endTimeBreakdown = getTimeService().newTimeBreakdown(0,
176: 0, 0, endCal.get(Calendar.HOUR_OF_DAY),
177: endCal.get(Calendar.MINUTE),
178: endCal.get(Calendar.SECOND), 0);
179: } else {
180: throw new ImportException(rb.getString("err_no_etime"));
181: }
182:
183: Date startDate = (Date) eventProperties
184: .get(GenericCalendarImporter.DATE_PROPERTY_NAME);
185:
186: // if the source time zone were known, this would be
187: // a good place to set it: startCal.setTimeZone()
188: GregorianCalendar startCal = new GregorianCalendar();
189: if (startDate != null)
190: startCal.setTimeInMillis(startDate.getTime());
191:
192: startTimeBreakdown.setYear(startCal.get(Calendar.YEAR));
193: startTimeBreakdown
194: .setMonth(startCal.get(Calendar.MONTH) + 1);
195: startTimeBreakdown.setDay(startCal
196: .get(Calendar.DAY_OF_MONTH));
197:
198: Date endDate = (Date) eventProperties
199: .get(GenericCalendarImporter.ENDS_PROPERTY_NAME);
200:
201: // if the source time zone were known, this would be
202: // a good place to set it: startCal.setTimeZone()
203: GregorianCalendar endCal = new GregorianCalendar();
204: if (endDate != null)
205: endCal.setTimeInMillis(endDate.getTime());
206:
207: endTimeBreakdown.setYear(endCal.get(Calendar.YEAR));
208: endTimeBreakdown.setMonth(endCal.get(Calendar.MONTH) + 1);
209: endTimeBreakdown.setDay(endCal.get(Calendar.DAY_OF_MONTH));
210:
211: eventProperties.put(
212: GenericCalendarImporter.ACTUAL_TIMERANGE,
213: getTimeService().newTimeRange(
214: getTimeService().newTimeLocal(
215: startTimeBreakdown),
216: getTimeService().newTimeLocal(
217: endTimeBreakdown), true, false));
218: }
219:
220: return events;
221: }
222:
223: /* (non-Javadoc)
224: * @see org.sakaiproject.tool.calendar.schedimportreaders.Reader#getDefaultColumnMap()
225: */
226: public Map getDefaultColumnMap() {
227: //
228: // Commented out properties are ones that we could set, but are
229: // currently not being used. They might be in the future.
230: //
231: Map columnHeaderMap = new HashMap();
232:
233: columnHeaderMap.put(SUBJECT_HEADER,
234: GenericCalendarImporter.TITLE_PROPERTY_NAME);
235: columnHeaderMap.put(DESCRIPTION_HEADER,
236: GenericCalendarImporter.DESCRIPTION_PROPERTY_NAME);
237: columnHeaderMap.put(START_DATE_HEADER,
238: GenericCalendarImporter.DATE_PROPERTY_NAME);
239: columnHeaderMap.put(START_TIME_HEADER,
240: GenericCalendarImporter.START_TIME_PROPERTY_NAME);
241: columnHeaderMap.put(END_TIME_HEADER,
242: GenericCalendarImporter.END_TIME_PROPERTY_NAME);
243: columnHeaderMap.put(LOCATION_HEADER,
244: GenericCalendarImporter.LOCATION_PROPERTY_NAME);
245: columnHeaderMap.put(END_DATE_HEADER,
246: GenericCalendarImporter.ENDS_PROPERTY_NAME);
247:
248: // This is one that we use only for conversion.
249: columnHeaderMap.put(ALL_DAY_EVENT_HEADER, ALL_DAY_EVENT_HEADER);
250:
251: return columnHeaderMap;
252: }
253: }
|