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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* 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)
}
}