Skip to content

Commit b59ceec

Browse files
authored
refactor AndroidEvent; introduce AndroidEvent2 with Entity as data object (#40)
* Refactor AndroidEvent to use Entity for event data * Keep legacy AndroidEvent * Keep legacy for InitCalendarProviderRule * Rename legacy calendar event builder/processing classes * Use low-level AndroidEvent in InitCalendarProviderRule * Builder template * [WIP] Ideas AssociatedRows + collection * AndroidEvent: move add() to LegacyAndroidCalendar * LegacyAndroidCalendar: add `getEvent()` for event retrieval * LegacyAndroidCalendar: add `getEvent()` for event retrieval * Move constants to AndroidEvent2 * Move getLegacyEvent to LegacyAndroidCalendar * Add package structure to README * AndroidCalendarTest * Adapt numDirectInstances * Fix updateEvent * [WIP] Fix tests * Simplify numDirectInstances / numInstances to only numInstances * Imports; AndroidEvent2: add attendees/extended properties * Fix InitCalendarProviderRule * Adapt tests * Add method to find first event row * Update findEventRow and iterateEventRows to accept nullable parameters * Update KDoc and AndroidEvent.toString
1 parent 211cc9f commit b59ceec

File tree

19 files changed

+1197
-584
lines changed

19 files changed

+1197
-584
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ We're happy about contributions! In case of bigger changes, please let us know i
1919
Then make the changes in your own repository and send a pull request.
2020

2121

22+
# Packages
23+
24+
- `at.bitfire.synctools`: new package where everything shall be refactored into
25+
- `.icalendar`: high-level operations on iCalendar objects
26+
- `.mapping`: mappers between low-level (database rows) and high-level (iCalendar/vCard) objects
27+
- `.storage`: low-level operations on content-provider storage (`ContentValues` / `Entity` to store data)
28+
- `at.bitfire.ical4android`: legacy [ical4android](https://github.com/bitfireAT/ical4android)
29+
- `at.bitfire.vcard4android`: legacy [vcard4android](https://github.com/bitfireAT/vcard4android)
30+
31+
32+
2233
# How to use
2334

2435
Add the [jitpack.io](https://jitpack.io) repository to your project's level `build.gradle`:

lib/src/androidTest/kotlin/at/bitfire/ical4android/AndroidEventTest.kt

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import at.bitfire.ical4android.impl.TestCalendar
1717
import at.bitfire.ical4android.util.MiscUtils.closeCompat
1818
import at.bitfire.synctools.icalendar.Css3Color
1919
import at.bitfire.synctools.storage.calendar.AndroidCalendar
20+
import at.bitfire.synctools.storage.calendar.AndroidEvent2
2021
import at.bitfire.synctools.test.InitCalendarProviderRule
2122
import net.fortuna.ical4j.model.DateTime
2223
import net.fortuna.ical4j.model.component.VAlarm
@@ -44,15 +45,17 @@ class AndroidEventTest {
4445

4546
private val testAccount = Account(javaClass.name, ACCOUNT_TYPE_LOCAL)
4647

47-
private lateinit var calendar: AndroidCalendar
4848
lateinit var client: ContentProviderClient
49+
private lateinit var calendar: AndroidCalendar
50+
private lateinit var legacyCalendar: LegacyAndroidCalendar
4951

5052
@Before
5153
fun prepare() {
5254
val context = getInstrumentation().targetContext
5355
client = context.contentResolver.acquireContentProviderClient(AUTHORITY)!!
5456

5557
calendar = TestCalendar.findOrCreate(testAccount, client, withColors = true)
58+
legacyCalendar = LegacyAndroidCalendar(calendar)
5659
}
5760

5861
@After
@@ -68,9 +71,9 @@ class AndroidEventTest {
6871
calendar, contentValuesOf(
6972
Events._ID to 123,
7073
Events._SYNC_ID to "some-ical.ics",
71-
AndroidEvent.COLUMN_ETAG to "some-etag",
72-
AndroidEvent.COLUMN_SCHEDULE_TAG to "some-schedule-tag",
73-
AndroidEvent.COLUMN_FLAGS to 45
74+
AndroidEvent2.COLUMN_ETAG to "some-etag",
75+
AndroidEvent2.COLUMN_SCHEDULE_TAG to "some-schedule-tag",
76+
AndroidEvent2.COLUMN_FLAGS to 45
7477
)
7578
)
7679
assertEquals(123L, e.id)
@@ -90,11 +93,11 @@ class AndroidEventTest {
9093
event.dtStart = DtStart("20150502T120000Z")
9194
event.dtEnd = DtEnd("20150502T130000Z")
9295
event.organizer = Organizer(URI("mailto:organizer@example.com"))
93-
val uri = AndroidEvent(calendar, event, "update-event").add()
96+
val uri = legacyCalendar.add(event)
9497

9598
// update test event in calendar
96-
val testEvent = calendar.getEvent(ContentUris.parseId(uri))!!
97-
val event2 = testEvent.event!!
99+
val testEvent = legacyCalendar.getAndroidEvent(calendar, ContentUris.parseId(uri))!!
100+
val event2 = legacyCalendar.getEvent(testEvent.id)!!
98101
event2.summary = "Updated event"
99102
// add data rows
100103
event2.alarms += VAlarm(Duration.parse("-P1DT2H3M4S"))
@@ -105,9 +108,9 @@ class AndroidEventTest {
105108
assertEquals(ContentUris.parseId(uri), ContentUris.parseId(uri2))
106109

107110
// read again and verify result
108-
val updatedEvent = calendar.getEvent(ContentUris.parseId(uri2))!!
111+
val updatedEvent = legacyCalendar.getAndroidEvent(calendar, ContentUris.parseId(uri2))!!
109112
try {
110-
val event3 = updatedEvent.event!!
113+
val event3 = legacyCalendar.getEvent(updatedEvent.id)!!
111114
assertEquals(event2.summary, event3.summary)
112115
assertEquals(1, event3.alarms.size)
113116
assertEquals(1, event3.attendees.size)
@@ -124,20 +127,20 @@ class AndroidEventTest {
124127
dtStart = DtStart(DateTime())
125128
color = Css3Color.silver
126129
}
127-
val uri = AndroidEvent(calendar, event, "reset-color").add()
130+
val uri = legacyCalendar.add(event)
128131
val id = ContentUris.parseId(uri)
129132

130133
// verify that it has color
131-
val beforeUpdate = calendar.getEvent(id)!!
132-
assertNotNull(beforeUpdate.event?.color)
134+
val beforeUpdate = legacyCalendar.getAndroidEvent(calendar, id)!!
135+
assertNotNull(legacyCalendar.getEvent(beforeUpdate.id)!!.color)
133136

134137
// update: reset color
135138
event.color = null
136139
beforeUpdate.update(event)
137140

138141
// verify that it doesn't have color anymore
139-
val afterUpdate = calendar.getEvent(id)!!
140-
assertNull(afterUpdate.event!!.color)
142+
val afterUpdate = legacyCalendar.getAndroidEvent(calendar, id)!!
143+
assertNull(legacyCalendar.getEvent(afterUpdate.id)!!.color)
141144
}
142145

143146
@Test
@@ -147,11 +150,11 @@ class AndroidEventTest {
147150
event.summary = "Sample event with STATUS"
148151
event.dtStart = DtStart("20150502T120000Z")
149152
event.dtEnd = DtEnd("20150502T130000Z")
150-
val uri = AndroidEvent(calendar, event, "update-status-from-null").add()
153+
val uri = legacyCalendar.add(event)
151154

152155
// update test event in calendar
153-
val testEvent = calendar.getEvent(ContentUris.parseId(uri))!!
154-
val event2 = testEvent.event!!
156+
val testEvent = legacyCalendar.getAndroidEvent(calendar, ContentUris.parseId(uri))!!
157+
val event2 = legacyCalendar.getEvent(testEvent.id)!!
155158
event2.summary = "Sample event without STATUS"
156159
event2.status = Status.VEVENT_CONFIRMED
157160
val uri2 = testEvent.update(event2)
@@ -160,9 +163,9 @@ class AndroidEventTest {
160163
assertEquals(ContentUris.parseId(uri), ContentUris.parseId(uri2))
161164

162165
// read again and verify result
163-
val updatedEvent = calendar.getEvent(ContentUris.parseId(uri2))!!
166+
val updatedEvent = legacyCalendar.getAndroidEvent(calendar, ContentUris.parseId(uri2))!!
164167
try {
165-
val event3 = updatedEvent.event!!
168+
val event3 = legacyCalendar.getEvent(updatedEvent.id)!!
166169
assertEquals(Status.VEVENT_CONFIRMED, event3.status)
167170
} finally {
168171
updatedEvent.delete()
@@ -177,11 +180,11 @@ class AndroidEventTest {
177180
event.dtStart = DtStart("20150502T120000Z")
178181
event.dtEnd = DtEnd("20150502T130000Z")
179182
event.status = Status.VEVENT_CONFIRMED
180-
val uri = AndroidEvent(calendar, event, "update-status-to-null").add()
183+
val uri = legacyCalendar.add(event)
181184

182185
// update test event in calendar
183-
val testEvent = calendar.getEvent(ContentUris.parseId(uri))!!
184-
val event2 = testEvent.event!!
186+
val testEvent = legacyCalendar.getAndroidEvent(calendar, ContentUris.parseId(uri))!!
187+
val event2 = legacyCalendar.getEvent(testEvent.id)!!
185188
event2.summary = "Sample event without STATUS"
186189
event2.status = null
187190
val uri2 = testEvent.update(event2)
@@ -190,9 +193,9 @@ class AndroidEventTest {
190193
assertNotEquals(ContentUris.parseId(uri), ContentUris.parseId(uri2))
191194

192195
// read again and verify result
193-
val updatedEvent = calendar.getEvent(ContentUris.parseId(uri2))!!
196+
val updatedEvent = legacyCalendar.getAndroidEvent(calendar, ContentUris.parseId(uri2))!!
194197
try {
195-
val event3 = updatedEvent.event!!
198+
val event3 = legacyCalendar.getEvent(updatedEvent.id)!!
196199
assertNull(event3.status)
197200
} finally {
198201
updatedEvent.delete()
@@ -209,11 +212,11 @@ class AndroidEventTest {
209212
event.dtEnd = DtEnd("20150502T130000Z")
210213
for (i in 0 until 20)
211214
event.attendees += Attendee(URI("mailto:att$i@example.com"))
212-
val uri = AndroidEvent(calendar, event, "transaction").add()
215+
val uri = legacyCalendar.add(event)
213216

214-
val testEvent = calendar.getEvent(ContentUris.parseId(uri))!!
217+
val testEvent = legacyCalendar.getAndroidEvent(calendar, ContentUris.parseId(uri))!!
215218
try {
216-
assertEquals(20, testEvent.event!!.attendees.size)
219+
assertEquals(20, legacyCalendar.getEvent(testEvent.id)!!.attendees.size)
217220
} finally {
218221
testEvent.delete()
219222
}

lib/src/androidTest/kotlin/at/bitfire/ical4android/impl/TestCalendar.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package at.bitfire.ical4android.impl
99
import android.accounts.Account
1010
import android.content.ContentProviderClient
1111
import android.provider.CalendarContract.Calendars
12-
import android.provider.CalendarContract.Reminders
1312
import androidx.core.content.contentValuesOf
1413
import at.bitfire.synctools.storage.calendar.AndroidCalendar
1514
import at.bitfire.synctools.storage.calendar.AndroidCalendarProvider
@@ -30,7 +29,7 @@ object TestCalendar {
3029
?: provider.createAndGetCalendar(contentValuesOf(
3130
Calendars.NAME to UUID.randomUUID().toString(),
3231
Calendars.CALENDAR_DISPLAY_NAME to "ical4android Test Calendar",
33-
Calendars.ALLOWED_REMINDERS to Reminders.METHOD_DEFAULT)
32+
Calendars.CALENDAR_ACCESS_LEVEL to Calendars.CAL_ACCESS_ROOT)
3433
)
3534
}
3635

lib/src/androidTest/kotlin/at/bitfire/synctools/mapping/calendar/AndroidEventBuilderTest.kt renamed to lib/src/androidTest/kotlin/at/bitfire/synctools/mapping/calendar/LegacyAndroidEventBuilderTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import android.provider.CalendarContract.Events
1616
import android.provider.CalendarContract.ExtendedProperties
1717
import android.provider.CalendarContract.Reminders
1818
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
19-
import at.bitfire.ical4android.AndroidEvent
2019
import at.bitfire.ical4android.Event
20+
import at.bitfire.ical4android.LegacyAndroidCalendar
2121
import at.bitfire.ical4android.UnknownProperty
2222
import at.bitfire.ical4android.impl.TestCalendar
2323
import at.bitfire.ical4android.util.AndroidTimeUtils
@@ -69,7 +69,7 @@ import java.net.URI
6969
import java.time.Period
7070
import java.util.UUID
7171

72-
class AndroidEventBuilderTest {
72+
class LegacyAndroidEventBuilderTest {
7373

7474
@get:Rule
7575
val initCalendarProviderRule = InitCalendarProviderRule.initialize()
@@ -134,7 +134,7 @@ class AndroidEventBuilderTest {
134134
eventBuilder()
135135
}
136136
// write event with random file name/sync_id
137-
val uri = AndroidEvent(calendar, event, syncId = UUID.randomUUID().toString()).add()
137+
val uri = LegacyAndroidCalendar(calendar).add(event, syncId = UUID.randomUUID().toString())
138138
client.query(uri, null, null, null, null)!!.use { cursor ->
139139
cursor.moveToNext()
140140
return cursor.toContentValues()

lib/src/androidTest/kotlin/at/bitfire/synctools/mapping/calendar/AndroidEventProcessorTest.kt renamed to lib/src/androidTest/kotlin/at/bitfire/synctools/mapping/calendar/LegacyAndroidEventProcessorTest.kt

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,17 @@ import android.accounts.Account
1010
import android.content.ContentProviderClient
1111
import android.content.ContentUris
1212
import android.content.ContentValues
13-
import android.net.Uri
1413
import android.provider.CalendarContract.ACCOUNT_TYPE_LOCAL
1514
import android.provider.CalendarContract.AUTHORITY
1615
import android.provider.CalendarContract.Attendees
17-
import android.provider.CalendarContract.Calendars
1816
import android.provider.CalendarContract.Events
1917
import android.provider.CalendarContract.ExtendedProperties
2018
import android.provider.CalendarContract.Reminders
2119
import androidx.core.content.contentValuesOf
2220
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
2321
import at.bitfire.ical4android.AndroidEvent
2422
import at.bitfire.ical4android.Event
23+
import at.bitfire.ical4android.LegacyAndroidCalendar
2524
import at.bitfire.ical4android.UnknownProperty
2625
import at.bitfire.ical4android.impl.TestCalendar
2726
import at.bitfire.ical4android.util.AndroidTimeUtils
@@ -30,6 +29,7 @@ import at.bitfire.ical4android.util.MiscUtils.closeCompat
3029
import at.bitfire.synctools.icalendar.Css3Color
3130
import at.bitfire.synctools.storage.calendar.AndroidCalendar
3231
import at.bitfire.synctools.storage.calendar.AndroidCalendarProvider
32+
import at.bitfire.synctools.storage.calendar.AndroidEvent2
3333
import at.bitfire.synctools.test.InitCalendarProviderRule
3434
import net.fortuna.ical4j.model.Date
3535
import net.fortuna.ical4j.model.DateTime
@@ -65,7 +65,7 @@ import org.junit.rules.TestRule
6565
import java.net.URI
6666
import java.time.Duration
6767

68-
class AndroidEventProcessorTest {
68+
class LegacyAndroidEventProcessorTest {
6969

7070
@get:Rule
7171
val initCalendarProviderRule: TestRule = InitCalendarProviderRule.initialize()
@@ -75,8 +75,8 @@ class AndroidEventProcessorTest {
7575
private val tzVienna = tzRegistry.getTimeZone("Europe/Vienna")!!
7676
private val tzShanghai = tzRegistry.getTimeZone("Asia/Shanghai")!!
7777

78-
private lateinit var calendarUri: Uri
7978
private lateinit var calendar: AndroidCalendar
79+
lateinit var legacyCalendar: LegacyAndroidCalendar
8080
lateinit var client: ContentProviderClient
8181

8282
@Before
@@ -85,8 +85,7 @@ class AndroidEventProcessorTest {
8585
client = context.contentResolver.acquireContentProviderClient(AUTHORITY)!!
8686

8787
calendar = TestCalendar.findOrCreate(testAccount, client)
88-
assertNotNull(calendar)
89-
calendarUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calendar.id)
88+
legacyCalendar = LegacyAndroidCalendar(calendar)
9089
}
9190

9291
@After
@@ -134,7 +133,7 @@ class AndroidEventProcessorTest {
134133
client.insert(ExtendedProperties.CONTENT_URI.asSyncAdapter(testAccount), extendedValues)
135134
}
136135

137-
return destinationCalendar.getEvent(id)!!
136+
return legacyCalendar.getAndroidEvent(destinationCalendar, id)!!
138137
}
139138

140139
private fun populateEvent(
@@ -145,22 +144,23 @@ class AndroidEventProcessorTest {
145144
extendedProperties: Map<String, String> = emptyMap(),
146145
valuesBuilder: ContentValues.() -> Unit = {}
147146
): Event {
148-
return populateAndroidEvent(
147+
val androidEvent = populateAndroidEvent(
149148
automaticDates,
150149
destinationCalendar,
151150
asSyncAdapter,
152151
insertCallback,
153152
extendedProperties,
154153
valuesBuilder
155-
).event!!
154+
)
155+
return LegacyAndroidCalendar(destinationCalendar).getEvent(androidEvent.id)!!
156156
}
157157

158158
@Test
159159
fun testPopulateEvent_Uid_iCalUid() {
160160
populateEvent(
161161
true,
162162
extendedProperties = mapOf(
163-
AndroidEvent.EXTNAME_ICAL_UID to "event1@example.com"
163+
AndroidEvent2.EXTNAME_ICAL_UID to "event1@example.com"
164164
)
165165
).let { result ->
166166
assertEquals("event1@example.com", result.uid)
@@ -181,7 +181,7 @@ class AndroidEventProcessorTest {
181181
populateEvent(
182182
true,
183183
extendedProperties = mapOf(
184-
AndroidEvent.EXTNAME_ICAL_UID to "event1@example.com"
184+
AndroidEvent2.EXTNAME_ICAL_UID to "event1@example.com"
185185
)
186186
) {
187187
put(Events.UID_2445, "event2@example.com")
@@ -194,7 +194,7 @@ class AndroidEventProcessorTest {
194194
@Test
195195
fun testPopulateEvent_Sequence_Int() {
196196
populateEvent(true, asSyncAdapter = true) {
197-
put(AndroidEvent.COLUMN_SEQUENCE, 5)
197+
put(AndroidEvent2.COLUMN_SEQUENCE, 5)
198198
}.let { result ->
199199
assertEquals(5, result.sequence)
200200
}
@@ -203,7 +203,7 @@ class AndroidEventProcessorTest {
203203
@Test
204204
fun testPopulateEvent_Sequence_Null() {
205205
populateEvent(true, asSyncAdapter = true) {
206-
putNull(AndroidEvent.COLUMN_SEQUENCE)
206+
putNull(AndroidEvent2.COLUMN_SEQUENCE)
207207
}.let { result ->
208208
assertNull(result.sequence)
209209
}
@@ -408,7 +408,7 @@ class AndroidEventProcessorTest {
408408
@Test
409409
fun testPopulateEvent_Url() {
410410
populateEvent(true,
411-
extendedProperties = mapOf(AndroidEvent.EXTNAME_URL to "https://example.com")
411+
extendedProperties = mapOf(AndroidEvent2.EXTNAME_URL to "https://example.com")
412412
).let { result ->
413413
assertEquals(URI("https://example.com"), result.url)
414414
}

0 commit comments

Comments
 (0)