2015-10-14 16:19:59 +00:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2013 – 2015 Ricki Hirner (bitfire web engineering).
|
|
|
|
|
* All rights reserved. This program and the accompanying materials
|
|
|
|
|
* are made available under the terms of the GNU Public License v3.0
|
|
|
|
|
* which accompanies this distribution, and is available at
|
|
|
|
|
* http://www.gnu.org/licenses/gpl.html
|
|
|
|
|
*/
|
|
|
|
|
|
2017-02-27 12:57:57 +00:00
|
|
|
|
package com.etesync.syncadapter.resource;
|
2015-10-14 16:19:59 +00:00
|
|
|
|
|
2015-10-18 22:04:58 +00:00
|
|
|
|
import android.annotation.TargetApi;
|
2015-10-14 16:19:59 +00:00
|
|
|
|
import android.content.ContentProviderOperation;
|
|
|
|
|
import android.content.ContentValues;
|
2017-02-10 16:56:41 +00:00
|
|
|
|
import android.database.Cursor;
|
2017-03-23 16:53:31 +00:00
|
|
|
|
import android.net.Uri;
|
2015-10-15 11:46:19 +00:00
|
|
|
|
import android.os.Build;
|
2015-10-14 16:19:59 +00:00
|
|
|
|
import android.os.RemoteException;
|
|
|
|
|
import android.provider.CalendarContract;
|
2015-10-14 19:45:19 +00:00
|
|
|
|
import android.provider.CalendarContract.Events;
|
2016-02-24 22:08:19 +00:00
|
|
|
|
import android.support.annotation.NonNull;
|
2017-01-02 19:39:10 +00:00
|
|
|
|
import android.text.TextUtils;
|
2015-10-14 16:19:59 +00:00
|
|
|
|
|
2017-03-23 16:53:31 +00:00
|
|
|
|
import com.etesync.syncadapter.App;
|
2017-04-07 08:41:21 +00:00
|
|
|
|
import com.etesync.syncadapter.Constants;
|
|
|
|
|
|
|
|
|
|
import net.fortuna.ical4j.model.property.ProdId;
|
2017-03-23 16:53:31 +00:00
|
|
|
|
|
2017-01-02 19:39:10 +00:00
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.util.logging.Level;
|
2015-10-14 19:45:19 +00:00
|
|
|
|
|
2015-10-14 16:19:59 +00:00
|
|
|
|
import at.bitfire.ical4android.AndroidCalendar;
|
|
|
|
|
import at.bitfire.ical4android.AndroidEvent;
|
|
|
|
|
import at.bitfire.ical4android.AndroidEventFactory;
|
|
|
|
|
import at.bitfire.ical4android.CalendarStorageException;
|
|
|
|
|
import at.bitfire.ical4android.Event;
|
2017-01-02 19:39:10 +00:00
|
|
|
|
import at.bitfire.vcard4android.ContactsStorageException;
|
2017-02-10 16:56:41 +00:00
|
|
|
|
import lombok.Cleanup;
|
2015-10-14 16:19:59 +00:00
|
|
|
|
import lombok.Getter;
|
|
|
|
|
import lombok.Setter;
|
|
|
|
|
|
2015-10-18 22:04:58 +00:00
|
|
|
|
@TargetApi(17)
|
2015-10-14 16:19:59 +00:00
|
|
|
|
public class LocalEvent extends AndroidEvent implements LocalResource {
|
2017-04-07 08:41:21 +00:00
|
|
|
|
static {
|
|
|
|
|
Event.prodId = new ProdId(Constants.PRODID_BASE + "//ical4android ical4j/2.x");
|
|
|
|
|
}
|
2015-10-14 19:45:19 +00:00
|
|
|
|
static final String COLUMN_ETAG = CalendarContract.Events.SYNC_DATA1,
|
2017-01-02 19:39:10 +00:00
|
|
|
|
COLUMN_UID = Build.VERSION.SDK_INT >= 17 ? Events.UID_2445 : Events.SYNC_DATA2,
|
|
|
|
|
COLUMN_SEQUENCE = CalendarContract.Events.SYNC_DATA3;
|
2015-10-14 16:19:59 +00:00
|
|
|
|
|
2017-03-23 16:53:31 +00:00
|
|
|
|
private boolean saveAsDirty = false; // When true, the resource will be saved as dirty
|
|
|
|
|
|
2017-01-02 19:39:10 +00:00
|
|
|
|
@Getter
|
|
|
|
|
protected String fileName;
|
|
|
|
|
@Getter
|
|
|
|
|
@Setter
|
|
|
|
|
protected String eTag;
|
2015-10-14 16:19:59 +00:00
|
|
|
|
|
2016-09-24 20:23:25 +00:00
|
|
|
|
public boolean weAreOrganizer = true;
|
|
|
|
|
|
2015-10-14 19:45:19 +00:00
|
|
|
|
public LocalEvent(@NonNull AndroidCalendar calendar, Event event, String fileName, String eTag) {
|
2015-10-14 16:19:59 +00:00
|
|
|
|
super(calendar, event);
|
|
|
|
|
this.fileName = fileName;
|
|
|
|
|
this.eTag = eTag;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-14 19:45:19 +00:00
|
|
|
|
protected LocalEvent(@NonNull AndroidCalendar calendar, long id, ContentValues baseInfo) {
|
2015-10-14 16:19:59 +00:00
|
|
|
|
super(calendar, id, baseInfo);
|
2015-10-14 19:45:19 +00:00
|
|
|
|
if (baseInfo != null) {
|
|
|
|
|
fileName = baseInfo.getAsString(Events._SYNC_ID);
|
|
|
|
|
eTag = baseInfo.getAsString(COLUMN_ETAG);
|
|
|
|
|
}
|
2015-10-14 16:19:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-02 19:39:10 +00:00
|
|
|
|
@Override
|
|
|
|
|
public String getContent() throws IOException, ContactsStorageException, CalendarStorageException {
|
|
|
|
|
App.log.log(Level.FINE, "Preparing upload of event " + getFileName(), getEvent());
|
|
|
|
|
|
|
|
|
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
|
|
|
getEvent().write(os);
|
|
|
|
|
|
|
|
|
|
return os.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean isLocalOnly() {
|
|
|
|
|
return TextUtils.isEmpty(getETag());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String getUuid() {
|
|
|
|
|
// Now the same
|
|
|
|
|
return getFileName();
|
|
|
|
|
}
|
2015-10-14 16:19:59 +00:00
|
|
|
|
|
|
|
|
|
/* process LocalEvent-specific fields */
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void populateEvent(ContentValues values) {
|
|
|
|
|
super.populateEvent(values);
|
2015-10-14 19:45:19 +00:00
|
|
|
|
fileName = values.getAsString(Events._SYNC_ID);
|
2015-10-14 16:19:59 +00:00
|
|
|
|
eTag = values.getAsString(COLUMN_ETAG);
|
|
|
|
|
event.uid = values.getAsString(COLUMN_UID);
|
2015-10-14 19:45:19 +00:00
|
|
|
|
|
2015-10-19 14:44:37 +00:00
|
|
|
|
event.sequence = values.getAsInteger(COLUMN_SEQUENCE);
|
2017-04-18 21:53:25 +00:00
|
|
|
|
if (Build.VERSION.SDK_INT >= 17) {
|
|
|
|
|
Integer isOrganizer = values.getAsInteger(Events.IS_ORGANIZER);
|
|
|
|
|
weAreOrganizer = isOrganizer != null && isOrganizer != 0;
|
|
|
|
|
} else {
|
2016-10-04 14:12:44 +00:00
|
|
|
|
String organizer = values.getAsString(Events.ORGANIZER);
|
|
|
|
|
weAreOrganizer = organizer == null || organizer.equals(calendar.account.name);
|
|
|
|
|
}
|
2015-10-14 16:19:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void buildEvent(Event recurrence, ContentProviderOperation.Builder builder) {
|
|
|
|
|
super.buildEvent(recurrence, builder);
|
2015-10-14 19:45:19 +00:00
|
|
|
|
|
|
|
|
|
boolean buildException = recurrence != null;
|
|
|
|
|
Event eventToBuild = buildException ? recurrence : event;
|
|
|
|
|
|
2017-01-02 19:39:10 +00:00
|
|
|
|
builder.withValue(COLUMN_UID, event.uid)
|
2015-10-14 19:45:19 +00:00
|
|
|
|
.withValue(COLUMN_SEQUENCE, eventToBuild.sequence)
|
2017-03-23 16:53:31 +00:00
|
|
|
|
.withValue(CalendarContract.Events.DIRTY, saveAsDirty ? 1 : 0)
|
2015-10-14 19:45:19 +00:00
|
|
|
|
.withValue(CalendarContract.Events.DELETED, 0);
|
|
|
|
|
|
|
|
|
|
if (buildException)
|
|
|
|
|
builder.withValue(Events.ORIGINAL_SYNC_ID, fileName);
|
|
|
|
|
else
|
2017-01-02 19:39:10 +00:00
|
|
|
|
builder.withValue(Events._SYNC_ID, fileName)
|
2015-10-14 19:45:19 +00:00
|
|
|
|
.withValue(COLUMN_ETAG, eTag);
|
2015-10-14 16:19:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-23 16:53:31 +00:00
|
|
|
|
public Uri addAsDirty() throws CalendarStorageException {
|
|
|
|
|
saveAsDirty = true;
|
|
|
|
|
return this.add();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Uri updateAsDirty(Event event) throws CalendarStorageException {
|
|
|
|
|
saveAsDirty = true;
|
|
|
|
|
return this.update(event);
|
|
|
|
|
}
|
2015-10-14 16:19:59 +00:00
|
|
|
|
|
|
|
|
|
/* custom queries */
|
|
|
|
|
|
2017-02-10 16:56:41 +00:00
|
|
|
|
public void prepareForUpload() throws CalendarStorageException {
|
2015-10-14 16:19:59 +00:00
|
|
|
|
try {
|
2017-02-10 16:56:41 +00:00
|
|
|
|
String uid = null;
|
2017-02-17 08:55:01 +00:00
|
|
|
|
@Cleanup Cursor c = calendar.provider.query(eventSyncURI(), new String[] { COLUMN_UID }, null, null, null);
|
2017-02-10 16:56:41 +00:00
|
|
|
|
if (c.moveToNext())
|
|
|
|
|
uid = c.getString(0);
|
|
|
|
|
if (uid == null)
|
|
|
|
|
uid = App.getUidGenerator().generateUid().getValue();
|
|
|
|
|
|
|
|
|
|
final String newFileName = uid;
|
2015-10-14 16:19:59 +00:00
|
|
|
|
|
|
|
|
|
ContentValues values = new ContentValues(2);
|
2015-10-14 19:45:19 +00:00
|
|
|
|
values.put(Events._SYNC_ID, newFileName);
|
2015-10-14 16:19:59 +00:00
|
|
|
|
values.put(COLUMN_UID, uid);
|
|
|
|
|
calendar.provider.update(eventSyncURI(), values, null, null);
|
|
|
|
|
|
|
|
|
|
fileName = newFileName;
|
|
|
|
|
if (event != null)
|
|
|
|
|
event.uid = uid;
|
|
|
|
|
|
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
|
throw new CalendarStorageException("Couldn't update UID", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void clearDirty(String eTag) throws CalendarStorageException {
|
|
|
|
|
try {
|
|
|
|
|
ContentValues values = new ContentValues(2);
|
|
|
|
|
values.put(CalendarContract.Events.DIRTY, 0);
|
|
|
|
|
values.put(COLUMN_ETAG, eTag);
|
2015-10-14 19:45:19 +00:00
|
|
|
|
if (event != null)
|
|
|
|
|
values.put(COLUMN_SEQUENCE, event.sequence);
|
2015-10-14 16:19:59 +00:00
|
|
|
|
calendar.provider.update(eventSyncURI(), values, null, null);
|
|
|
|
|
|
|
|
|
|
this.eTag = eTag;
|
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
|
throw new CalendarStorageException("Couldn't update UID", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static class Factory implements AndroidEventFactory {
|
|
|
|
|
static final Factory INSTANCE = new Factory();
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public AndroidEvent newInstance(AndroidCalendar calendar, long id, ContentValues baseInfo) {
|
|
|
|
|
return new LocalEvent(calendar, id, baseInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public AndroidEvent newInstance(AndroidCalendar calendar, Event event) {
|
|
|
|
|
return new LocalEvent(calendar, event, null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public AndroidEvent[] newArray(int size) {
|
|
|
|
|
return new LocalEvent[size];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|