upgrade to ical4j beta4, ContactSyncSource will not attempt to find existing items...
[funambol-groupdav-connector.git] / src / main / java / net / bionicmessage / funambol / datakit / ical4j2funambol.java
blobde6dd311e86c006f2b9a6d7428f789e97c0f402d
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 com.funambol.common.pim.calendar.RecurrencePattern;
23 import com.funambol.common.pim.calendar.RecurrencePatternException;
24 import com.funambol.common.pim.calendar.Task;
25 import com.funambol.common.pim.converter.VCalendarConverter;
26 import com.funambol.common.pim.model.VCalendar;
27 import java.io.FileInputStream;
28 import java.net.URI;
29 import net.fortuna.ical4j.model.*;
30 import net.fortuna.ical4j.model.Property.*;
32 import net.fortuna.ical4j.data.*;
33 import java.util.ArrayList;
34 import java.util.Iterator;
35 import java.util.List;
36 import net.fortuna.ical4j.model.component.CalendarComponent;
37 import net.fortuna.ical4j.model.component.VAlarm;
38 import net.fortuna.ical4j.model.component.VEvent;
39 import net.fortuna.ical4j.model.component.VToDo;
40 import net.fortuna.ical4j.model.parameter.AltRep;
41 import net.fortuna.ical4j.model.parameter.CuType;
42 import net.fortuna.ical4j.model.parameter.Encoding;
43 import net.fortuna.ical4j.model.parameter.Related;
44 import net.fortuna.ical4j.model.property.Action;
45 import net.fortuna.ical4j.model.property.Attendee;
46 import net.fortuna.ical4j.model.property.Categories;
47 import net.fortuna.ical4j.model.property.Clazz;
48 import net.fortuna.ical4j.model.property.DateProperty;
49 import net.fortuna.ical4j.model.property.Description;
50 import net.fortuna.ical4j.model.property.DtEnd;
51 import net.fortuna.ical4j.model.property.DtStart;
52 import net.fortuna.ical4j.model.property.Due;
53 import net.fortuna.ical4j.model.property.Duration;
54 import net.fortuna.ical4j.model.property.LastModified;
55 import net.fortuna.ical4j.model.property.Location;
56 import net.fortuna.ical4j.model.property.Priority;
57 import net.fortuna.ical4j.model.property.RDate;
58 import net.fortuna.ical4j.model.property.RRule;
59 import net.fortuna.ical4j.model.property.Status;
60 import net.fortuna.ical4j.model.property.Summary;
61 import net.fortuna.ical4j.model.property.Transp;
62 import net.fortuna.ical4j.model.property.Trigger;
63 import net.fortuna.ical4j.model.property.Uid;
65 /**
66 * Provides utilities for converting ical4j data objects to Fumambol
67 * PDI objects
68 * @author matt
70 public class ical4j2funambol {
72 /** Creates a new instance of ical4j2funambol */
73 public static com.funambol.common.pim.calendar.Calendar convertIcal4jToFunambolEvent(net.fortuna.ical4j.model.Calendar ical4j, String clientType) throws RecurrencePatternException {
74 long dstime = 0;
75 long detime = 0;
76 /* Setup a funambol event */
77 com.funambol.common.pim.calendar.Calendar fnblcal = new com.funambol.common.pim.calendar.Calendar();
78 com.funambol.common.pim.calendar.CalendarContent fnblcontent = null;
79 Component comp = null;
80 comp = (Component) ical4j.getComponents().get(0);
81 if (comp.getName().equals(VEvent.VEVENT)) {
82 fnblcontent = new com.funambol.common.pim.calendar.Event();
83 fnblcal.setEvent((com.funambol.common.pim.calendar.Event) fnblcontent);
84 } else if (comp.getName().equals(VToDo.VTODO)) {
85 fnblcontent = new com.funambol.common.pim.calendar.Task();
86 fnblcal.setTask((Task) fnblcontent);
90 String startDate = ""; /* If we get DtStart, then cache it for Funambol recur */
91 DtStart dts = null; /* Also cache dtstart */
92 /* Blatantly obvious attributes */
93 if (comp.getProperty(Uid.UID) != null) {
94 Uid uid = (Uid) comp.getProperty(Uid.UID);
95 com.funambol.common.pim.common.Property uidprop =
96 new com.funambol.common.pim.common.Property(uid.getValue());
97 fnblcontent.setUid(uidprop);
99 /* if (comp.getProperty(LastModified.LAST_MODIFIED) != null) {
100 LastModified lm = (LastModified)comp.getProperty(LastModified.LAST_MODIFIED);
101 com.funambol.common.pim.common.Property lmprop =
102 new com.funambol.common.pim.common.Property();
103 lm.setUtc(true);
104 lmprop.setPropertyValue(lm.getValue());
105 fnblcontent.setLastModified(lmprop);
106 } */
107 /* if (comp.getProperty(Clazz.CLASS) != null) {
108 Clazz cl = (Clazz)comp.getProperty(Clazz.CLASS);
109 com.funambol.common.pim.common.Property clprop =
110 new com.funambol.common.pim.common.Property(cl.getValue());
112 } */
113 /* Start off with basic attributes.. DTSTART, DTEND, SUMMARY, DESCRIPTION, LOCATION,
114 PRIORITY */
115 // Do not convert DTSTART for VToDo (rejected by some clients)
116 if (comp.getProperty(DtStart.DTSTART) != null &&
117 !comp.getName().equals(VToDo.VTODO)) {
118 dts = (DtStart) comp.getProperty(DtStart.DTSTART);
119 Parameter v = dts.getParameter("VALUE");
120 if (v != null &&
121 v.getValue().equals("DATE")) {
122 String newValue = dts.getValue();
123 attachAllDayDtStart(fnblcontent, newValue, clientType);
124 } else {
125 dts.setUtc(true);
126 com.funambol.common.pim.common.Property dtsprop = new com.funambol.common.pim.common.Property(dts.getValue());
127 fnblcontent.setDtStart(dtsprop);
128 dstime = dts.getDate().getTime();
129 fnblcontent.setAllDay(false);
131 startDate = fnblcontent.getDtStart().getPropertyValueAsString();
133 if (comp.getProperty(DtEnd.DTEND) != null) {
134 DtEnd dte = (DtEnd) comp.getProperty(DtEnd.DTEND);
135 Parameter v = dte.getParameter("VALUE");
136 if (v != null &&
137 v.getValue().equals("DATE")) {
138 String newValue = dte.getValue();
139 attachAllDayDtEnd(fnblcontent, newValue, clientType);
140 } else {
141 dte.setUtc(true);
142 com.funambol.common.pim.common.Property dteprop =
143 new com.funambol.common.pim.common.Property(dte.getValue());
144 fnblcontent.setDtEnd(dteprop);
145 detime = dte.getDate().getTime();
146 fnblcontent.setAllDay(false);
149 if (comp.getProperty(Due.DUE) != null && comp.getProperty(DtEnd.DTEND) == null) {
150 Due due = (Due) comp.getProperty(Due.DUE);
151 Parameter v = due.getParameter("VALUE");
152 if (v != null &&
153 v.getValue().equals("DATE")) {
154 String newValue = due.getValue();
155 attachAllDayDtEnd(fnblcontent, newValue, clientType);
156 } else {
157 due.setUtc(true);
158 com.funambol.common.pim.common.Property dteprop =
159 new com.funambol.common.pim.common.Property(due.getValue());
160 fnblcontent.setDtEnd(dteprop);
163 /** See if an all day event hasn't sneaked in via the back door */
164 if (detime - dstime == 86340000 || detime - dstime == 86399000) {
165 /* See the vObject minimum interoperability profile - OMA
166 * (OMA-TS-vObjectOMAProfile-V1_0-20050118-C) for information on how to
167 * correctly establish an all day event */
168 fnblcontent.setAllDay(true);
169 DtEnd dte = (DtEnd) comp.getProperty(DtEnd.DTEND);
170 dte.setUtc(false);
171 net.fortuna.ical4j.model.Date dt = new net.fortuna.ical4j.model.Date(dte.getDate().getTime());
172 dte.setDate(dt);
173 net.fortuna.ical4j.model.Date ds = new net.fortuna.ical4j.model.Date(dts.getDate().getTime());
174 dts.setDate(ds);
175 attachAllDayDtStart(fnblcontent, dts.getValue(), clientType);
176 attachAllDayDtEnd(fnblcontent, dte.getValue(), clientType);
177 } else {
178 fnblcontent.setAllDay(false);
180 if (comp.getProperty(Summary.SUMMARY) != null) {
181 /* We need to consider text encodings for this.
182 * ical2 specifies 8 bit and base64 in spec, but vcal1
183 * also allows quoted-printable (EVIL!!!). */
184 Summary summ = (Summary) comp.getProperty(Summary.SUMMARY);
185 com.funambol.common.pim.common.Property summprop =
186 new com.funambol.common.pim.common.Property();
187 // Check for encodings
188 if (summ.getParameter(Encoding.ENCODING) != null) {
189 Encoding enc = (Encoding) summ.getParameter(Encoding.ENCODING);
190 summprop.setEncoding(enc.getValue());
192 summprop.setPropertyValue(summ.getValue());
193 fnblcontent.setSummary(summprop);
195 if (comp.getProperty(Description.DESCRIPTION) != null) {
196 /* We also need to consider alternative text encoding here */
197 Description des = (Description) comp.getProperty(Description.DESCRIPTION);
198 com.funambol.common.pim.common.Property desprop =
199 new com.funambol.common.pim.common.Property();
200 // Check for encdoings
201 if (des.getParameter(Encoding.ENCODING) != null) {
202 Encoding enc = (Encoding) des.getParameter(Encoding.ENCODING);
203 desprop.setEncoding(enc.getValue());
205 desprop.setPropertyValue(des.getValue());
206 fnblcontent.setDescription(desprop);
208 if (comp.getProperty(Location.LOCATION) != null) {
209 Location loc = (Location) comp.getProperty(Location.LOCATION);
210 com.funambol.common.pim.common.Property locprop =
211 new com.funambol.common.pim.common.Property();
212 // Is our location pointing to a URL?
213 if (loc.getParameter(AltRep.ALTREP) != null) {
214 AltRep url = (AltRep) loc.getParameter(AltRep.ALTREP);
215 locprop.setValue("URL");
216 locprop.setType("VCARD");
218 locprop.setPropertyValue(loc.getValue());
219 fnblcontent.setLocation(locprop);
221 if (comp.getProperty(Priority.PRIORITY) != null) {
222 Priority pri = (Priority) comp.getProperty(Priority.PRIORITY);
223 com.funambol.common.pim.common.Property priprop =
224 new com.funambol.common.pim.common.Property(pri.getValue());
225 fnblcontent.setPriority(priprop);
226 } else if (comp.getName().equals(VToDo.VTODO)) {
227 com.funambol.common.pim.common.Property priprop =
228 new com.funambol.common.pim.common.Property("1");
229 fnblcontent.setPriority(priprop);
231 /* Slightly harder */
232 if (comp.getProperty(Transp.TRANSP) != null && fnblcontent instanceof com.funambol.common.pim.calendar.Event) {
233 Transp tsp = (Transp) comp.getProperty(Transp.TRANSP);
234 com.funambol.common.pim.common.Property tspprop =
235 new com.funambol.common.pim.common.Property();
236 if (tsp.getValue().equals(Transp.OPAQUE)) {
237 // This event WILL show up as busy
238 tspprop.setPropertyValue("0");
239 } else { // What calendar app couldn't chose between OPAQUE and TRANSPARENT?
240 tspprop.setPropertyValue("1");
242 com.funambol.common.pim.calendar.Event e =
243 (com.funambol.common.pim.calendar.Event) fnblcontent;
244 e.setTransp(tspprop);
246 if (comp.getProperty(Status.STATUS) != null &&
247 fnblcontent instanceof com.funambol.common.pim.calendar.Task) {
248 Status status = (Status) comp.getProperty(Status.STATUS);
249 com.funambol.common.pim.common.Property stat =
250 new com.funambol.common.pim.common.Property();
251 if (status.equals(Status.VTODO_COMPLETED)) {
252 stat.setPropertyValue("2");
253 } else if(status.equals(Status.VTODO_CANCELLED)) {
254 stat.setPropertyValue("4");
255 } else if (status.equals(Status.VTODO_IN_PROCESS)) {
256 stat.setPropertyValue("1");
257 } else if (status.equals(Status.VTODO_NEEDS_ACTION)) {
258 stat.setPropertyValue("0");
260 // stat.setPropertyValue(status.getValue());
261 com.funambol.common.pim.calendar.Task t =
262 (com.funambol.common.pim.calendar.Task) fnblcontent;
263 //t.setStatus(stat);
265 PropertyList attendees = comp.getProperties("ATTENDEE");
266 List<com.funambol.common.pim.calendar.Attendee> fnblattendees =
267 fnblcontent.getAttendees();
268 Iterator attendeeIterator = attendees.iterator();
269 while (attendeeIterator.hasNext()) {
270 Attendee att = (Attendee) attendeeIterator.next();
271 com.funambol.common.pim.calendar.Attendee fnblatt =
272 new com.funambol.common.pim.calendar.Attendee();
273 URI attaddr = att.getCalAddress();
274 if (attaddr.toString().length() > 0) {
275 fnblatt.setUri(attaddr.toString());
276 fnblatt.setName(att.getParameter("CN").getValue());
277 CuType ct = (CuType) att.getParameter("CUTYPE");
278 if (ct != null) {
279 if (CuType.INDIVIDUAL.equals(ct)) {
280 fnblatt.setKind(com.funambol.common.pim.calendar.Attendee.INDIVIDUAL);
281 } else if (CuType.GROUP.equals(ct)) {
282 fnblatt.setKind(com.funambol.common.pim.calendar.Attendee.GROUP);
285 fnblattendees.add(fnblatt);
288 if (comp.getProperty(Categories.CATEGORIES) != null) {
289 Categories cat = (Categories) comp.getProperty(Categories.CATEGORIES);
290 fnblcontent.getCategories().setPropertyValue(cat.getValue());
292 if (comp.getProperty(RRule.RRULE) != null) {
293 RRule rr = (RRule) comp.getProperty(RRule.RRULE);
294 Recur r = rr.getRecur();
295 /* This is where things start getting insane. Funambol wants us to
296 * find out every property of the recurrance rule and then use a custom
297 * constructor for each case! */
298 /* ical2 RULE VIOLATION: VEVENT may contain multiple RRULES... */
299 String freq = r.getFrequency();
300 System.err.println("FREQ="+freq);
301 int interval = r.getInterval();
302 int count = r.getCount();
303 boolean noEndDate = false;
304 String endDate = "";
305 if (r.getUntil() == null) {
306 noEndDate = true;
307 } else {
308 net.fortuna.ical4j.model.Date eDate = 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);
321 } catch (RecurrencePatternException re) {
322 re.printStackTrace();
323 // Send all RecurrencePatternExceptions to ground for now
325 } else if (freq.equals(Recur.HOURLY)) {
326 /* NOT SUPPORTED BY VCAL1 AND FUNAMBOL */
327 } else if (freq.equals(Recur.WEEKLY)) {
328 /* Weekly */
329 try {
330 ArrayList wkdaylist = r.getDayList();
331 for (int i = 0; i < wkdaylist.size(); i++) {
332 WeekDay wday = (WeekDay) wkdaylist.get(i);
333 String day = wday.getDay();
334 if (day.equals("SU")) {
335 dayOfWeekMask++;
336 } else if (day.equals("MO")) {
337 dayOfWeekMask = (short) (dayOfWeekMask + 2);
338 } else if (day.equals("TU")) {
339 dayOfWeekMask = (short) (dayOfWeekMask + 4);
340 } else if (day.equals("WE")) {
341 dayOfWeekMask = (short) (dayOfWeekMask + 8);
342 } else if (day.equals("TU")) {
343 dayOfWeekMask = (short) (dayOfWeekMask + 16);
344 } else if (day.equals("FR")) {
345 dayOfWeekMask = (short) (dayOfWeekMask + 32);
346 } else if (day.equals("SA")) {
347 dayOfWeekMask = (short) (dayOfWeekMask + 64);
350 RecurrencePattern rp = RecurrencePattern.getWeeklyRecurrencePattern(interval,
351 dayOfWeekMask,
352 startDate,
353 endDate,
354 noEndDate,
355 count);
356 fnblcontent.setRecurrencePattern(rp);
357 } catch (RecurrencePatternException re) {
358 re.printStackTrace();
360 } else if (freq.equals(Recur.MONTHLY)) {
361 /* Monthly - we have two sorts of month recurrance - by number day of month
362 * or day of week of month */
363 // Do we have a set week position
364 if (r.getDayList().size() > 0) {
365 // Get the weekday instance
366 WeekDay wd = (WeekDay) r.getDayList().get(0);
367 String day = wd.getDay();
368 int week = wd.getOffset();
369 Integer weekoffset = new Integer(week);
370 if (day.equals("SU")) {
371 dayOfWeekMask++;
372 } else if (day.equals("MO")) {
373 dayOfWeekMask = (short) (dayOfWeekMask + 2);
374 } else if (day.equals("TU")) {
375 dayOfWeekMask = (short) (dayOfWeekMask + 4);
376 } else if (day.equals("WE")) {
377 dayOfWeekMask = (short) (dayOfWeekMask + 8);
378 } else if (day.equals("TU")) {
379 dayOfWeekMask = (short) (dayOfWeekMask + 16);
380 } else if (day.equals("FR")) {
381 dayOfWeekMask = (short) (dayOfWeekMask + 32);
382 } else if (day.equals("SA")) {
383 dayOfWeekMask = (short) (dayOfWeekMask + 64);
385 RecurrencePattern rp = RecurrencePattern.getMonthNthRecurrencePattern(
386 r.getInterval(),
387 dayOfWeekMask,
388 weekoffset.shortValue(),
389 startDate,
390 endDate,
391 noEndDate,
392 r.getCount());
393 fnblcontent.setRecurrencePattern(rp);
394 } else {
395 try {
396 java.util.Calendar mcal = java.util.Calendar.getInstance();
397 mcal.setTime(dts.getDate());
398 Integer dayOfMonth = new Integer(mcal.get(java.util.Calendar.DAY_OF_MONTH));
399 dayOfWeekMask = dayOfMonth.shortValue();
400 RecurrencePattern rp = RecurrencePattern.getMonthlyRecurrencePattern(interval,
401 dayOfWeekMask,
402 startDate,
403 endDate,
404 noEndDate,
405 count);
406 fnblcontent.setRecurrencePattern(rp);
407 } catch (RecurrencePatternException re) {
408 re.printStackTrace();
412 } else if (freq.equals(Recur.YEARLY)) {
413 // Same as monthly recurrence basically.
414 if (r.getDayList().size() > 0) {
415 WeekDay wd = (WeekDay) r.getDayList().get(0);
416 String day = wd.getDay();
417 int week = wd.getOffset();
418 Integer weekoffset = new Integer(week);
419 Integer month = (Integer) r.getMonthList().get(0);
420 if (day.equals("SU")) {
421 dayOfWeekMask++;
422 } else if (day.equals("MO")) {
423 dayOfWeekMask = (short) (dayOfWeekMask + 2);
424 } else if (day.equals("TU")) {
425 dayOfWeekMask = (short) (dayOfWeekMask + 4);
426 } else if (day.equals("WE")) {
427 dayOfWeekMask = (short) (dayOfWeekMask + 8);
428 } else if (day.equals("TU")) {
429 dayOfWeekMask = (short) (dayOfWeekMask + 16);
430 } else if (day.equals("FR")) {
431 dayOfWeekMask = (short) (dayOfWeekMask + 32);
432 } else if (day.equals("SA")) {
433 dayOfWeekMask = (short) (dayOfWeekMask + 64);
435 RecurrencePattern rp = RecurrencePattern.getYearNthRecurrencePattern(r.getInterval(),
436 dayOfWeekMask,
437 month.shortValue(),
438 weekoffset.shortValue(),
439 startDate,
440 endDate,
441 noEndDate,
442 count);
443 } else {
444 if (r.getInterval() < 0) {
445 r.setInterval(1);
447 try {
448 RecurrencePattern rp = RecurrencePattern.getYearlyRecurrencePattern(
449 r.getInterval(),
450 (short) 0,
451 (short) 0,
452 startDate,
453 endDate,
454 noEndDate,
455 count);
456 fnblcontent.setRecurrencePattern(rp);
457 } catch (Exception ex) {
458 ex.printStackTrace();
464 com.funambol.common.pim.common.Property prodid =
465 new com.funambol.common.pim.common.Property("-//BionicMessage Funambol Connector//ical4jFunambolconvert//EN");
466 fnblcal.setProdId(prodid);
467 com.funambol.common.pim.common.Property ver =
468 new com.funambol.common.pim.common.Property("1.0");
469 fnblcal.setVersion(ver);
470 return fnblcal;
471 /* NOT YET CONVERTED: attach / attendee / exdate / exrule / geo / seq
472 * recurid */
475 public static void attachAllDayDtEnd(com.funambol.common.pim.calendar.CalendarContent e, String newValue, String clientType) {
476 if (clientType.equals("text/x-vcalendar")) {
477 newValue = newValue + "T240000";
478 com.funambol.common.pim.common.Property dteprop =
479 new com.funambol.common.pim.common.Property(newValue);
480 e.setAllDay(true);
481 e.getDtEnd().setPropertyValue(newValue);
482 } else if (clientType.equals("text/x-s4j-sife")) {
483 e.getDtEnd().setPropertyValue(newValue);
484 e.setAllDay(true);
488 public static void attachAllDayDtStart(com.funambol.common.pim.calendar.CalendarContent e, String newValue, String clientType) {
489 if (clientType.equals("text/x-vcalendar")) {
490 newValue = newValue + "T000000";
491 com.funambol.common.pim.common.Property dtsprop =
492 new com.funambol.common.pim.common.Property(newValue);
493 e.setAllDay(true);
494 e.getDtStart().setPropertyValue(newValue);
495 } else if (clientType.equals("text/x-s4j-sife")) {
496 e.getDtStart().setPropertyValue(newValue);
497 e.setAllDay(true);
501 /** Process any alarms in the event/todo. Since this functionality is optional,
502 * it is in another function
504 public static void attachAlarm(com.funambol.common.pim.calendar.CalendarContent e,
505 net.fortuna.ical4j.model.component.CalendarComponent ical4je) {
506 ComponentList alarms = null;
507 if (ical4je instanceof VEvent) {
508 VEvent ve = (VEvent) ical4je;
509 alarms = ve.getAlarms();
510 } else if (ical4je instanceof VToDo) {
511 VToDo vt = (VToDo) ical4je;
512 alarms = vt.getAlarms();
513 } else {
514 return;
516 Iterator alarmIterator = alarms.iterator();
517 while (alarmIterator.hasNext()) {
518 VAlarm va = (VAlarm) alarmIterator.next();
520 Trigger t = va.getTrigger();
521 String[] dalarmComponents = {"", "", "", ""};
522 if (va.getAction().getValue().equals("DISPLAY")) {
523 if (t.getDateTime() != null) {
524 dalarmComponents[0] = t.getDateTime().toString();
525 } else if (t.getDuration() != null) {
526 Dur dur = t.getDuration();
527 DateProperty relatedTo = null;
528 if (t.getParameter(Related.RELATED) != null &&
529 t.getParameter(Related.RELATED).equals(Related.END)) {
530 relatedTo = (DateProperty) ical4je.getProperty(DtEnd.DTEND);
531 } else {
532 relatedTo = (DateProperty) ical4je.getProperty(DtStart.DTSTART);
534 Date dt = relatedTo.getDate();
535 // Calculate a new DateTime relative to dt
536 java.util.Calendar cal = java.util.Calendar.getInstance();
537 cal.setTime(dt);
538 cal.add(java.util.Calendar.SECOND, -(dur.getSeconds()));
539 cal.add(java.util.Calendar.MINUTE, -(dur.getMinutes()));
540 cal.add(java.util.Calendar.HOUR, -(dur.getHours()));
541 cal.add(java.util.Calendar.DAY_OF_YEAR, -(dur.getDays()));
542 cal.add(java.util.Calendar.WEEK_OF_YEAR, -(dur.getWeeks()));
543 DateTime newDate = new DateTime(cal.getTime());
544 newDate.setUtc(true);
545 dalarmComponents[0] = newDate.toString();
548 StringBuffer buf = new StringBuffer();
549 for (int i = 0; i < dalarmComponents.length; i++) {
550 if (dalarmComponents[i] != null) {
551 buf.append(dalarmComponents[i]);
553 if (dalarmComponents.length != i - 1) {
554 buf.append(";");
557 e.setDAlarm(new com.funambol.common.pim.common.Property(buf.toString()));
560 /** Standalone tester */
561 public static void main(String args[]) {
562 if (args.length < 1) {
563 System.err.println("Arguments: ical4j2funambol <file.ics>");
564 return;
566 try {
567 String file = args[0];
568 FileInputStream fis = new FileInputStream(file);
569 CalendarBuilder cbuild = new CalendarBuilder();
570 Calendar ics = cbuild.build(fis);
571 com.funambol.common.pim.calendar.Calendar fnblcal =
572 ical4j2funambol.convertIcal4jToFunambolEvent(ics, "text/x-vcalendar");
573 VCalendarConverter vcc = new VCalendarConverter(null, "UTF-8");
574 VCalendar vc = vcc.calendar2vcalendar(fnblcal, true);
575 System.out.println(vc.toString());
576 } catch (Exception e) {
577 e.printStackTrace();