Skip to content

Commit 0312164

Browse files
authored
Remove deprecated AndroidEvent2, support iterating EventAndExceptions (#125)
* Remove deprecated AndroidEvent2 class, support iterating recurring events - Replace references to `AndroidEvent2` with `AndroidEvent` - Add support for iterating through recurring events in `AndroidRecurringCalendar` * Fix references and tests * Fix tests
1 parent 7b420d6 commit 0312164

File tree

24 files changed

+211
-313
lines changed

24 files changed

+211
-313
lines changed

lib/src/androidTest/kotlin/at/bitfire/synctools/storage/calendar/AndroidCalendarTest.kt

Lines changed: 46 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import at.bitfire.ical4android.util.MiscUtils.closeCompat
2121
import at.bitfire.synctools.storage.BatchOperation
2222
import at.bitfire.synctools.test.InitCalendarProviderRule
2323
import at.bitfire.synctools.test.assertContentValuesEqual
24+
import at.bitfire.synctools.test.assertEntitiesEqual
2425
import org.junit.After
2526
import org.junit.Assert.assertEquals
2627
import org.junit.Assert.assertNotEquals
@@ -63,27 +64,21 @@ class AndroidCalendarTest {
6364

6465
@Test
6566
fun testAddEvent_and_GetEvent() {
66-
val values = contentValuesOf(
67+
val entity = Entity(contentValuesOf(
6768
Events.CALENDAR_ID to calendar.id,
6869
Events.DTSTART to now,
6970
Events.DTEND to now + 3600000,
7071
Events.TITLE to "Some Event"
71-
)
72-
val entity = Entity(values)
73-
val reminder = contentValuesOf(
74-
Reminders.MINUTES to 123
75-
)
76-
entity.subValues.add(Entity.NamedContentValues(Reminders.CONTENT_URI, reminder))
72+
)).apply {
73+
addSubValue(Reminders.CONTENT_URI, contentValuesOf(
74+
Reminders.MINUTES to 123
75+
))
76+
}
7777
val id = calendar.addEvent(entity)
7878

7979
// verify that event has been inserted
8080
val result = calendar.getEvent(id)!!
81-
assertEquals(id, result.id)
82-
assertEquals(now, result.dtStart)
83-
assertEquals(now + 3600000, result.dtEnd)
84-
assertEquals("Some Event", result.title)
85-
assertEquals(1, result.reminders.size)
86-
assertEquals(123, result.reminders.first().getAsInteger(Reminders.MINUTES))
81+
assertEntitiesEqual(entity, result, onlyFieldsInExpected = true)
8782
}
8883

8984
@Test
@@ -97,17 +92,16 @@ class AndroidCalendarTest {
9792
.withSelection("${Events._SYNC_ID}=?", arrayOf("testAddEvent_toBatch_AsSecondOperation"))
9893

9994
// second operation (event row index > 0)
100-
val values = contentValuesOf(
95+
val entity = Entity(contentValuesOf(
10196
Events.CALENDAR_ID to calendar.id,
10297
Events.DTSTART to now,
10398
Events.DTEND to now + 3600000,
10499
Events.TITLE to "Some Event"
105-
)
106-
val entity = Entity(values)
107-
val reminder = contentValuesOf(
108-
Reminders.MINUTES to 123
109-
)
110-
entity.subValues.add(Entity.NamedContentValues(Reminders.CONTENT_URI, reminder))
100+
)).apply {
101+
addSubValue(Reminders.CONTENT_URI, contentValuesOf(
102+
Reminders.MINUTES to 123
103+
))
104+
}
111105
val idx = batch.nextBackrefIdx()
112106
calendar.addEvent(entity, batch)
113107

@@ -116,12 +110,7 @@ class AndroidCalendarTest {
116110

117111
// verify that event has been inserted
118112
val result = calendar.getEvent(id)!!
119-
assertEquals(id, result.id)
120-
assertEquals(now, result.dtStart)
121-
assertEquals(now + 3600000, result.dtEnd)
122-
assertEquals("Some Event", result.title)
123-
assertEquals(1, result.reminders.size)
124-
assertEquals(123, result.reminders.first().getAsInteger(Reminders.MINUTES))
113+
assertEntitiesEqual(entity, result, onlyFieldsInExpected = true)
125114
}
126115

127116
@Test
@@ -146,8 +135,14 @@ class AndroidCalendarTest {
146135
)))
147136
val result = calendar.findEvents("${Events.DTSTART}=?", arrayOf((now + 3600000).toString()))
148137
assertEquals(2, result.size)
149-
assertEquals(setOf(id2, id3), result.map { it.id }.toSet())
150-
assertEquals(setOf("Some Other Event 1", "Some Other Event 2"), result.map { it.title }.toSet())
138+
assertEquals(
139+
setOf(id2, id3),
140+
result.map { it.entityValues.getAsLong(Events._ID) }.toSet()
141+
)
142+
assertEquals(
143+
setOf("Some Other Event 1", "Some Other Event 2"),
144+
result.map { it.entityValues.getAsString(Events.TITLE) }.toSet()
145+
)
151146
}
152147

153148
@Test
@@ -303,57 +298,58 @@ class AndroidCalendarTest {
303298

304299
calendar.updateEventRow(id, contentValuesOf(Events.TITLE to "New Title"))
305300

306-
assertEquals("New Title", calendar.getEvent(id)!!.title)
301+
assertEquals("New Title", calendar.getEvent(id)!!.entityValues.getAsString(Events.TITLE))
307302
}
308303

309304
@Test
310305
fun testUpdateEvent_NoRebuild() {
311-
val values = contentValuesOf(
306+
val entity = Entity(contentValuesOf(
312307
Events.CALENDAR_ID to calendar.id,
313308
Events.DTSTART to now,
314309
Events.DTEND to now + 3600000,
315310
Events.TITLE to "Some Event",
316-
Events.STATUS to null
317-
)
318-
val entity = Entity(values)
319-
val reminder = contentValuesOf(
320-
Reminders.MINUTES to 123
321-
)
322-
entity.subValues.add(Entity.NamedContentValues(Reminders.CONTENT_URI, reminder))
311+
//Events.STATUS to null
312+
)).apply {
313+
addSubValue(Reminders.CONTENT_URI, contentValuesOf(
314+
Reminders.MINUTES to 123
315+
))
316+
}
323317
val id = calendar.addEvent(entity)
324318

325-
values.put(Events.TITLE, "New Title")
319+
// update with modified title
320+
entity.entityValues.put(Events.TITLE, "New Title")
326321
assertEquals(id, calendar.updateEvent(id, entity))
327322

328323
val result = calendar.getEvent(id)!!
329-
assertEquals("New Title", result.title)
330-
assertEquals(1, result.reminders.size)
331-
assertEquals(123, result.reminders.first().getAsInteger(Reminders.MINUTES))
324+
assertEntitiesEqual(entity, result, onlyFieldsInExpected = true)
332325
}
333326

334327
@Test
335328
fun testUpdateEvent_Rebuild() {
336-
val values = contentValuesOf(
329+
val entity = Entity(contentValuesOf(
337330
Events.CALENDAR_ID to calendar.id,
338331
Events.DTSTART to now,
339332
Events.DTEND to now + 3600000,
340333
Events.TITLE to "Some Event 1",
341334
Events.STATUS to Events.STATUS_CONFIRMED
342-
)
343-
val id = calendar.addEvent(Entity(values))
335+
))
336+
val id = calendar.addEvent(entity)
344337

345-
values.put(Events.TITLE, "New Title")
346-
values.putNull(Events.STATUS)
347-
val newId = calendar.updateEvent(id, Entity(values))
338+
entity.entityValues.put(Events.TITLE, "New Title")
339+
entity.entityValues.putNull(Events.STATUS) // triggers re-build
340+
val newId = calendar.updateEvent(id, entity)
348341
assertNotEquals(newId, id)
349342

350343
// old event is deleted
351344
assertNull(calendar.getEvent(id))
352345

353346
// new event doesn't have status
354347
val newEvent = calendar.getEvent(newId)!!
355-
assertEquals("New Title", newEvent.title)
356-
assertNull(newEvent.status)
348+
assertNull(newEvent.entityValues.getAsInteger(Events.STATUS)) // verify that it's null
349+
val expected = Entity(ContentValues(entity.entityValues).apply {
350+
remove(Events.STATUS) // is null in provider and thus not returned by getEvent
351+
})
352+
assertEntitiesEqual(expected, newEvent, onlyFieldsInExpected = true)
357353
}
358354

359355
@Test
@@ -371,7 +367,7 @@ class AndroidCalendarTest {
371367
arrayOf(now.toString())
372368
)
373369

374-
assertEquals("New Title", calendar.getEvent(id)!!.title)
370+
assertEquals("New Title", calendar.getEvent(id)!!.entityValues.getAsString(Events.TITLE))
375371
}
376372

377373
@Test

lib/src/main/kotlin/at/bitfire/synctools/mapping/calendar/builder/CategoriesBuilder.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ package at.bitfire.synctools.mapping.calendar.builder
99
import android.content.Entity
1010
import android.provider.CalendarContract.ExtendedProperties
1111
import androidx.core.content.contentValuesOf
12-
import at.bitfire.synctools.storage.calendar.AndroidEvent2
12+
import at.bitfire.synctools.storage.calendar.EventsContract
1313
import net.fortuna.ical4j.model.Property
1414
import net.fortuna.ical4j.model.component.VEvent
1515
import net.fortuna.ical4j.model.property.Categories
@@ -19,15 +19,15 @@ class CategoriesBuilder: AndroidEntityBuilder {
1919
override fun build(from: VEvent, main: VEvent, to: Entity) {
2020
val categories = from.getProperty<Categories>(Property.CATEGORIES)?.categories
2121
if (categories != null && !categories.isEmpty) {
22-
val rawCategories = categories.joinToString(AndroidEvent2.CATEGORIES_SEPARATOR.toString()) { category ->
22+
val rawCategories = categories.joinToString(EventsContract.CATEGORIES_SEPARATOR.toString()) { category ->
2323
// drop occurrences of CATEGORIES_SEPARATOR in category names
24-
category.filter { it != AndroidEvent2.CATEGORIES_SEPARATOR }
24+
category.filter { it != EventsContract.CATEGORIES_SEPARATOR }
2525
}
2626

2727
to.addSubValue(
2828
ExtendedProperties.CONTENT_URI,
2929
contentValuesOf(
30-
ExtendedProperties.NAME to AndroidEvent2.EXTNAME_CATEGORIES,
30+
ExtendedProperties.NAME to EventsContract.EXTNAME_CATEGORIES,
3131
ExtendedProperties.VALUE to rawCategories
3232
)
3333
)

lib/src/main/kotlin/at/bitfire/synctools/mapping/calendar/builder/ETagBuilder.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
package at.bitfire.synctools.mapping.calendar.builder
88

99
import android.content.Entity
10-
import at.bitfire.synctools.storage.calendar.AndroidEvent2
10+
import at.bitfire.synctools.storage.calendar.EventsContract
1111
import net.fortuna.ical4j.model.component.VEvent
1212

1313
class ETagBuilder(
@@ -19,11 +19,11 @@ class ETagBuilder(
1919
val values = to.entityValues
2020
if (from === main) {
2121
// only set ETag and Schedule-Tag for main event
22-
values.put(AndroidEvent2.COLUMN_ETAG, eTag)
23-
values.put(AndroidEvent2.COLUMN_SCHEDULE_TAG, scheduleTag)
22+
values.put(EventsContract.COLUMN_ETAG, eTag)
23+
values.put(EventsContract.COLUMN_SCHEDULE_TAG, scheduleTag)
2424
} else {
25-
values.putNull(AndroidEvent2.COLUMN_ETAG)
26-
values.putNull(AndroidEvent2.COLUMN_SCHEDULE_TAG)
25+
values.putNull(EventsContract.COLUMN_ETAG)
26+
values.putNull(EventsContract.COLUMN_SCHEDULE_TAG)
2727
}
2828
}
2929

lib/src/main/kotlin/at/bitfire/synctools/mapping/calendar/builder/SequenceBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
package at.bitfire.synctools.mapping.calendar.builder
88

99
import android.content.Entity
10-
import at.bitfire.synctools.storage.calendar.AndroidEvent2
10+
import at.bitfire.synctools.storage.calendar.EventsContract
1111
import net.fortuna.ical4j.model.component.VEvent
1212

1313
class SequenceBuilder: AndroidEntityBuilder {
1414

1515
override fun build(from: VEvent, main: VEvent, to: Entity) {
1616
/* When we build the SEQUENCE column from a real event, we set the sequence to 0 (not null), so that we
1717
can distinguish it from events which have been created locally and have never been uploaded yet. */
18-
to.entityValues.put(AndroidEvent2.COLUMN_SEQUENCE, from.sequence?.sequenceNo ?: 0)
18+
to.entityValues.put(EventsContract.COLUMN_SEQUENCE, from.sequence?.sequenceNo ?: 0)
1919
}
2020

2121
}

lib/src/main/kotlin/at/bitfire/synctools/mapping/calendar/builder/SyncFlagsBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
package at.bitfire.synctools.mapping.calendar.builder
88

99
import android.content.Entity
10-
import at.bitfire.synctools.storage.calendar.AndroidEvent2
10+
import at.bitfire.synctools.storage.calendar.EventsContract
1111
import net.fortuna.ical4j.model.component.VEvent
1212

1313
class SyncFlagsBuilder(
1414
private val flags: Int
1515
): AndroidEntityBuilder {
1616

1717
override fun build(from: VEvent, main: VEvent, to: Entity) {
18-
to.entityValues.put(AndroidEvent2.COLUMN_FLAGS, flags)
18+
to.entityValues.put(EventsContract.COLUMN_FLAGS, flags)
1919
}
2020

2121
}

lib/src/main/kotlin/at/bitfire/synctools/mapping/calendar/builder/UrlBuilder.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ package at.bitfire.synctools.mapping.calendar.builder
99
import android.content.Entity
1010
import android.provider.CalendarContract.ExtendedProperties
1111
import androidx.core.content.contentValuesOf
12-
import at.bitfire.synctools.storage.calendar.AndroidEvent2
12+
import at.bitfire.synctools.storage.calendar.EventsContract
1313
import net.fortuna.ical4j.model.component.VEvent
1414

1515
class UrlBuilder: AndroidEntityBuilder {
@@ -20,7 +20,7 @@ class UrlBuilder: AndroidEntityBuilder {
2020
to.addSubValue(
2121
ExtendedProperties.CONTENT_URI,
2222
contentValuesOf(
23-
ExtendedProperties.NAME to AndroidEvent2.EXTNAME_URL,
23+
ExtendedProperties.NAME to EventsContract.EXTNAME_URL,
2424
ExtendedProperties.VALUE to uri
2525
)
2626
)

lib/src/main/kotlin/at/bitfire/synctools/mapping/calendar/processor/CategoriesProcessor.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ package at.bitfire.synctools.mapping.calendar.processor
88

99
import android.content.Entity
1010
import android.provider.CalendarContract.ExtendedProperties
11-
import at.bitfire.synctools.storage.calendar.AndroidEvent2
11+
import at.bitfire.synctools.storage.calendar.EventsContract
1212
import net.fortuna.ical4j.model.TextList
1313
import net.fortuna.ical4j.model.component.VEvent
1414
import net.fortuna.ical4j.model.property.Categories
@@ -17,11 +17,11 @@ class CategoriesProcessor: AndroidEventFieldProcessor {
1717

1818
override fun process(from: Entity, main: Entity, to: VEvent) {
1919
val extended = from.subValues.filter { it.uri == ExtendedProperties.CONTENT_URI }.map { it.values }
20-
val categories = extended.firstOrNull { it.getAsString(ExtendedProperties.NAME) == AndroidEvent2.EXTNAME_CATEGORIES }
20+
val categories = extended.firstOrNull { it.getAsString(ExtendedProperties.NAME) == EventsContract.EXTNAME_CATEGORIES }
2121
val listValue = categories?.getAsString(ExtendedProperties.VALUE)
2222
if (listValue != null) {
2323
to.properties += Categories(TextList(
24-
listValue.split(AndroidEvent2.CATEGORIES_SEPARATOR).toTypedArray()
24+
listValue.split(EventsContract.CATEGORIES_SEPARATOR).toTypedArray()
2525
))
2626
}
2727
}

lib/src/main/kotlin/at/bitfire/synctools/mapping/calendar/processor/SequenceProcessor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
package at.bitfire.synctools.mapping.calendar.processor
88

99
import android.content.Entity
10-
import at.bitfire.synctools.storage.calendar.AndroidEvent2
10+
import at.bitfire.synctools.storage.calendar.EventsContract
1111
import net.fortuna.ical4j.model.component.VEvent
1212
import net.fortuna.ical4j.model.property.Sequence
1313

1414
class SequenceProcessor: AndroidEventFieldProcessor {
1515

1616
override fun process(from: Entity, main: Entity, to: VEvent) {
17-
val seqNo = from.entityValues.getAsInteger(AndroidEvent2.COLUMN_SEQUENCE)
17+
val seqNo = from.entityValues.getAsInteger(EventsContract.COLUMN_SEQUENCE)
1818
if (seqNo != null && seqNo > 0)
1919
to.properties += Sequence(seqNo)
2020
}

lib/src/main/kotlin/at/bitfire/synctools/mapping/calendar/processor/UidProcessor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ package at.bitfire.synctools.mapping.calendar.processor
99
import android.content.Entity
1010
import android.provider.CalendarContract.Events
1111
import android.provider.CalendarContract.ExtendedProperties
12-
import at.bitfire.synctools.storage.calendar.AndroidEvent2
12+
import at.bitfire.synctools.storage.calendar.EventsContract
1313
import net.fortuna.ical4j.model.component.VEvent
1414
import net.fortuna.ical4j.model.property.Uid
1515

@@ -26,7 +26,7 @@ class UidProcessor: AndroidEventFieldProcessor {
2626
private fun uidFromExtendedProperties(rows: List<Entity.NamedContentValues>): String? {
2727
val uidRow = rows.firstOrNull {
2828
it.uri == ExtendedProperties.CONTENT_URI &&
29-
it.values.getAsString(ExtendedProperties.NAME) == AndroidEvent2.EXTNAME_ICAL_UID
29+
it.values.getAsString(ExtendedProperties.NAME) == EventsContract.EXTNAME_ICAL_UID
3030
}
3131

3232
return uidRow?.values?.getAsString(ExtendedProperties.VALUE)

lib/src/main/kotlin/at/bitfire/synctools/mapping/calendar/processor/UrlProcessor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ package at.bitfire.synctools.mapping.calendar.processor
88

99
import android.content.Entity
1010
import android.provider.CalendarContract.ExtendedProperties
11-
import at.bitfire.synctools.storage.calendar.AndroidEvent2
11+
import at.bitfire.synctools.storage.calendar.EventsContract
1212
import net.fortuna.ical4j.model.component.VEvent
1313
import net.fortuna.ical4j.model.property.Url
1414
import java.net.URI
@@ -18,7 +18,7 @@ class UrlProcessor: AndroidEventFieldProcessor {
1818

1919
override fun process(from: Entity, main: Entity, to: VEvent) {
2020
val extended = from.subValues.filter { it.uri == ExtendedProperties.CONTENT_URI }.map { it.values }
21-
val urlRow = extended.firstOrNull { it.getAsString(ExtendedProperties.NAME) == AndroidEvent2.EXTNAME_URL }
21+
val urlRow = extended.firstOrNull { it.getAsString(ExtendedProperties.NAME) == EventsContract.EXTNAME_URL }
2222
val url = urlRow?.getAsString(ExtendedProperties.VALUE)
2323
if (url != null) {
2424
val uri = try {

0 commit comments

Comments
 (0)