Sat, 14 Feb 2015 21:21:19 +0100
Correct import and other build configuration to use assertions.
1 /**
2 * Copyright (c) 2012-2013, Gerald Garcia, Timo Berger
3 *
4 * This file is part of Andoid Caldav Sync Adapter Free.
5 *
6 * Andoid Caldav Sync Adapter Free is free software: you can redistribute
7 * it and/or modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation, either version 3 of the
9 * License, or at your option any later version.
10 *
11 * Andoid Caldav Sync Adapter Free is distributed in the hope that
12 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
13 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Andoid Caldav Sync Adapter Free.
18 * If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
22 package org.gege.caldavsyncadapter.android.entities;
24 import android.database.Cursor;
25 import android.net.Uri;
26 import android.provider.CalendarContract.Attendees;
27 import android.provider.CalendarContract.Events;
28 import android.provider.CalendarContract.Reminders;
30 import net.fortuna.ical4j.model.Calendar;
31 import net.fortuna.ical4j.model.Component;
32 import net.fortuna.ical4j.model.ComponentList;
33 import net.fortuna.ical4j.model.Date;
34 import net.fortuna.ical4j.model.DateTime;
35 import net.fortuna.ical4j.model.Dur;
36 import net.fortuna.ical4j.model.ParameterList;
37 import net.fortuna.ical4j.model.Property;
38 import net.fortuna.ical4j.model.PropertyList;
39 import net.fortuna.ical4j.model.TimeZone;
40 import net.fortuna.ical4j.model.TimeZoneRegistry;
41 import net.fortuna.ical4j.model.TimeZoneRegistryFactory;
42 import net.fortuna.ical4j.model.component.VAlarm;
43 import net.fortuna.ical4j.model.component.VEvent;
44 import net.fortuna.ical4j.model.parameter.Cn;
45 import net.fortuna.ical4j.model.parameter.PartStat;
46 import net.fortuna.ical4j.model.parameter.Role;
47 import net.fortuna.ical4j.model.parameter.Rsvp;
48 import net.fortuna.ical4j.model.parameter.Value;
49 import net.fortuna.ical4j.model.property.Action;
50 import net.fortuna.ical4j.model.property.Attendee;
51 import net.fortuna.ical4j.model.property.CalScale;
52 import net.fortuna.ical4j.model.property.Clazz;
53 import net.fortuna.ical4j.model.property.Description;
54 import net.fortuna.ical4j.model.property.DtEnd;
55 import net.fortuna.ical4j.model.property.DtStart;
56 import net.fortuna.ical4j.model.property.Duration;
57 import net.fortuna.ical4j.model.property.ExDate;
58 import net.fortuna.ical4j.model.property.ExRule;
59 import net.fortuna.ical4j.model.property.Location;
60 import net.fortuna.ical4j.model.property.Organizer;
61 import net.fortuna.ical4j.model.property.ProdId;
62 import net.fortuna.ical4j.model.property.RDate;
63 import net.fortuna.ical4j.model.property.RRule;
64 import net.fortuna.ical4j.model.property.Status;
65 import net.fortuna.ical4j.model.property.Summary;
66 import net.fortuna.ical4j.model.property.Trigger;
67 import net.fortuna.ical4j.model.property.Uid;
68 import net.fortuna.ical4j.model.property.Version;
70 import org.gege.caldavsyncadapter.caldav.entities.CalendarEvent;
72 import java.net.URISyntaxException;
73 import java.text.ParseException;
75 import static junit.framework.Assert.*;
77 //import android.accounts.Account;
78 //import android.content.ContentProviderClient;
79 //import android.content.ContentValues;
80 //import android.content.SyncStats;
81 //import android.os.RemoteException;
82 //import android.provider.CalendarContract.Calendars;
83 //import org.gege.caldavsyncadapter.Event;
84 //import org.gege.caldavsyncadapter.caldav.CaldavFacade;
85 //import org.gege.caldavsyncadapter.caldav.entities.DavCalendar;
86 //import org.gege.caldavsyncadapter.syncadapter.SyncAdapter;
88 public class AndroidEvent extends org.gege.caldavsyncadapter.Event {
90 private Uri muri;
92 private Uri mAndroidCalendarUri;
94 /**
95 * the list of attendees
96 */
97 private PropertyList mAttendees = new PropertyList();
99 /**
100 * the list of reminders
101 */
102 private ComponentList mReminders = new ComponentList();
104 private Calendar mCalendar = null;
106 /* private Account mAccount = null;
107 private ContentProviderClient mProvider = null;*/
109 //public AndroidEvent(Account account, ContentProviderClient provider, Uri uri, Uri calendarUri) {
110 public AndroidEvent(Uri uri, Uri calendarUri) {
111 super();
112 this.setUri(uri);
113 /* this.mAccount = account;
114 this.mProvider = provider;*/
115 //this.setCounterpartUri(calendarUri);
116 mAndroidCalendarUri = calendarUri;
117 }
119 public Calendar getIcsEvent() {
120 return mCalendar;
121 }
123 public String getETag() {
124 String Result = "";
125 if (this.ContentValues.containsKey(ETAG))
126 Result = this.ContentValues.getAsString(ETAG);
127 return Result;
128 }
130 public void setETag(String eTag) {
131 this.ContentValues.put(ETAG, eTag);
132 }
134 public Uri getUri() {
135 return muri;
136 }
138 public void setUri(Uri uri) {
139 this.muri = uri;
140 }
142 public Uri getAndroidCalendarUri() {
143 return mAndroidCalendarUri;
144 }
146 @Override
147 public String toString() {
148 return this.getUri().toString();
149 }
151 /**
152 * reads an android event from a given cursor into {@link AndroidEvent#ContentValues}
153 *
154 * @param cur the cursor with the event
155 * @return success of this funtion
156 * @see AndroidEvent#ContentValues
157 */
158 public boolean readContentValues(Cursor cur) {
159 this.setETag(cur.getString(cur.getColumnIndex(ETAG)));
161 this.ContentValues.put(Events.EVENT_TIMEZONE, cur.getString(cur.getColumnIndex(Events.EVENT_TIMEZONE)));
162 this.ContentValues.put(Events.EVENT_END_TIMEZONE, cur.getString(cur.getColumnIndex(Events.EVENT_END_TIMEZONE)));
163 this.ContentValues.put(Events.DTSTART, cur.getLong(cur.getColumnIndex(Events.DTSTART)));
164 this.ContentValues.put(Events.DTEND, cur.getLong(cur.getColumnIndex(Events.DTEND)));
165 this.ContentValues.put(Events.ALL_DAY, cur.getLong(cur.getColumnIndex(Events.ALL_DAY)));
166 this.ContentValues.put(Events.TITLE, cur.getString(cur.getColumnIndex(Events.TITLE)));
167 this.ContentValues.put(Events.CALENDAR_ID, cur.getString(cur.getColumnIndex(Events.CALENDAR_ID)));
168 this.ContentValues.put(Events._SYNC_ID, cur.getString(cur.getColumnIndex(Events._SYNC_ID)));
169 //this.ContentValues.put(Events.SYNC_DATA1, cur.getString(cur.getColumnIndex(Events.SYNC_DATA1))); //not needed here, eTag has already been read
170 this.ContentValues.put(Events.DESCRIPTION, cur.getString(cur.getColumnIndex(Events.DESCRIPTION)));
171 this.ContentValues.put(Events.EVENT_LOCATION, cur.getString(cur.getColumnIndex(Events.EVENT_LOCATION)));
172 this.ContentValues.put(Events.ACCESS_LEVEL, cur.getInt(cur.getColumnIndex(Events.ACCESS_LEVEL)));
174 this.ContentValues.put(Events.STATUS, cur.getInt(cur.getColumnIndex(Events.STATUS)));
176 this.ContentValues.put(Events.LAST_DATE, cur.getInt(cur.getColumnIndex(Events.LAST_DATE)));
177 this.ContentValues.put(Events.DURATION, cur.getString(cur.getColumnIndex(Events.DURATION)));
179 this.ContentValues.put(Events.RDATE, cur.getString(cur.getColumnIndex(Events.RDATE)));
180 this.ContentValues.put(Events.RRULE, cur.getString(cur.getColumnIndex(Events.RRULE)));
181 this.ContentValues.put(Events.EXRULE, cur.getString(cur.getColumnIndex(Events.EXRULE)));
182 this.ContentValues.put(Events.EXDATE, cur.getString(cur.getColumnIndex(Events.EXDATE)));
183 this.ContentValues.put(Events.DIRTY, cur.getInt(cur.getColumnIndex(Events.DIRTY)));
184 this.ContentValues.put(UID, cur.getString(cur.getColumnIndex(UID)));
185 this.ContentValues.put(RAWDATA, cur.getString(cur.getColumnIndex(RAWDATA)));
187 return true;
188 }
190 /**
191 * reads the attendees from a given cursor
192 *
193 * @param cur the cursor with the attendees
194 * @return success of this function
195 * @see AndroidEvent#mAttendees
196 */
197 public boolean readAttendees(Cursor cur) {
198 Attendee attendee = null;
199 Organizer organizer = null;
200 ParameterList paraList = null;
202 String Name = "";
203 Cn cn = null;
205 String Email = "";
207 int Relationship = 0;
210 int Status = 0;
211 PartStat partstat = null;
213 int Type = 0;
214 Role role = null;
216 try {
217 while (cur.moveToNext()) {
218 Name = cur.getString(cur.getColumnIndex(Attendees.ATTENDEE_NAME));
219 Email = cur.getString(cur.getColumnIndex(Attendees.ATTENDEE_EMAIL));
220 Relationship = cur.getInt(cur.getColumnIndex(Attendees.ATTENDEE_RELATIONSHIP));
221 Type = cur.getInt(cur.getColumnIndex(Attendees.ATTENDEE_TYPE));
222 Status = cur.getInt(cur.getColumnIndex(Attendees.ATTENDEE_STATUS));
224 if (Relationship == Attendees.RELATIONSHIP_ORGANIZER) {
225 organizer = new Organizer();
226 organizer.setValue("mailto:" + Email);
227 paraList = organizer.getParameters();
228 mAttendees.add(organizer);
229 } else {
230 attendee = new Attendee();
231 attendee.setValue("mailto:" + Email);
232 paraList = attendee.getParameters();
233 mAttendees.add(attendee);
234 }
236 Rsvp rsvp = new Rsvp(true);
237 paraList.add(rsvp);
239 cn = new Cn(Name);
240 paraList.add(cn);
242 if (Status == Attendees.ATTENDEE_STATUS_INVITED)
243 partstat = new PartStat(PartStat.NEEDS_ACTION.getValue());
244 else if (Status == Attendees.ATTENDEE_STATUS_ACCEPTED)
245 partstat = new PartStat(PartStat.ACCEPTED.getValue());
246 else if (Status == Attendees.ATTENDEE_STATUS_DECLINED)
247 partstat = new PartStat(PartStat.DECLINED.getValue());
248 else if (Status == Attendees.ATTENDEE_STATUS_NONE)
249 partstat = new PartStat(PartStat.COMPLETED.getValue());
250 else if (Status == Attendees.ATTENDEE_STATUS_TENTATIVE)
251 partstat = new PartStat(PartStat.TENTATIVE.getValue());
252 else
253 partstat = new PartStat(PartStat.NEEDS_ACTION.getValue());
254 paraList.add(partstat);
256 if (Type == Attendees.TYPE_OPTIONAL)
257 role = new Role(Role.OPT_PARTICIPANT.getValue());
258 else if (Type == Attendees.TYPE_NONE)
259 role = new Role(Role.NON_PARTICIPANT.getValue()); //regular participants in android are non required?
260 else if (Type == Attendees.TYPE_REQUIRED)
261 role = new Role(Role.REQ_PARTICIPANT.getValue());
262 else
263 role = new Role(Role.NON_PARTICIPANT.getValue());
264 paraList.add(role);
265 }
267 } catch (URISyntaxException e) {
268 e.printStackTrace();
269 }
270 return true;
271 }
273 /**
274 * reads the reminders from a given cursor
275 *
276 * @param cur the cursor with the reminders
277 * @return success of this function
278 */
279 public boolean readReminder(Cursor cur) {
280 int Method;
281 int Minutes;
282 VAlarm reminder;
283 while (cur.moveToNext()) {
284 reminder = new VAlarm();
285 Method = cur.getInt(cur.getColumnIndex(Reminders.METHOD));
286 Minutes = cur.getInt(cur.getColumnIndex(Reminders.MINUTES)) * -1;
289 Dur dur = new Dur(0, 0, Minutes, 0);
290 Trigger tri = new Trigger(dur);
291 Value val = new Value(Duration.DURATION);
292 tri.getParameters().add(val);
293 reminder.getProperties().add(tri);
295 Description desc = new Description();
296 desc.setValue("caldavsyncadapter standard description");
297 reminder.getProperties().add(desc);
300 if (Method == Reminders.METHOD_EMAIL)
301 reminder.getProperties().add(Action.EMAIL);
302 else
303 reminder.getProperties().add(Action.DISPLAY);
305 this.mReminders.add(reminder);
306 }
307 return true;
308 }
310 /**
311 * generates a new ics-file.
312 * uses {@link AndroidEvent#ContentValues} as source.
313 * this should only be used when a new event has been generated within android.
314 *
315 * @param strUid the UID for this event. example: UID:e6be67c6-eff0-44f8-a1a0-6c2cb1029944-caldavsyncadapter
316 * @return success of the function
317 * @see CalendarEvent#fetchBody()
318 */
319 public boolean createIcs(String strUid) {
320 boolean Result = false;
321 TimeZone timeZone = null;
322 //if (obj == null) throw new AssertionError("Null object");
323 assertNotNull(Thread.currentThread().getContextClassLoader());
324 TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry();
325 //TODO: do not simply create the ics-file new. take into account the RAWDATA if available
326 /*
327 * dtstart=1365598800000
328 * dtend=1365602400000
329 * eventTimezone=Europe/Berlin
330 * eventEndTimezone=null
331 * duration=null
332 * allDay=0
333 * rrule=null
334 * rdate=null
335 * exrule=null
336 * exdate=null
337 * title=Einurlner Termin
338 * description=null
339 * eventLocation=null
340 * accessLevel=0
341 * eventStatus=0
342 *
343 * calendar_id=4
344 * lastDate=-197200128
345 * sync_data1=null
346 * _sync_id=null
347 * dirty=1
348 */
350 try {
351 mCalendar = new Calendar();
352 PropertyList propCalendar = mCalendar.getProperties();
353 propCalendar.add(new ProdId("-//Ben Fortuna//iCal4j 1.0//EN"));
354 propCalendar.add(Version.VERSION_2_0);
355 propCalendar.add(CalScale.GREGORIAN);
357 VEvent event = new VEvent();
358 mCalendar.getComponents().add(event);
359 PropertyList propEvent = event.getProperties();
361 // DTSTAMP -> is created by new VEvent() automatical
362 //na
364 // CREATED
365 //na
367 // LAST-MODIFIED
368 //na
370 // SEQUENCE
371 //na
373 // DTSTART
374 long lngStart = this.ContentValues.getAsLong(Events.DTSTART);
375 String strTZStart = this.ContentValues.getAsString(Events.EVENT_TIMEZONE);
376 boolean allDay = this.ContentValues.getAsBoolean(Events.ALL_DAY);
377 if (lngStart > 0) {
378 DtStart dtStart = new DtStart();
379 if (allDay) {
380 Date dateStart = new Date();
381 dateStart.setTime(lngStart);
382 dtStart.setDate(dateStart);
383 } else {
384 DateTime datetimeStart = new DateTime();
385 datetimeStart.setTime(lngStart);
386 dtStart.setDate(datetimeStart);
388 timeZone = registry.getTimeZone(strTZStart);
389 if (timeZone == null) {
390 java.util.TimeZone systemTimeZone = TimeZone.getTimeZone(strTZStart);
391 if (systemTimeZone == null) {
392 systemTimeZone = TimeZone.getDefault();
393 }
394 timeZone = registry.getTimeZone(systemTimeZone.getID());
395 }
396 dtStart.setTimeZone(timeZone);
398 // no timezone information for allDay events
399 mCalendar.getComponents().add(timeZone.getVTimeZone());
400 }
401 propEvent.add(dtStart);
402 }
404 // DTEND
405 long lngEnd = this.ContentValues.getAsLong(Events.DTEND);
406 String strTZEnd = this.ContentValues.getAsString(Events.EVENT_END_TIMEZONE);
407 if (strTZEnd == null)
408 strTZEnd = strTZStart;
409 if (lngEnd > 0) {
410 DtEnd dtEnd = new DtEnd();
411 if (allDay) {
412 Date dateEnd = new Date();
413 dateEnd.setTime(lngEnd);
414 dtEnd.setDate(dateEnd);
415 } else {
416 DateTime datetimeEnd = new DateTime();
417 datetimeEnd.setTime(lngEnd);
418 dtEnd.setDate(datetimeEnd);
419 if (strTZEnd != null)
420 timeZone = registry.getTimeZone(strTZEnd);
421 dtEnd.setTimeZone(timeZone);
422 }
423 propEvent.add(dtEnd);
424 }
426 // DURATION
427 if (this.ContentValues.containsKey(Events.DURATION)) {
428 String strDuration = this.ContentValues.getAsString(Events.DURATION);
429 if (strDuration != null) {
430 Duration duration = new Duration();
431 duration.setValue(strDuration);
433 propEvent.add(duration);
434 }
435 }
437 //RRULE
438 if (this.ContentValues.containsKey(Events.RRULE)) {
439 String strRrule = this.ContentValues.getAsString(Events.RRULE);
440 if (strRrule != null) {
441 if (!strRrule.equals("")) {
442 RRule rrule = new RRule();
443 rrule.setValue(strRrule);
444 propEvent.add(rrule);
445 }
446 }
447 }
449 //RDATE
450 if (this.ContentValues.containsKey(Events.RDATE)) {
451 String strRdate = this.ContentValues.getAsString(Events.RDATE);
452 if (strRdate != null) {
453 if (!strRdate.equals("")) {
454 RDate rdate = new RDate();
455 rdate.setValue(strRdate);
456 propEvent.add(rdate);
457 }
458 }
459 }
461 //EXRULE
462 if (this.ContentValues.containsKey(Events.EXRULE)) {
463 String strExrule = this.ContentValues.getAsString(Events.EXRULE);
464 if (strExrule != null) {
465 if (!strExrule.equals("")) {
466 ExRule exrule = new ExRule();
467 exrule.setValue(strExrule);
468 propEvent.add(exrule);
469 }
470 }
471 }
473 //EXDATE
474 if (this.ContentValues.containsKey(Events.EXDATE)) {
475 String strExdate = this.ContentValues.getAsString(Events.EXDATE);
476 if (strExdate != null) {
477 if (!strExdate.equals("")) {
478 ExDate exdate = new ExDate();
479 exdate.setValue(strExdate);
480 propEvent.add(exdate);
481 }
482 }
483 }
485 //SUMMARY
486 if (this.ContentValues.containsKey(Events.TITLE)) {
487 String strTitle = this.ContentValues.getAsString(Events.TITLE);
488 if (strTitle != null) {
489 Summary summary = new Summary(strTitle);
490 propEvent.add(summary);
491 }
492 }
494 //DESCIPTION
495 if (this.ContentValues.containsKey(Events.DESCRIPTION)) {
496 String strDescription = this.ContentValues.getAsString(Events.DESCRIPTION);
497 if (strDescription != null) {
498 if (!strDescription.equals("")) {
499 Description description = new Description(strDescription);
500 propEvent.add(description);
501 }
502 }
503 }
505 //LOCATION
506 if (this.ContentValues.containsKey(Events.EVENT_LOCATION)) {
507 String strLocation = this.ContentValues.getAsString(Events.EVENT_LOCATION);
508 if (strLocation != null) {
509 if (!strLocation.equals("")) {
510 Location location = new Location(strLocation);
511 propEvent.add(location);
512 }
513 }
514 }
516 //CLASS / ACCESS_LEVEL
517 if (this.ContentValues.containsKey(Events.ACCESS_LEVEL)) {
518 int accessLevel = this.ContentValues.getAsInteger(Events.ACCESS_LEVEL);
519 Clazz clazz = new Clazz();
520 if (accessLevel == Events.ACCESS_PUBLIC)
521 clazz.setValue(Clazz.PUBLIC.getValue());
522 else if (accessLevel == Events.ACCESS_PRIVATE)
523 clazz.setValue(Clazz.PRIVATE.getValue());
524 else if (accessLevel == Events.ACCESS_CONFIDENTIAL)
525 clazz.setValue(Clazz.CONFIDENTIAL.getValue());
526 else
527 clazz.setValue(Clazz.PUBLIC.getValue());
529 propEvent.add(clazz);
530 }
532 //STATUS
533 if (this.ContentValues.containsKey(Events.STATUS)) {
534 int intStatus = this.ContentValues.getAsInteger(Events.STATUS);
535 if (intStatus > -1) {
536 Status status = new Status();
537 if (intStatus == Events.STATUS_CANCELED)
538 status.setValue(Status.VEVENT_CANCELLED.getValue());
539 else if (intStatus == Events.STATUS_CONFIRMED)
540 status.setValue(Status.VEVENT_CONFIRMED.getValue());
541 else if (intStatus == Events.STATUS_TENTATIVE)
542 status.setValue(Status.VEVENT_TENTATIVE.getValue());
544 propEvent.add(status);
545 }
546 }
548 //UID
549 Uid uid = new Uid(strUid);
550 propEvent.add(uid);
552 // Attendees
553 if (mAttendees.size() > 0) {
554 for (Object objProp : mAttendees) {
555 Property prop = (Property) objProp;
556 propEvent.add(prop);
557 }
558 }
560 // Reminders
561 if (mReminders.size() > 0) {
562 for (Object objComp : mReminders) {
563 VAlarm com = (VAlarm) objComp;
564 event.getAlarms().add(com);
565 }
566 }
568 } catch (ParseException e) {
569 e.printStackTrace();
570 }
572 return Result;
573 }
575 /**
576 * marks the android event as already handled
577 * @return
578 * @see AndroidEvent#cInternalTag
579 * @see SyncAdapter#synchroniseEvents(CaldavFacade, Account, ContentProviderClient, Uri, DavCalendar, SyncStats)
580 * @throws RemoteException
581 */
582 /* public boolean tagAndroidEvent() throws RemoteException {
584 ContentValues values = new ContentValues();
585 values.put(Event.INTERNALTAG, 1);
587 int RowCount = this.mProvider.update(asSyncAdapter(this.getUri(), this.mAccount.name, this.mAccount.type), values, null, null);
588 //Log.e(TAG,"Rows updated: " + RowCount.toString());
590 return (RowCount == 1);
591 }*/
593 /* private static Uri asSyncAdapter(Uri uri, String account, String accountType) {
594 return uri.buildUpon()
595 .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true")
596 .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
597 .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
598 }*/
599 }