You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
etesync-android/app/src/main/java/com/etesync/syncadapter/resource/LocalEvent.kt

191 lines
6.3 KiB

/*
* 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
*/
package com.etesync.syncadapter.resource
import android.content.ContentProviderOperation
import android.content.ContentValues
import android.net.Uri
import android.provider.CalendarContract
import android.provider.CalendarContract.Events
import android.text.TextUtils
import at.bitfire.ical4android.*
import at.bitfire.ical4android.Ical4Android.ical4jVersion
import com.etesync.syncadapter.Constants
import com.etesync.syncadapter.log.Logger
import net.fortuna.ical4j.model.component.VAlarm
import net.fortuna.ical4j.model.property.Action
import net.fortuna.ical4j.model.property.ProdId
import java.io.ByteArrayOutputStream
import java.util.*
import java.util.logging.Level
class LocalEvent : AndroidEvent, LocalResource<Event> {
companion object {
init {
ICalendar.prodId = ProdId(Constants.PRODID_BASE + " ical4j/" + ical4jVersion)
}
internal const val COLUMN_ETAG = CalendarContract.Events.SYNC_DATA1
internal const val COLUMN_UID = Events.UID_2445
internal const val COLUMN_SEQUENCE = CalendarContract.Events.SYNC_DATA3
}
private var saveAsDirty = false // When true, the resource will be saved as dirty
override var fileName: String? = null
var eTag: String? = null
var weAreOrganizer = true
override val content: String
get() {
Logger.log.log(Level.FINE, "Preparing upload of event $fileName} ${event}")
val os = ByteArrayOutputStream()
event?.write(os)
return os.toString()
}
override val isLocalOnly: Boolean
get() = TextUtils.isEmpty(eTag)
override// Now the same
val uuid: String?
get() = event?.uid
constructor(calendar: AndroidCalendar<*>, event: Event, fileName: String?, eTag: String?) : super(calendar, event) {
this.fileName = fileName
this.eTag = eTag
}
protected constructor(calendar: AndroidCalendar<*>, baseInfo: ContentValues) : super(calendar, baseInfo) {
fileName = baseInfo.getAsString(Events._SYNC_ID)
eTag = baseInfo.getAsString(COLUMN_ETAG)
}
/* process LocalEvent-specific fields */
override fun populateEvent(row: ContentValues, groupScheduled: Boolean) {
super.populateEvent(row, groupScheduled)
fileName = row.getAsString(Events._SYNC_ID)
eTag = row.getAsString(COLUMN_ETAG)
event?.uid = row.getAsString(COLUMN_UID)
event?.sequence = row.getAsInteger(COLUMN_SEQUENCE)
val isOrganizer = row.getAsInteger(Events.IS_ORGANIZER)
weAreOrganizer = isOrganizer != null && isOrganizer != 0
}
override fun buildEvent(recurrence: Event?, builder: ContentProviderOperation.Builder) {
super.buildEvent(recurrence, builder)
val buildException = recurrence != null
val eventToBuild = if (buildException) recurrence else event
builder.withValue(COLUMN_UID, event?.uid)
.withValue(COLUMN_SEQUENCE, eventToBuild?.sequence)
.withValue(CalendarContract.Events.DIRTY, if (saveAsDirty) 1 else 0)
.withValue(CalendarContract.Events.DELETED, 0)
if (buildException)
builder.withValue(Events.ORIGINAL_SYNC_ID, fileName)
else
builder.withValue(Events._SYNC_ID, fileName)
.withValue(COLUMN_ETAG, eTag)
}
override fun insertReminder(batch: BatchOperation, idxEvent: Int, alarm: VAlarm) {
// We only support DISPLAY and AUDIO alarms so modify when inserting
val action = alarm.action
val modifiedAlarm = when (action?.value) {
Action.DISPLAY.value,
Action.AUDIO.value -> alarm
Action.EMAIL.value -> {
val tmp = VAlarm(alarm.trigger?.duration)
tmp.properties += Action.DISPLAY
tmp.properties += alarm.description
tmp
}
else -> alarm
}
super.insertReminder(batch, idxEvent, modifiedAlarm)
}
fun addAsDirty(): Uri {
saveAsDirty = true
return this.add()
}
fun updateAsDirty(event: Event): Uri {
saveAsDirty = true
return this.update(event)
}
/* custom queries */
override fun legacyPrepareForUpload(fileName_: String?) {
var uid: String? = null
val c = calendar.provider.query(eventSyncURI(), arrayOf(COLUMN_UID), null, null, null)
if (c.moveToNext())
uid = c.getString(0)
if (uid == null)
uid = UUID.randomUUID().toString()
c.close()
val fileName = fileName_ ?: uid
val values = ContentValues(2)
values.put(Events._SYNC_ID, fileName)
values.put(COLUMN_UID, uid)
calendar.provider.update(eventSyncURI(), values, null, null)
this.fileName = fileName
val event = this.event
if (event != null)
event.uid = uid
}
override fun prepareForUpload(fileName: String, uid: String) {
val values = ContentValues(2)
values.put(Events._SYNC_ID, fileName)
values.put(COLUMN_UID, uid)
calendar.provider.update(eventSyncURI(), values, null, null)
event?.uid = uid
this.fileName = fileName
}
override fun resetDeleted() {
val values = ContentValues(1)
values.put(CalendarContract.Events.DELETED, 0)
calendar.provider.update(eventSyncURI(), values, null, null)
}
override fun clearDirty(eTag: String?) {
val values = ContentValues(2)
values.put(CalendarContract.Events.DIRTY, 0)
if (eTag != null) {
values.put(COLUMN_ETAG, eTag)
}
if (event != null)
values.put(COLUMN_SEQUENCE, event?.sequence)
calendar.provider.update(eventSyncURI(), values, null, null)
this.eTag = eTag
}
object Factory: AndroidEventFactory<LocalEvent> {
override fun fromProvider(calendar: AndroidCalendar<AndroidEvent>, values: ContentValues): LocalEvent =
LocalEvent(calendar, values)
}
}