You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
etesync-android/app/src/main/java/com/etesync/syncadapter/EtebaseLocalCache.kt

172 lines
5.8 KiB

package com.etesync.syncadapter
import android.content.Context
import com.etebase.client.*
import com.etebase.client.Collection
import okhttp3.OkHttpClient
import java.io.File
import java.util.*
/*
File structure:
cache_dir/
user1/ <--- the name of the user
stoken <-- the stokens of the collection fetch
cols/
UID1/ - The uid of the first col
...
UID2/ - The uid of the second col
col <-- the col itself
stoken <-- the stoken of the items fetch
items/
item_uid1 <-- the item with uid 1
item_uid2
...
*/
class EtebaseLocalCache private constructor(context: Context, username: String) {
private val filesDir: File = File(context.filesDir, username)
private val colsDir: File
init {
colsDir = File(filesDir, "cols")
colsDir.mkdirs()
}
private fun getCollectionItemsDir(colUid: String): File {
val colsDir = File(filesDir, "cols")
val colDir = File(colsDir, colUid)
return File(colDir, "items")
}
private fun clearUserCache() {
filesDir.deleteRecursively()
}
fun saveStoken(stoken: String) {
val stokenFile = File(filesDir, "stoken")
stokenFile.writeText(stoken)
}
fun loadStoken(): String? {
val stokenFile = File(filesDir, "stoken")
return if (stokenFile.exists()) stokenFile.readText() else null
}
fun collectionSaveStoken(colUid: String, stoken: String) {
val colDir = File(colsDir, colUid)
val stokenFile = File(colDir, "stoken")
stokenFile.writeText(stoken)
}
fun collectionLoadStoken(colUid: String): String? {
val colDir = File(colsDir, colUid)
val stokenFile = File(colDir, "stoken")
return if (stokenFile.exists()) stokenFile.readText() else null
}
fun collectionList(colMgr: CollectionManager, withDeleted: Boolean = false): List<CachedCollection> {
return colsDir.list().map {
val colDir = File(colsDir, it)
val colFile = File(colDir, "col")
val content = colFile.readBytes()
colMgr.cacheLoad(content)
}.filter { withDeleted || !it.isDeleted }.map{
CachedCollection(it, it.meta)
}
}
fun collectionGet(colMgr: CollectionManager, colUid: String): CachedCollection? {
val colDir = File(colsDir, colUid)
val colFile = File(colDir, "col")
if (!colFile.exists()) {
return null
}
val content = colFile.readBytes()
return colMgr.cacheLoad(content).let {
CachedCollection(it, it.meta)
}
}
fun collectionSet(colMgr: CollectionManager, collection: Collection) {
val colDir = File(colsDir, collection.uid)
colDir.mkdirs()
val colFile = File(colDir, "col")
colFile.writeBytes(colMgr.cacheSaveWithContent(collection))
val itemsDir = getCollectionItemsDir(collection.uid)
itemsDir.mkdirs()
}
fun collectionUnset(colMgr: CollectionManager, colUid: String) {
val colDir = File(colsDir, colUid)
colDir.deleteRecursively()
}
fun itemList(itemMgr: ItemManager, colUid: String, withDeleted: Boolean = false): List<CachedItem> {
val itemsDir = getCollectionItemsDir(colUid)
return itemsDir.list().map {
val itemFile = File(itemsDir, it)
val content = itemFile.readBytes()
itemMgr.cacheLoad(content)
}.filter { withDeleted || !it.isDeleted }.map {
CachedItem(it, it.meta, it.contentString)
}
}
fun itemGet(itemMgr: ItemManager, colUid: String, itemUid: String): CachedItem? {
val itemsDir = getCollectionItemsDir(colUid)
val itemFile = File(itemsDir, itemUid)
if (!itemFile.exists()) {
return null
}
val content = itemFile.readBytes()
return itemMgr.cacheLoad(content).let {
CachedItem(it, it.meta, it.contentString)
}
}
fun itemSet(itemMgr: ItemManager, colUid: String, item: Item) {
val itemsDir = getCollectionItemsDir(colUid)
val itemFile = File(itemsDir, item.uid)
itemFile.writeBytes(itemMgr.cacheSaveWithContent(item))
}
fun itemUnset(itemMgr: ItemManager, colUid: String, itemUid: String) {
val itemsDir = getCollectionItemsDir(colUid)
val itemFile = File(itemsDir, itemUid)
itemFile.delete()
}
companion object {
private val localCacheCache: HashMap<String, EtebaseLocalCache> = HashMap()
fun getInstance(context: Context, username: String): EtebaseLocalCache {
synchronized(localCacheCache) {
val cached = localCacheCache.get(username)
if (cached != null) {
return cached
} else {
val ret = EtebaseLocalCache(context, username)
localCacheCache.set(username, ret)
return ret
}
}
}
fun clearUserCache(context: Context, username: String) {
val localCache = getInstance(context, username)
localCache.clearUserCache()
localCacheCache.remove(username)
}
// FIXME: If we ever cache this we need to cache bust on changePassword
fun getEtebase(context: Context, httpClient: OkHttpClient, settings: AccountSettings): Account {
val client = Client.create(httpClient, settings.uri?.toString())
return Account.restore(client, settings.etebaseSession!!, null)
}
}
}
data class CachedCollection(val col: Collection, val meta: CollectionMetadata)
data class CachedItem(val item: Item, val meta: ItemMetadata, val content: String)