data: add ColumnReader abstraction + Cursor.toCalendarSource mapper

Deviation from Plan 02: the JVM mockable-android.jar stubs every Cursor
method even with isReturnDefaultValues=true (returns null/0 regardless of
the underlying MatrixCursor backing). Introduce an internal ColumnReader
interface so mappers stay pure-Kotlin and JVM-testable via MapColumnReader,
while production reads through CursorColumnReader.
This commit is contained in:
2026-06-08 17:40:37 +02:00
parent fb723fba68
commit 0e4c47febe
4 changed files with 132 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
package de.jeanlucmakiola.calendula.data.calendar
import de.jeanlucmakiola.calendula.domain.CalendarSource
internal fun ColumnReader.toCalendarSource(): CalendarSource = CalendarSource(
id = getLong(CalendarProjection.IDX_ID),
displayName = getString(CalendarProjection.IDX_DISPLAY_NAME)
?: Fallbacks.UNNAMED_CALENDAR,
accountName = getString(CalendarProjection.IDX_ACCOUNT_NAME).orEmpty(),
accountType = getString(CalendarProjection.IDX_ACCOUNT_TYPE).orEmpty(),
color = getInt(CalendarProjection.IDX_COLOR),
isVisibleInSystem = getInt(CalendarProjection.IDX_VISIBLE) != 0,
)

View File

@@ -0,0 +1,22 @@
package de.jeanlucmakiola.calendula.data.calendar
import android.database.Cursor
/**
* Read-only view over a single row's columns by index. Lets the mappers work
* on pure-Kotlin test fixtures (MapColumnReader) on the JVM, while the
* production path adapts an Android Cursor row via CursorColumnReader.
*/
internal interface ColumnReader {
fun getLong(index: Int): Long
fun getString(index: Int): String?
fun getInt(index: Int): Int
fun isNull(index: Int): Boolean
}
internal class CursorColumnReader(private val cursor: Cursor) : ColumnReader {
override fun getLong(index: Int): Long = cursor.getLong(index)
override fun getString(index: Int): String? = cursor.getString(index)
override fun getInt(index: Int): Int = cursor.getInt(index)
override fun isNull(index: Int): Boolean = cursor.isNull(index)
}