Simplify LocalResource interface (#1784)

* Simplify LocalResource interface

- Remove generic parameter from LocalResource interface
- Update all implementations to reflect the change
- Adjust related test cases and exception handling

* Fix tests
This commit is contained in:
Ricki Hirner
2025-10-29 08:50:09 +01:00
committed by GitHub
parent f0f9f58e49
commit b839cbfe7f
11 changed files with 31 additions and 36 deletions

View File

@@ -8,7 +8,7 @@ import android.content.Context
import at.bitfire.davdroid.resource.LocalResource
import java.util.Optional
class LocalTestResource: LocalResource<Any> {
class LocalTestResource: LocalResource {
override val id: Long? = null
override var fileName: String? = null
@@ -33,7 +33,6 @@ class LocalTestResource: LocalResource<Any> {
this.flags = flags
}
override fun update(data: Any, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) = throw NotImplementedError()
override fun deleteLocal() = throw NotImplementedError()
override fun resetDeleted() = throw NotImplementedError()

View File

@@ -6,4 +6,8 @@ package at.bitfire.davdroid.resource
import at.bitfire.vcard4android.Contact
interface LocalAddress: LocalResource<Contact>
interface LocalAddress: LocalResource {
fun update(data: Contact, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int)
}

View File

@@ -4,7 +4,7 @@
package at.bitfire.davdroid.resource
interface LocalCollection<out T: LocalResource<*>> {
interface LocalCollection<out T: LocalResource> {
/** a tag that uniquely identifies the collection (DAVx5-wide) */
val tag: String

View File

@@ -23,7 +23,7 @@ import java.util.UUID
class LocalEvent(
val recurringCalendar: AndroidRecurringCalendar,
val androidEvent: AndroidEvent2
) : LocalResource<Event> {
) : LocalResource {
override val id: Long
get() = androidEvent.id
@@ -41,7 +41,7 @@ class LocalEvent(
get() = androidEvent.flags
override fun update(data: Event, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
fun update(data: Event, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
val eventAndExceptions = LegacyAndroidEventBuilder2(
calendar = androidEvent.calendar,
event = data,

View File

@@ -22,7 +22,7 @@ class LocalJtxICalObject(
flags: Int
) :
JtxICalObject(collection),
LocalResource<JtxICalObject> {
LocalResource {
init {
@@ -52,7 +52,7 @@ class LocalJtxICalObject(
}
override fun update(data: JtxICalObject, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
fun update(data: JtxICalObject, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
this.fileName = fileName
this.eTag = eTag
this.scheduleTag = scheduleTag

View File

@@ -13,7 +13,7 @@ import java.util.Optional
/**
* Defines operations that are used by SyncManager for all sync data types.
*/
interface LocalResource<in TData: Any> {
interface LocalResource {
companion object {
/**
@@ -78,14 +78,6 @@ interface LocalResource<in TData: Any> {
*/
fun updateFlags(flags: Int)
/**
* Updates the data object in the content provider and ensures that the dirty flag is clear.
* Does not affect `this` or the [data] object (which are both immutable).
*
* @return content URI of the updated row (e.g. event URI)
*/
fun update(data: TData, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int)
/**
* Deletes the data object from the content provider.
*/

View File

@@ -21,7 +21,7 @@ import org.dmfs.tasks.contract.TaskContract.Tasks
import java.util.Optional
import java.util.UUID
class LocalTask: DmfsTask, LocalResource<Task> {
class LocalTask: DmfsTask, LocalResource {
companion object {
const val COLUMN_ETAG = Tasks.SYNC1
@@ -100,7 +100,7 @@ class LocalTask: DmfsTask, LocalResource<Task> {
this.eTag = eTag
}
override fun update(data: Task, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
fun update(data: Task, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
this.fileName = fileName
this.eTag = eTag
this.scheduleTag = scheduleTag

View File

@@ -18,12 +18,12 @@ class SyncException(cause: Throwable) : Exception(cause) {
// provide lambda wrappers for setting the local/remote resource
fun <T> wrapWithLocalResource(localResource: LocalResource<*>?, body: () -> T): T =
fun <T> wrapWithLocalResource(localResource: LocalResource?, body: () -> T): T =
runBlocking {
wrapWithLocalResourceSuspending(localResource, body)
}
suspend fun <T> wrapWithLocalResourceSuspending(localResource: LocalResource<*>?, body: suspend () -> T): T {
suspend fun <T> wrapWithLocalResourceSuspending(localResource: LocalResource?, body: suspend () -> T): T {
try {
return body()
} catch (e: SyncException) {
@@ -68,12 +68,12 @@ class SyncException(cause: Throwable) : Exception(cause) {
}
var localResource: LocalResource<*>? = null
var localResource: LocalResource? = null
private set
var remoteResource: HttpUrl? = null
private set
fun setLocalResourceIfNull(local: LocalResource<*>): SyncException {
fun setLocalResourceIfNull(local: LocalResource): SyncException {
if (localResource == null)
localResource = local

View File

@@ -74,7 +74,7 @@ import javax.net.ssl.SSLHandshakeException
* @param collection collection info in the database
* @param resync whether re-synchronization is requested
*/
abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: LocalCollection<ResourceType>, RemoteType: DavCollection>(
abstract class SyncManager<ResourceType: LocalResource, out CollectionType: LocalCollection<ResourceType>, RemoteType: DavCollection>(
val account: Account,
val httpClient: HttpClient,
val dataType: SyncDataType,
@@ -247,7 +247,7 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L
logger.info("Remote collection didn't change, no reason to sync")
} catch (potentiallyWrappedException: Throwable) {
var local: LocalResource<*>? = null
var local: LocalResource? = null
var remote: HttpUrl? = null
val e = SyncException.unwrap(potentiallyWrappedException) {
@@ -745,7 +745,7 @@ abstract class SyncManager<ResourceType: LocalResource<*>, out CollectionType: L
/**
* Logs the exception, updates sync result and shows a notification to the user.
*/
private fun handleException(e: Throwable, local: LocalResource<*>?, remote: HttpUrl?) {
private fun handleException(e: Throwable, local: LocalResource?, remote: HttpUrl?) {
var message: String
when (e) {
is IOException -> {

View File

@@ -111,7 +111,7 @@ class SyncNotificationManager @AssistedInject constructor(
message: String,
localCollection: LocalCollection<*>,
e: Throwable,
local: LocalResource<*>?,
local: LocalResource?,
remote: HttpUrl?
) = notificationRegistry.notifyIfPossible(NotificationRegistry.NOTIFY_SYNC_ERROR, tag = notificationTag) {
val contentIntent: Intent
@@ -218,7 +218,7 @@ class SyncNotificationManager @AssistedInject constructor(
private fun buildDebugInfoIntent(
dataType: SyncDataType,
e: Throwable,
local: LocalResource<*>?,
local: LocalResource?,
remote: HttpUrl?
): Intent {
val builder = DebugInfoActivity.IntentBuilder(context)

View File

@@ -16,8 +16,8 @@ class SyncExceptionTest {
@Test
fun testWrapWithLocalResource_LocalResource_Exception() {
val outer = mockk<LocalResource<*>>()
val inner = mockk<LocalResource<*>>()
val outer = mockk<LocalResource>()
val inner = mockk<LocalResource>()
val e = Exception()
val result = assertSyncException {
@@ -34,8 +34,8 @@ class SyncExceptionTest {
@Test
fun testWrapWithLocalResource_LocalResource_SyncException() {
val outer = mockk<LocalResource<*>>()
val inner = mockk<LocalResource<*>>()
val outer = mockk<LocalResource>()
val inner = mockk<LocalResource>()
val e = SyncException(Exception())
val result = assertSyncException {
@@ -52,7 +52,7 @@ class SyncExceptionTest {
@Test
fun testWrapWithLocalResource_RemoteResource_Exception() {
val local = mockk<LocalResource<*>>()
val local = mockk<LocalResource>()
val remote = mockk<HttpUrl>()
val e = Exception()
@@ -71,7 +71,7 @@ class SyncExceptionTest {
@Test
fun testWrapWithLocalResource_RemoteResource_SyncException() {
val local = mockk<LocalResource<*>>()
val local = mockk<LocalResource>()
val remote = mockk<HttpUrl>()
val e = SyncException(Exception())
@@ -92,7 +92,7 @@ class SyncExceptionTest {
@Test
fun testWrapWithRemoteResource_LocalResource_Exception() {
val remote = mockk<HttpUrl>()
val local = mockk<LocalResource<*>>()
val local = mockk<LocalResource>()
val e = Exception()
val result = assertSyncException {
@@ -111,7 +111,7 @@ class SyncExceptionTest {
@Test
fun testWrapWithRemoteResource_LocalResource_SyncException() {
val remote = mockk<HttpUrl>()
val local = mockk<LocalResource<*>>()
val local = mockk<LocalResource>()
val e = SyncException(Exception())
val result = assertSyncException {