Update deps to Funambol 8.7
[funambol-groupdav-connector.git] / src / main / java / net / bionicmessage / funambol / datakit / ical4j2funambol.java
blob45a33c750a193bf91db141394e0735bc288b6bae
1 /*
2 * ical4j2funambol.java
4 * Created on 26 November 2006, 15:44
5 * Copyright (C) Mathew McBride 2006-2007
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 package net.bionicmessage.funambol.datakit;
22 import java.text.ParseException;
23 import java.util.logging.Level;
24 import java.util.logging.Logger;
25 import net.bionicmessage.utils.QPDecode;
26 import com.funambol.common.pim.calendar.RecurrencePattern;
27 import com.funambol.common.pim.calendar.RecurrencePatternException;
28 import com.funambol.common.pim.calendar.Task;
29 import com.funambol.common.pim.converter.CalendarStatus;
30 import com.funambol.common.pim.converter.VCalendarConverter;
31 import com.funambol.common.pim.model.VCalendar;
32 import java.io.FileInputStream;
33 import net.fortuna.ical4j.model.*;
34 import net.fortuna.ical4j.model.Property.*;
36 import net.fortuna.ical4j.data.*;
37 import java.util.ArrayList;
38 import java.util.Iterator;
39 import java.util.List;
40 import net.bionicmessage.funambol.framework.Constants;
41 import net.bionicmessage.utils.QPDecode;
42 import net.fortuna.ical4j.model.component.VAlarm;
43 import net.fortuna.ical4j.model.component.VEvent;
44 import net.fortuna.ical4j.model.component.VToDo;
45 import net.fortuna.ical4j.model.parameter.AltRep;
46 import net.fortuna.ical4j.model.parameter.Encoding;
47 import net.fortuna.ical4j.model.parameter.PartStat;
48 import net.fortuna.ical4j.model.parameter.Related;
49 import net.fortuna.ical4j.model.property.Attendee;
50 import net.fortuna.ical4j.model.property.Categories;
51 import net.fortuna.ical4j.model.property.DateProperty;
52 import net.fortuna.ical4j.model.property.Description;
53 import net.fortuna.ical4j.model.property.DtEnd;
54 import net.fortuna.ical4j.model.property.DtStart;
55 import net.fortuna.ical4j.model.property.Due;
56 import net.fortuna.ical4j.model.property.ExDate;
57 import net.fortuna.ical4j.model.property.Location;
58 import net.fortuna.ical4j.model.property.Priority;
59 import net.fortuna.ical4j.model.property.RRule;
60 import net.fortuna.ical4j.model.property.Status;
61 import net.fortuna.ical4j.model.property.Summary;
62 import net.fortuna.ical4j.model.property.Transp;
63 import net.fortuna.ical4j.model.property.Trigger;
64 import net.fortuna.ical4j.model.property.Uid;
66 /**
67 * Provides utilities for converting ical4j data objects to Fumambol
68 * PDI objects
69 * @author matt
71 public class ical4j2funambol {
73 /** Creates a new instance of ical4j2funambol */
74 public static com.funambol.common.pim.calendar.Calendar convertIcal4jToFunambolEvent(net.fortuna.ical4j.model.Calendar ical4j_in, String clientType) throws RecurrencePatternException {
75 long dstime = 0;
76 long detime = 0;
77 /* QP decode a second time just to be sure. (the first is in object store/jgroupdav) */
78 net.fortuna.ical4j.model.Calendar ical4j = QPDecode.decodeQP(ical4j_in);
79 /* Setup a funambol event */
80 com.funambol.common.pim.calendar.Calendar fnblcal = new com.funambol.common.pim.calendar.Calendar();
81 com.funambol.common.pim.calendar.CalendarContent fnblcontent = null;
82 Component comp = null;
83 comp = (Component) ical4j.getComponents().getComponent(Component.VEVENT);
84 if (comp == null) {
85 comp = (Component) ical4j.getComponents().getComponent(Component.VTODO);
86 fnblcontent = new com.funambol.common.pim.calendar.Task();
87 fnblcal.setTask((Task) fnblcontent);
88 } else {
89 fnblcontent = new com.funambol.common.pim.calendar.Event();
90 fnblcal.setEvent((com.funambol.common.pim.calendar.Event) fnblcontent);
93 String startDate = ""; /* If we get DtStart, then cache it for Funambol recur */
94 DtStart dts = null; /* Also cache dtstart */
95 /* Blatantly obvious attributes */
96 if (comp.getProperty(Uid.UID) != null) {
97 Uid uid = (Uid) comp.getProperty(Uid.UID);
98 com.funambol.common.pim.common.Property uidprop =
99 new com.funambol.common.pim.common.Property(uid.getValue());
100 fnblcontent.setUid(uidprop);
102 /* if (comp.getProperty(LastModified.LAST_MODIFIED) != null) {
103 LastModified lm = (LastModified)comp.getProperty(LastModified.LAST_MODIFIED);
104 com.funambol.common.pim.common.Property lmprop =
105 new com.funambol.common.pim.common.Property();
106 lm.setUtc(true);
107 lmprop.setPropertyValue(lm.getValue());
108 fnblcontent.setLastModified(lmprop);
109 } */
110 /* if (comp.getProperty(Clazz.CLASS) != null) {
111 Clazz cl = (Clazz)comp.getProperty(Clazz.CLASS);
112 com.funambol.common.pim.common.Property clprop =
113 new com.funambol.common.pim.common.Property(cl.getValue());
115 } */
116 /* Start off with basic attributes.. DTSTART, DTEND, SUMMARY, DESCRIPTION, LOCATION,
117 PRIORITY */
118 // Do not convert DTSTART for VToDo (rejected by some clients)
119 if (comp.getProperty(DtStart.DTSTART) != null &&
120 !comp.getName().equals(VToDo.VTODO)) {
121 dts = (DtStart) comp.getProperty(DtStart.DTSTART);
122 Parameter v = dts.getParameter("VALUE");
123 if (v != null &&
124 v.getValue().equals("DATE")) {
125 String newValue = dts.getValue();
126 attachAllDayDtStart(fnblcontent, newValue, clientType);
127 } else {
128 dts.setUtc(true);
129 com.funambol.common.pim.common.Property dtsprop = new com.funambol.common.pim.common.Property(dts.getValue());
130 fnblcontent.setDtStart(dtsprop);
131 dstime = dts.getDate().getTime();
132 fnblcontent.setAllDay(false);
134 startDate = fnblcontent.getDtStart().getPropertyValueAsString();
136 if (comp.getProperty(DtEnd.DTEND) != null) {
137 DtEnd dte = (DtEnd) comp.getProperty(DtEnd.DTEND);
138 Parameter v = dte.getParameter("VALUE");
139 if (v != null &&
140 v.getValue().equals("DATE")) {
141 String newValue = dte.getValue();
142 attachAllDayDtEnd(fnblcontent, newValue, clientType);
143 } else {
144 dte.setUtc(true);
145 com.funambol.common.pim.common.Property dteprop =
146 new com.funambol.common.pim.common.Property(dte.getValue());
147 fnblcontent.setDtEnd(dteprop);
148 detime = dte.getDate().getTime();
149 fnblcontent.setAllDay(false);
152 if (comp.getProperty(Due.DUE) != null && comp.getProperty(DtEnd.DTEND) == null) {
153 Due due = (Due) comp.getProperty(Due.DUE);
154 Parameter v = due.getParameter("VALUE");
155 if (v != null &&
156 v.getValue().equals("DATE")) {
157 String newValue = due.getValue();
158 attachAllDayDtEnd(fnblcontent, newValue, clientType);
159 } else {
160 due.setUtc(true);
161 com.funambol.common.pim.common.Property dteprop =
162 new com.funambol.common.pim.common.Property(due.getValue());
163 fnblcontent.setDtEnd(dteprop);
166 /** See if an all day event hasn't sneaked in via the back door */
167 if (detime - dstime == 86340000 || detime - dstime == 86399000) {
168 /* See the vObject minimum interoperability profile - OMA
169 * (OMA-TS-vObjectOMAProfile-V1_0-20050118-C) for information on how to
170 * correctly establish an all day event */
171 fnblcontent.setAllDay(true);
172 DtEnd dte = (DtEnd) comp.getProperty(DtEnd.DTEND);
173 dte.setUtc(false);
174 net.fortuna.ical4j.model.Date dt = new net.fortuna.ical4j.model.Date(dte.getDate().getTime());
175 dte.setDate(dt);
176 net.fortuna.ical4j.model.Date ds = new net.fortuna.ical4j.model.Date(dts.getDate().getTime());
177 dts.setDate(ds);
178 attachAllDayDtStart(fnblcontent, dts.getValue(), clientType);
179 attachAllDayDtEnd(fnblcontent, dte.getValue(), clientType);
181 if (comp.getProperty(Summary.SUMMARY) != null) {
182 /* We need to consider text encodings for this.
183 * ical2 specifies 8 bit and base64 in spec, but vcal1
184 * also allows quoted-printable (EVIL!!!). */
185 Summary summ = (Summary) comp.getProperty(Summary.SUMMARY);
186 com.funambol.common.pim.common.Property summprop =
187 new com.funambol.common.pim.common.Property();
188 // Check for encodings
189 if (summ.getParameter(Encoding.ENCODING) != null) {
190 Encoding enc = (Encoding) summ.getParameter(Encoding.ENCODING);
191 summprop.setEncoding(enc.getValue());
193 summprop.setPropertyValue(summ.getValue());
194 fnblcontent.setSummary(summprop);
196 if (comp.getProperty(Description.DESCRIPTION) != null) {
197 /* We also need to consider alternative text encoding here */
198 Description des = (Description) comp.getProperty(Description.DESCRIPTION);
199 com.funambol.common.pim.common.Property desprop =
200 new com.funambol.common.pim.common.Property();
201 // Check for encdoings
202 if (des.getParameter(Encoding.ENCODING) != null) {
203 Encoding enc = (Encoding) des.getParameter(Encoding.ENCODING);
204 desprop.setEncoding(enc.getValue());
206 desprop.setPropertyValue(des.getValue());
207 fnblcontent.setDescription(desprop);
209 if (comp.getProperty(Location.LOCATION) != null) {
210 Location loc = (Location) comp.getProperty(Location.LOCATION);
211 com.funambol.common.pim.common.Property locprop =
212 new com.funambol.common.pim.common.Property();
213 // Is our location pointing to a URL?
214 if (loc.getParameter(AltRep.ALTREP) != null) {
215 AltRep url = (AltRep) loc.getParameter(AltRep.ALTREP);
216 locprop.setValue("URL");
217 locprop.setType("VCARD");
219 locprop.setPropertyValue(loc.getValue());
220 fnblcontent.setLocation(locprop);
222 if (comp.getProperty(Priority.PRIORITY) != null) {
223 Priority pri = (Priority) comp.getProperty(Priority.PRIORITY);
224 com.funambol.common.pim.common.Property priprop =
225 new com.funambol.common.pim.common.Property(pri.getValue());
226 fnblcontent.setPriority(priprop);
227 } else if (comp.getName().equals(VToDo.VTODO)) {
228 com.funambol.common.pim.common.Property priprop =
229 new com.funambol.common.pim.common.Property("1");
230 fnblcontent.setPriority(priprop);
232 /* Slightly harder */
233 if (comp.getProperty(Transp.TRANSP) != null && fnblcontent instanceof com.funambol.common.pim.calendar.Event) {
234 Transp tsp = (Transp) comp.getProperty(Transp.TRANSP);
235 com.funambol.common.pim.common.Property tspprop =
236 new com.funambol.common.pim.common.Property();
237 if (tsp.getValue().equals(Transp.OPAQUE)) {
238 // This event WILL show up as busy
239 tspprop.setPropertyValue("0");
240 } else { // What calendar app couldn't chose between OPAQUE and TRANSPARENT?
241 tspprop.setPropertyValue("1");
243 com.funambol.common.pim.calendar.Event e =
244 (com.funambol.common.pim.calendar.Event) fnblcontent;
245 e.setTransp(tspprop);
247 if (comp.getProperty(Status.STATUS) != null &&
248 fnblcontent instanceof com.funambol.common.pim.calendar.Task) {
249 Status status = (Status) comp.getProperty(Status.STATUS);
250 com.funambol.common.pim.common.Property stat =
251 new com.funambol.common.pim.common.Property();
252 CalendarStatus cstatus = CalendarStatus.mapVcalIcalStatus(status.getValue());
253 if (fnblcontent instanceof com.funambol.common.pim.calendar.Event) {
254 stat.setPropertyValue(cstatus.getVCalICalValue(true));
255 } else if (fnblcontent instanceof com.funambol.common.pim.calendar.Task) {
256 stat.setPropertyValue(cstatus.getServerValue());
258 fnblcontent.setStatus(stat);
260 PropertyList attendees = comp.getProperties("ATTENDEE");
261 List<com.funambol.common.pim.calendar.Attendee> fnblattendees =
262 fnblcontent.getAttendees();
263 Iterator attendeeIterator = attendees.iterator();
264 while (attendeeIterator.hasNext()) {
265 Attendee att = (Attendee) attendeeIterator.next();
266 com.funambol.common.pim.calendar.Attendee fnblatt = AttendeeConverter.icalToFunambol(att);
267 if (fnblatt != null) {
268 fnblattendees.add(fnblatt);
271 if (comp.getProperty(Categories.CATEGORIES) != null) {
272 Categories cat = (Categories) comp.getProperty(Categories.CATEGORIES);
273 fnblcontent.getCategories().setPropertyValue(cat.getValue());
275 if (comp.getProperty(RRule.RRULE) != null) {
276 RRule rr = (RRule) comp.getProperty(RRule.RRULE);
277 Recur r = rr.getRecur();
278 ArrayList<com.funambol.common.pim.calendar.ExceptionToRecurrenceRule>
279 exceptionList = new ArrayList(2);
280 if (comp.getProperty(ExDate.EXDATE) != null) {
281 ExDate ex = (ExDate)comp.getProperty("EXDATE");
282 String value = ex.getValue();
283 String[] params = value.split(",");
284 for (int i = 0; i < params.length; i++) {
285 try {
286 String val = params[i];
287 com.funambol.common.pim.calendar.ExceptionToRecurrenceRule etrr = new com.funambol.common.pim.calendar.ExceptionToRecurrenceRule(false, val);
288 exceptionList.add(etrr);
289 } catch (ParseException ex1) {
290 ex1.printStackTrace();
294 /* This is where things start getting insane. Funambol wants us to
295 * find out every property of the recurrance rule and then use a custom
296 * constructor for each case! */
297 /* ical2 RULE VIOLATION: VEVENT may contain multiple RRULES... */
298 String freq = r.getFrequency();
300 int interval = (r.getInterval() > 0) ? r.getInterval() : 1;
301 int count = r.getCount();
302 boolean noEndDate = false;
303 String endDate = "";
304 if (r.getUntil() == null) {
305 noEndDate = true;
306 } else {
307 net.fortuna.ical4j.model.Date eDate =
308 new net.fortuna.ical4j.model.Date(r.getUntil());
309 endDate = eDate.toString();
311 short dayOfWeekMask = 0;
312 if (freq.equals(Recur.DAILY)) {
313 try {
314 RecurrencePattern rp = RecurrencePattern.getDailyRecurrencePattern(interval,
315 startDate,
316 endDate,
317 noEndDate,
318 count,
319 dayOfWeekMask);
320 fnblcontent.setRecurrencePattern(rp);
322 } catch (RecurrencePatternException re) {
323 re.printStackTrace();
324 // Send all RecurrencePatternExceptions to ground for now
326 } else if (freq.equals(Recur.HOURLY)) {
327 /* NOT SUPPORTED BY VCAL1 AND FUNAMBOL */
328 } else if (freq.equals(Recur.WEEKLY)) {
329 /* Weekly */
330 try {
331 ArrayList wkdaylist = r.getDayList();
332 for (int i = 0; i < wkdaylist.size(); i++) {
333 WeekDay wday = (WeekDay) wkdaylist.get(i);
334 String day = wday.getDay();
335 if (day.equals("SU")) {
336 dayOfWeekMask++;
337 } else if (day.equals("MO")) {
338 dayOfWeekMask = (short) (dayOfWeekMask + 2);
339 } else if (day.equals("TU")) {
340 dayOfWeekMask = (short) (dayOfWeekMask + 4);
341 } else if (day.equals("WE")) {
342 dayOfWeekMask = (short) (dayOfWeekMask + 8);
343 } else if (day.equals("TU")) {
344 dayOfWeekMask = (short) (dayOfWeekMask + 16);
345 } else if (day.equals("FR")) {
346 dayOfWeekMask = (short) (dayOfWeekMask + 32);
347 } else if (day.equals("SA")) {
348 dayOfWeekMask = (short) (dayOfWeekMask + 64);
351 RecurrencePattern rp = RecurrencePattern.getWeeklyRecurrencePattern(interval,
352 dayOfWeekMask,
353 startDate,
354 endDate,
355 noEndDate,
356 count);
357 fnblcontent.setRecurrencePattern(rp);
358 } catch (RecurrencePatternException re) {
359 re.printStackTrace();
361 } else if (freq.equals(Recur.MONTHLY)) {
362 /* Monthly - we have two sorts of month recurrance - by number day of month
363 * or day of week of month */
364 // Do we have a set week position
365 if (r.getDayList().size() > 0) {
366 // Get the weekday instance
367 WeekDay wd = (WeekDay) r.getDayList().get(0);
368 String day = wd.getDay();
369 int week = wd.getOffset();
370 Integer weekoffset = new Integer(week);
371 if (day.equals("SU")) {
372 dayOfWeekMask++;
373 } else if (day.equals("MO")) {
374 dayOfWeekMask = (short) (dayOfWeekMask + 2);
375 } else if (day.equals("TU")) {
376 dayOfWeekMask = (short) (dayOfWeekMask + 4);
377 } else if (day.equals("WE")) {
378 dayOfWeekMask = (short) (dayOfWeekMask + 8);
379 } else if (day.equals("TU")) {
380 dayOfWeekMask = (short) (dayOfWeekMask + 16);
381 } else if (day.equals("FR")) {
382 dayOfWeekMask = (short) (dayOfWeekMask + 32);
383 } else if (day.equals("SA")) {
384 dayOfWeekMask = (short) (dayOfWeekMask + 64);
386 RecurrencePattern rp = RecurrencePattern.getMonthNthRecurrencePattern(
387 r.getInterval(),
388 dayOfWeekMask,
389 weekoffset.shortValue(),
390 startDate,
391 endDate,
392 noEndDate,
393 r.getCount());
394 fnblcontent.setRecurrencePattern(rp);
395 } else {
396 try {
397 java.util.Calendar mcal = java.util.Calendar.getInstance();
398 mcal.setTime(dts.getDate());
399 Integer dayOfMonth = new Integer(mcal.get(java.util.Calendar.DAY_OF_MONTH));
400 dayOfWeekMask = dayOfMonth.shortValue();
401 RecurrencePattern rp = RecurrencePattern.getMonthlyRecurrencePattern(interval,
402 dayOfWeekMask,
403 startDate,
404 endDate,
405 noEndDate,
406 count);
407 fnblcontent.setRecurrencePattern(rp);
408 } catch (RecurrencePatternException re) {
409 re.printStackTrace();
413 } else if (freq.equals(Recur.YEARLY)) {
414 // Same as monthly recurrence basically.
415 if (r.getDayList().size() > 0) {
416 WeekDay wd = (WeekDay) r.getDayList().get(0);
417 String day = wd.getDay();
418 int week = wd.getOffset();
419 Integer weekoffset = new Integer(week);
420 Integer month = (Integer) r.getMonthList().get(0);
421 if (day.equals("SU")) {
422 dayOfWeekMask++;
423 } else if (day.equals("MO")) {
424 dayOfWeekMask = (short) (dayOfWeekMask + 2);
425 } else if (day.equals("TU")) {
426 dayOfWeekMask = (short) (dayOfWeekMask + 4);
427 } else if (day.equals("WE")) {
428 dayOfWeekMask = (short) (dayOfWeekMask + 8);
429 } else if (day.equals("TU")) {
430 dayOfWeekMask = (short) (dayOfWeekMask + 16);
431 } else if (day.equals("FR")) {
432 dayOfWeekMask = (short) (dayOfWeekMask + 32);
433 } else if (day.equals("SA")) {
434 dayOfWeekMask = (short) (dayOfWeekMask + 64);
436 RecurrencePattern rp = RecurrencePattern.getYearNthRecurrencePattern(r.getInterval(),
437 dayOfWeekMask,
438 month.shortValue(),
439 weekoffset.shortValue(),
440 startDate,
441 endDate,
442 noEndDate,
443 count);
444 } else {
445 if (r.getInterval() < 0) {
446 r.setInterval(1);
448 try {
449 RecurrencePattern rp = RecurrencePattern.getYearlyRecurrencePattern(
450 r.getInterval(),
451 (short) 0,
452 (short) 0,
453 startDate,
454 endDate,
455 noEndDate,
456 count);
457 fnblcontent.setRecurrencePattern(rp);
458 } catch (Exception ex) {
459 ex.printStackTrace();
463 if (fnblcontent.getRecurrencePattern() != null) {
464 try {
465 fnblcontent.getRecurrencePattern().setExceptions(exceptionList);
466 } catch (Exception e) {
467 e.printStackTrace();
471 com.funambol.common.pim.common.Property prodid =
472 new com.funambol.common.pim.common.Property("-//BionicMessage Funambol Connector//ical4jFunambolconvert//EN");
473 fnblcal.setProdId(prodid);
474 com.funambol.common.pim.common.Property ver =
475 new com.funambol.common.pim.common.Property("1.0");
476 fnblcal.setVersion(ver);
477 return fnblcal;
478 /* NOT YET CONVERTED: attach / attendee / exdate / exrule / geo / seq
479 * recurid */
482 public static void attachAllDayDtEnd(com.funambol.common.pim.calendar.CalendarContent e, String newValue, String clientType) {
483 if (clientType.equals("text/x-vcalendar")) {
484 newValue = newValue + "T240000";
485 com.funambol.common.pim.common.Property dteprop =
486 new com.funambol.common.pim.common.Property(newValue);
487 e.setAllDay(true);
488 e.getDtEnd().setPropertyValue(newValue);
489 } else if (clientType.equals("text/x-s4j-sife")) {
490 e.getDtEnd().setPropertyValue(newValue);
491 e.setAllDay(true);
495 public static void attachAllDayDtStart(com.funambol.common.pim.calendar.CalendarContent e, String newValue, String clientType) {
496 if (clientType.equals("text/x-vcalendar")) {
497 newValue = newValue + "T000000";
498 com.funambol.common.pim.common.Property dtsprop =
499 new com.funambol.common.pim.common.Property(newValue);
500 e.setAllDay(true);
501 e.getDtStart().setPropertyValue(newValue);
502 } else if (clientType.equals("text/x-s4j-sife")) {
503 e.getDtStart().setPropertyValue(newValue);
504 e.setAllDay(true);
508 /** Process any alarms in the event/todo. Since this functionality is optional,
509 * it is in another function
511 public static void attachAlarm(com.funambol.common.pim.calendar.CalendarContent e,
512 net.fortuna.ical4j.model.component.CalendarComponent ical4je) {
513 ComponentList alarms = null;
514 if (ical4je instanceof VEvent) {
515 VEvent ve = (VEvent) ical4je;
516 alarms = ve.getAlarms();
517 } else if (ical4je instanceof VToDo) {
518 VToDo vt = (VToDo) ical4je;
519 alarms = vt.getAlarms();
520 } else {
521 return;
523 Iterator alarmIterator = alarms.iterator();
524 while (alarmIterator.hasNext()) {
525 VAlarm va = (VAlarm) alarmIterator.next();
527 Trigger t = va.getTrigger();
528 String[] dalarmComponents = {"", "", "", ""};
529 if (va.getAction().getValue().equals("DISPLAY")) {
530 if (t.getDateTime() != null) {
531 dalarmComponents[0] = t.getDateTime().toString();
532 } else if (t.getDuration() != null) {
533 Dur dur = t.getDuration();
534 DateProperty relatedTo = null;
535 if (t.getParameter(Related.RELATED) != null &&
536 t.getParameter(Related.RELATED).equals(Related.END)) {
537 relatedTo = (DateProperty) ical4je.getProperty(DtEnd.DTEND);
538 } else {
539 relatedTo = (DateProperty) ical4je.getProperty(DtStart.DTSTART);
541 Date dt = relatedTo.getDate();
542 // Calculate a new DateTime relative to dt
543 java.util.Calendar cal = java.util.Calendar.getInstance();
544 cal.setTime(dt);
545 cal.add(java.util.Calendar.SECOND, -(dur.getSeconds()));
546 cal.add(java.util.Calendar.MINUTE, -(dur.getMinutes()));
547 cal.add(java.util.Calendar.HOUR, -(dur.getHours()));
548 cal.add(java.util.Calendar.DAY_OF_YEAR, -(dur.getDays()));
549 cal.add(java.util.Calendar.WEEK_OF_YEAR, -(dur.getWeeks()));
550 DateTime newDate = new DateTime(cal.getTime());
551 newDate.setUtc(true);
552 dalarmComponents[0] = newDate.toString();
555 StringBuffer buf = new StringBuffer();
556 for (int i = 0; i < dalarmComponents.length; i++) {
557 if (dalarmComponents[i] != null) {
558 buf.append(dalarmComponents[i]);
560 if (dalarmComponents.length != i - 1) {
561 buf.append(";");
564 e.setDAlarm(new com.funambol.common.pim.common.Property(buf.toString()));
567 public static com.funambol.common.pim.calendar.Attendee
568 attachPartStat(PartStat ps,
569 com.funambol.common.pim.calendar.Attendee att) {
570 com.funambol.common.pim.calendar.Attendee fnblatt = att;
571 if (PartStat.ACCEPTED.equals(ps)) {
572 fnblatt.setStatus(com.funambol.common.pim.calendar.Attendee.ACCEPTED);
573 } else if (PartStat.DECLINED.equals(ps)) {
574 fnblatt.setStatus(com.funambol.common.pim.calendar.Attendee.DECLINED);
575 } else if (PartStat.DELEGATED.equals(ps)) {
576 fnblatt.setStatus(com.funambol.common.pim.calendar.Attendee.DELEGATED);
577 } else if (PartStat.TENTATIVE.equals(ps)) {
578 fnblatt.setStatus(com.funambol.common.pim.calendar.Attendee.TENTATIVE);
580 return fnblatt;
582 /** Standalone tester */
583 public static void main(String args[]) {
584 if (args.length < 1) {
585 System.err.println("Arguments: ical4j2funambol <file.ics>");
586 return;
588 try {
589 String file = args[0];
590 FileInputStream fis = new FileInputStream(file);
591 CalendarBuilder cbuild = new CalendarBuilder();
592 Calendar ics = cbuild.build(fis);
593 com.funambol.common.pim.calendar.Calendar fnblcal =
594 ical4j2funambol.convertIcal4jToFunambolEvent(ics, "text/x-vcalendar");
595 VCalendarConverter vcc = new VCalendarConverter(null, "UTF-8",false);
596 VCalendar vc = vcc.calendar2vcalendar(fnblcal, true);
597 System.out.println(vc.toString());
598 } catch (Exception e) {
599 e.printStackTrace();