Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,14 @@ class AndroidCalendarTest {
@Test
fun testInsertColors() {
AndroidCalendar.insertColors(provider, testAccount)
assertEquals(Css3Color.values().size, countColors(testAccount))
assertEquals(Css3Color.entries.size, countColors(testAccount))
}

@Test
fun testInsertColors_AlreadyThere() {
AndroidCalendar.insertColors(provider, testAccount)
AndroidCalendar.insertColors(provider, testAccount)
assertEquals(Css3Color.values().size, countColors(testAccount))
assertEquals(Css3Color.entries.size, countColors(testAccount))
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,6 @@ import java.net.URI
import java.time.Duration
import java.time.Period
import java.util.logging.Logger
import kotlin.collections.Map
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.emptyMap
import kotlin.collections.first
import kotlin.collections.firstOrNull
import kotlin.collections.iterator
import kotlin.collections.mapOf
import kotlin.collections.plusAssign

class AndroidEventTest {
Expand Down Expand Up @@ -126,6 +118,25 @@ class AndroidEventTest {
}


@Test
fun testConstructor_ContentValues() {
val e = AndroidEvent(
calendar, contentValuesOf(
Events._ID to 123,
Events._SYNC_ID to "some-ical.ics",
AndroidEvent.COLUMN_ETAG to "some-etag",
AndroidEvent.COLUMN_SCHEDULE_TAG to "some-schedule-tag",
AndroidEvent.COLUMN_FLAGS to 45
)
)
assertEquals(123L, e.id)
assertEquals("some-ical.ics", e.syncId)
assertEquals("some-etag", e.eTag)
assertEquals("some-schedule-tag", e.scheduleTag)
assertEquals(45, e.flags)
}


/**
* buildEvent() BASIC TEST MATRIX:
*
Expand Down Expand Up @@ -1522,6 +1533,87 @@ class AndroidEventTest {
).event!!
}

@Test
fun testPopulateEvent_Uid_iCalUid() {
populateEvent(
true,
extendedProperties = mapOf(
AndroidEvent.EXTNAME_ICAL_UID to "[email protected]"
)
).let { result ->
assertEquals("[email protected]", result.uid)
}
}

@Test
fun testPopulateEvent_Uid_UID_2445() {
populateEvent(true) {
put(Events.UID_2445, "[email protected]")
}.let { result ->
assertEquals("[email protected]", result.uid)
}
}

@Test
fun testPopulateEvent_Uid_UID_2445_and_iCalUid() {
populateEvent(
true,
extendedProperties = mapOf(
AndroidEvent.EXTNAME_ICAL_UID to "[email protected]"
)
) {
put(Events.UID_2445, "[email protected]")
}.let { result ->
assertEquals("[email protected]", result.uid)
}
}


@Test
fun testPopulateEvent_Sequence_Int() {
populateEvent(true, asSyncAdapter = true) {
put(AndroidEvent.COLUMN_SEQUENCE, 5)
}.let { result ->
assertEquals(5, result.sequence)
}
}

@Test
fun testPopulateEvent_Sequence_Null() {
populateEvent(true, asSyncAdapter = true) {
putNull(AndroidEvent.COLUMN_SEQUENCE)
}.let { result ->
assertNull(result.sequence)
}
}

@Test
fun testPopulateEvent_IsOrganizer_False() {
populateEvent(true, asSyncAdapter = true) {
put(Events.IS_ORGANIZER, "0")
}.let { result ->
assertFalse(result.isOrganizer!!)
}
}

@Test
fun testPopulateEvent_IsOrganizer_Null() {
populateEvent(true, asSyncAdapter = true) {
putNull(Events.IS_ORGANIZER)
}.let { result ->
assertNull(result.isOrganizer)
}
}

@Test
fun testPopulateEvent_IsOrganizer_True() {
populateEvent(true, asSyncAdapter = true) {
put(Events.IS_ORGANIZER, "1")
}.let { result ->
assertTrue(result.isOrganizer!!)
}
}

@Test
fun testPopulateEvent_NonAllDay_NonRecurring() {
populateEvent(false) {
Expand Down Expand Up @@ -1886,39 +1978,6 @@ class AndroidEventTest {
}
}

@Test
fun testPopulateEvent_Uid_iCalUid() {
populateEvent(
true,
extendedProperties = mapOf(
AndroidEvent.EXTNAME_ICAL_UID to "[email protected]"
)
).let { result ->
assertEquals("[email protected]", result.uid)
}
}

@Test
fun testPopulateEvent_Uid_UID_2445() {
populateEvent(true) {
put(Events.UID_2445, "[email protected]")
}.let { result ->
assertEquals("[email protected]", result.uid)
}
}

@Test
fun testPopulateEvent_Uid_UID_2445_and_iCalUid() {
populateEvent(true,
extendedProperties = mapOf(
AndroidEvent.EXTNAME_ICAL_UID to "[email protected]"
)) {
put(Events.UID_2445, "[email protected]")
}.let { result ->
assertEquals("[email protected]", result.uid)
}
}


private fun populateReminder(destinationCalendar: TestCalendar = calendar, builder: ContentValues.() -> Unit): VAlarm? {
populateEvent(true, destinationCalendar = destinationCalendar, insertCallback = { id ->
Expand Down Expand Up @@ -2340,7 +2399,6 @@ class AndroidEventTest {
}



@Test
fun testUpdateEvent() {
// add test event without reminder
Expand Down Expand Up @@ -2480,4 +2538,4 @@ class AndroidEventTest {
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import at.bitfire.ical4android.AndroidCalendar
import at.bitfire.ical4android.AndroidCalendarFactory

class TestCalendar(
account: Account,
providerClient: ContentProviderClient,
id: Long
account: Account,
providerClient: ContentProviderClient,
id: Long
): AndroidCalendar<TestEvent>(account, providerClient, TestEvent.Factory, id) {

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
package at.bitfire.ical4android.impl

import android.content.ContentValues
import android.provider.CalendarContract.Events
import at.bitfire.ical4android.AndroidCalendar
import at.bitfire.ical4android.AndroidEvent
import at.bitfire.ical4android.AndroidEventFactory
import at.bitfire.ical4android.Event
import at.bitfire.synctools.storage.BatchOperation
import java.util.UUID

class TestEvent: AndroidEvent {
Expand All @@ -21,19 +19,7 @@ class TestEvent: AndroidEvent {
: super(calendar, values)

constructor(calendar: TestCalendar, event: Event)
: super(calendar, event)

val syncId by lazy { UUID.randomUUID().toString() }


override fun buildEvent(recurrence: Event?, builder: BatchOperation.CpoBuilder) {
if (recurrence != null)
builder.withValue(Events.ORIGINAL_SYNC_ID, syncId)
else
builder.withValue(Events._SYNC_ID, syncId)

super.buildEvent(recurrence, builder)
}
: super(calendar, event, UUID.randomUUID().toString(), null, null, 0)


object Factory: AndroidEventFactory<TestEvent> {
Expand Down
32 changes: 25 additions & 7 deletions lib/src/main/kotlin/at/bitfire/ical4android/AndroidCalendar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import android.provider.CalendarContract.Calendars
import android.provider.CalendarContract.Colors
import android.provider.CalendarContract.Events
import android.provider.CalendarContract.Reminders
import androidx.annotation.CallSuper
import androidx.core.content.contentValuesOf
import at.bitfire.ical4android.AndroidCalendar.Companion.find
import at.bitfire.ical4android.util.MiscUtils.asSyncAdapter
import at.bitfire.ical4android.util.MiscUtils.toValues
import java.io.FileNotFoundException
Expand All @@ -30,7 +31,7 @@ import java.util.logging.Logger
* Communicates with the Android Contacts Provider which uses an SQLite
* database to store the events.
*/
abstract class AndroidCalendar<out T: AndroidEvent>(
open class AndroidCalendar<out T : AndroidEvent>(
val account: Account,
val provider: ContentProviderClient,
val eventFactory: AndroidEventFactory<T>,
Expand All @@ -40,7 +41,9 @@ abstract class AndroidCalendar<out T: AndroidEvent>(
) {

companion object {


private const val COLUMN_SYNC_STATE = Calendars.CAL_SYNC1

private val logger
get() = Logger.getLogger(AndroidCalendar::class.java.name)

Expand Down Expand Up @@ -77,7 +80,7 @@ abstract class AndroidCalendar<out T: AndroidEvent>(

fun insertColors(provider: ContentProviderClient, account: Account) {
provider.query(Colors.CONTENT_URI.asSyncAdapter(account), arrayOf(Colors.COLOR_KEY), null, null, null)?.use { cursor ->
if (cursor.count == Css3Color.values().size)
if (cursor.count == Css3Color.entries.size)
// colors already inserted and up to date
return
}
Expand All @@ -87,7 +90,7 @@ abstract class AndroidCalendar<out T: AndroidEvent>(
values.put(Colors.ACCOUNT_NAME, account.name)
values.put(Colors.ACCOUNT_TYPE, account.type)
values.put(Colors.COLOR_TYPE, Colors.TYPE_EVENT)
for (color in Css3Color.values()) {
for (color in Css3Color.entries) {
values.put(Colors.COLOR_KEY, color.name)
values.put(Colors.COLOR, color.argb)
try {
Expand Down Expand Up @@ -161,6 +164,7 @@ abstract class AndroidCalendar<out T: AndroidEvent>(

var name: String? = null
var displayName: String? = null
var accessLevel: Int? = null
var color: Int? = null
var isSynced = true
var isVisible = true
Expand All @@ -179,10 +183,10 @@ abstract class AndroidCalendar<out T: AndroidEvent>(
*
* @param info values from Calendar Provider
*/
@CallSuper
protected open fun populate(info: ContentValues) {
private fun populate(info: ContentValues) {
name = info.getAsString(Calendars.NAME)
displayName = info.getAsString(Calendars.CALENDAR_DISPLAY_NAME)
accessLevel = info.getAsInteger(Calendars.CALENDAR_ACCESS_LEVEL)

color = info.getAsInteger(Calendars.CALENDAR_COLOR)

Expand Down Expand Up @@ -234,6 +238,20 @@ abstract class AndroidCalendar<out T: AndroidEvent>(
?: throw FileNotFoundException()


fun getSyncState(): String? =
provider.query(calendarSyncURI(), arrayOf(COLUMN_SYNC_STATE), null, null, null)?.use { cursor ->
if (cursor.moveToNext())
return cursor.getString(0)
else
null
}

fun setSyncState(state: String?) {
val values = contentValuesOf(COLUMN_SYNC_STATE to state.toString())
provider.update(calendarSyncURI(), values, null, null)
}


fun calendarSyncURI() = ContentUris.withAppendedId(Calendars.CONTENT_URI, id).asSyncAdapter(account)

}
Loading