Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1882dee0 authored by Ricki Hirner's avatar Ricki Hirner
Browse files

Process home-set display names

parent fb7012e7
Loading
Loading
Loading
Loading
+64 −0
Original line number Diff line number Diff line
package at.bitfire.davdroid.model

import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.test.platform.app.InstrumentationRegistry
import okhttp3.HttpUrl
import org.junit.After
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test

class DaoToolsTest {

    private lateinit var db: AppDatabase

    @Before
    fun createDb() {
        val context = InstrumentationRegistry.getInstrumentation().context
        db = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java).build()
    }

    @After
    fun closeDb() {
        db.close()
    }

    @Test
    fun testSyncAll() {
        val serviceDao = db.serviceDao()
        val service = Service(id=0, accountName="test", type=Service.TYPE_CALDAV, principal = null)
        service.id = serviceDao.insertOrReplace(service)

        val homeSetDao = db.homeSetDao()
        val entry1 = HomeSet(id=1, serviceId=service.id, url=HttpUrl.get("https://example.com/1"))
        val entry3 = HomeSet(id=3, serviceId=service.id, url=HttpUrl.get("https://example.com/3"))
        val oldItems = listOf(
                entry1,
                HomeSet(id=2, serviceId=service.id, url=HttpUrl.get("https://example.com/2")),
                entry3
        )
        homeSetDao.insert(oldItems)

        val newItems = mutableMapOf<HttpUrl, HomeSet>()
        newItems[entry1.url] = entry1

        // no id, because identity is given by the url
        val updated = HomeSet(id=0, serviceId=service.id,
                url=HttpUrl.get("https://example.com/2"), displayName="Updated Entry")
        newItems[updated.url] = updated

        val created = HomeSet(id=4, serviceId=service.id, url=HttpUrl.get("https://example.com/4"))
        newItems[created.url] = created

        DaoTools(homeSetDao).syncAll(oldItems, newItems) { it.url }

        val afterSync = homeSetDao.getByService(service.id)
        assertEquals(afterSync.size, 3)
        assertFalse(afterSync.contains(entry3))
        assertTrue(afterSync.contains(entry1))
        assertTrue(afterSync.contains(updated))
        assertTrue(afterSync.contains(created))
    }

}
 No newline at end of file
+21 −54
Original line number Diff line number Diff line
@@ -23,10 +23,8 @@ import at.bitfire.dav4jvm.UrlUtils
import at.bitfire.dav4jvm.exception.HttpException
import at.bitfire.dav4jvm.property.*
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.model.AppDatabase
import at.bitfire.davdroid.model.*
import at.bitfire.davdroid.model.Collection
import at.bitfire.davdroid.model.HomeSet
import at.bitfire.davdroid.model.Service
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.davdroid.ui.DebugInfoActivity
import at.bitfire.davdroid.ui.NotificationUtils
@@ -146,14 +144,8 @@ class DavService: android.app.Service() {
        val service = db.serviceDao().get(serviceId) ?: throw IllegalArgumentException("Service not found")
        val account = Account(service.accountName, getString(R.string.account_type))

        val homeSets = homeSetDao.getByService(serviceId)
                .map { it.url }
                .toMutableSet()

        val collections = mutableMapOf<HttpUrl, Collection>()
        collectionDao.getByService(serviceId).forEach {
            collections[it.url] = it
        }
        val homeSets = homeSetDao.getByService(serviceId).associateBy { it.url }.toMutableMap()
        val collections = collectionDao.getByService(serviceId).associateBy { it.url }.toMutableMap()

        /**
         * Checks if the given URL defines home sets and adds them to the home set list.
@@ -199,11 +191,12 @@ class DavService: android.app.Service() {
            when (service.type) {
                Service.TYPE_CARDDAV ->
                    try {
                        dav.propfind(0, AddressbookHomeSet.NAME, GroupMembership.NAME) { response, _ ->
                        dav.propfind(0, DisplayName.NAME, AddressbookHomeSet.NAME, GroupMembership.NAME) { response, _ ->
                            response[AddressbookHomeSet::class.java]?.let { homeSet ->
                                for (href in homeSet.hrefs)
                                    dav.location.resolve(href)?.let {
                                        homeSets += UrlUtils.withTrailingSlash(it)
                                        val foundUrl = UrlUtils.withTrailingSlash(it)
                                        homeSets[foundUrl] = HomeSet(0, service.id, foundUrl, response[DisplayName::class.java]?.displayName)
                                    }
                            }

@@ -218,11 +211,12 @@ class DavService: android.app.Service() {
                    }
                Service.TYPE_CALDAV -> {
                    try {
                        dav.propfind(0, CalendarHomeSet.NAME, CalendarProxyReadFor.NAME, CalendarProxyWriteFor.NAME, GroupMembership.NAME) { response, _ ->
                        dav.propfind(0, DisplayName.NAME, CalendarHomeSet.NAME, CalendarProxyReadFor.NAME, CalendarProxyWriteFor.NAME, GroupMembership.NAME) { response, _ ->
                            response[CalendarHomeSet::class.java]?.let { homeSet ->
                                for (href in homeSet.hrefs)
                                    dav.location.resolve(href)?.let {
                                        homeSets += UrlUtils.withTrailingSlash(it)
                                        val foundUrl = UrlUtils.withTrailingSlash(it)
                                        homeSets[foundUrl] = HomeSet(0, service.id, foundUrl, response[DisplayName::class.java]?.displayName)
                                    }
                            }

@@ -244,46 +238,18 @@ class DavService: android.app.Service() {

        @Transaction
        fun saveHomesets() {
            val oldHomesets = homeSetDao.getByService(serviceId)
            oldHomesets.forEach { oldHomeset ->
                val url = oldHomeset.url
                if (homeSets.contains(url))
                    // URL is the same in oldHomesets and newHomesets, remove from "homesets" (which will be added later)
                    homeSets.remove(url)
                else
                    // URL is not in newHomesets, delete from database
                    homeSetDao.delete(oldHomeset)
            }
            // insert new homesets
            homeSetDao.insert(homeSets.map { url ->
                HomeSet(0, serviceId, url)
            })
            DaoTools(homeSetDao).syncAll(
                    homeSetDao.getByService(serviceId),
                    homeSets
            ) { it.url }
        }

        @Transaction
        fun saveCollections() {
            val oldCollections = collectionDao.getByService(serviceId)
            oldCollections.forEach { oldCollection ->
                val url = oldCollection.url
                val matchingNewCollection = collections[url]
                if (matchingNewCollection != null) {
                    // old URL exists in newCollections, update database if content has been changed
                    matchingNewCollection.id = oldCollection.id
                    matchingNewCollection.serviceId = oldCollection.serviceId
                    if (matchingNewCollection != oldCollection)
                        collectionDao.update(matchingNewCollection)

                    // remove from "collections" (which will be added later)
                    collections.remove(url)
                } else
                    // URL is not in newCollections, delete from database
                    collectionDao.delete(oldCollection)
            }
            // insert new collections
            collections.forEach { (_, collection) ->
                collection.serviceId = serviceId
            }
            collectionDao.insert(collections.values.toList())
            DaoTools(collectionDao).syncAll(
                    collectionDao.getByService(serviceId),
                    collections
            ) { it.url }
        }

        fun saveResults() {
@@ -320,15 +286,16 @@ class DavService: android.app.Service() {
                // now refresh collections (taken from home sets)
                val itHomeSets = homeSets.iterator()
                while (itHomeSets.hasNext()) {
                    val homeSetUrl = itHomeSets.next()
                    Logger.log.fine("Listing home set $homeSetUrl")
                    val homeSet = itHomeSets.next()
                    Logger.log.fine("Listing home set ${homeSet.key}")

                    try {
                        DavResource(httpClient, homeSetUrl).propfind(1, *DAV_COLLECTION_PROPERTIES) { response, _ ->
                        DavResource(httpClient, homeSet.key).propfind(1, *DAV_COLLECTION_PROPERTIES) { response, _ ->
                            if (!response.isSuccess())
                                return@propfind

                            val info = Collection.fromDavResponse(response) ?: return@propfind
                            info.serviceId = serviceId
                            info.confirmed = true
                            Logger.log.log(Level.FINE, "Found collection", info)

+9 −2
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ import at.bitfire.davdroid.log.Logger
    Service::class,
    HomeSet::class,
    Collection::class
], version = 6)
], version = 7)
@TypeConverters(Converters::class)
abstract class AppDatabase: RoomDatabase() {

@@ -38,7 +38,8 @@ abstract class AppDatabase: RoomDatabase() {
                            Migration2_3,
                            Migration3_4,
                            Migration4_5,
                            Migration5_6
                            Migration5_6,
                            Migration6_7
                    )
                    .fallbackToDestructiveMigration()   // as a last fallback, recreate database instead of crashing
                    .build()
@@ -99,6 +100,12 @@ abstract class AppDatabase: RoomDatabase() {

    // migrations

    object Migration6_7: Migration(6, 7) {
        override fun migrate(db: SupportSQLiteDatabase) {
            db.execSQL("ALTER TABLE homeset ADD COLUMN displayName TEXT DEFAULT NULL")
        }
    }

    object Migration5_6: Migration(5, 6) {
        override fun migrate(db: SupportSQLiteDatabase) {
            val sql = arrayOf(
+2 −2
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ import okhttp3.HttpUrl
)
data class Collection(
    @PrimaryKey(autoGenerate = true)
    var id: Long = 0,
    override var id: Long = 0,

    var serviceId: Long = 0,

@@ -52,7 +52,7 @@ data class Collection(
    /** whether this collection has been selected for synchronization */
    var sync: Boolean = false

) {
): IdEntity() {

    companion object {

+2 −11
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ import androidx.paging.DataSource
import androidx.room.*

@Dao
interface CollectionDao {
interface CollectionDao: SyncableDao<Collection> {

    @Query("SELECT * FROM collection WHERE id=:id")
    fun get(id: Long): Collection?
@@ -37,13 +37,4 @@ interface CollectionDao {
    @Insert
    fun insert(collection: Collection)

    @Insert
    fun insert(collections: List<Collection>)

    @Update
    fun update(collection: Collection)

    @Delete
    fun delete(collection: Collection)

}
Loading