Introduce ContentMapper, allowing to map a content directly without going through an event entity.

This commit is contained in:
ganfra 2018-12-17 18:24:01 +01:00
parent d9e24558ec
commit 0f667fe6e8
3 changed files with 57 additions and 52 deletions

View File

@ -0,0 +1,20 @@
package im.vector.matrix.android.internal.database.mapper

import im.vector.matrix.android.api.session.events.model.Content
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.internal.di.MoshiProvider

internal object ContentMapper {

private val moshi = MoshiProvider.providesMoshi()
private val adapter = moshi.adapter<Content>(Event.CONTENT_TYPE)

fun map(content: String?): Content? {
return adapter.fromJson(content ?: "")
}

fun map(content: Content?): String {
return adapter.toJson(content)
}

}

View File

@ -3,17 +3,23 @@ package im.vector.matrix.android.internal.database.mapper
import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.UnsignedData import im.vector.matrix.android.api.session.events.model.UnsignedData
import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.di.MoshiProvider




internal object EventMapper { internal object EventMapper {


private val moshi = MoshiProvider.providesMoshi()
private val adapter = moshi.adapter<Map<String, Any>>(Event.CONTENT_TYPE)


fun map(event: Event): EventEntity { fun map(event: Event): EventEntity {
val eventEntity = EventEntity() val eventEntity = EventEntity()
fill(eventEntity, with = event) eventEntity.eventId = event.eventId ?: ""
eventEntity.content = ContentMapper.map(event.content)
val resolvedPrevContent = event.prevContent ?: event.unsignedData?.prevContent
eventEntity.prevContent = ContentMapper.map(resolvedPrevContent)
eventEntity.stateKey = event.stateKey
eventEntity.type = event.type
eventEntity.sender = event.sender
eventEntity.originServerTs = event.originServerTs
eventEntity.redacts = event.redacts
eventEntity.age = event.unsignedData?.age ?: event.originServerTs
return eventEntity return eventEntity
} }


@ -21,8 +27,8 @@ internal object EventMapper {
return Event( return Event(
type = eventEntity.type, type = eventEntity.type,
eventId = eventEntity.eventId, eventId = eventEntity.eventId,
content = adapter.fromJson(eventEntity.content), content = ContentMapper.map(eventEntity.content),
prevContent = adapter.fromJson(eventEntity.prevContent ?: ""), prevContent = ContentMapper.map(eventEntity.prevContent),
originServerTs = eventEntity.originServerTs, originServerTs = eventEntity.originServerTs,
sender = eventEntity.sender, sender = eventEntity.sender,
stateKey = eventEntity.stateKey, stateKey = eventEntity.stateKey,
@ -32,18 +38,6 @@ internal object EventMapper {
) )
} }


fun fill(eventEntity: EventEntity, with: Event) {
eventEntity.eventId = with.eventId ?: ""
eventEntity.content = adapter.toJson(with.content)
val resolvedPrevContent = with.prevContent ?: with.unsignedData?.prevContent
eventEntity.prevContent = adapter.toJson(resolvedPrevContent)
eventEntity.stateKey = with.stateKey
eventEntity.type = with.type
eventEntity.sender = with.sender
eventEntity.originServerTs = with.originServerTs
eventEntity.redacts = with.redacts
eventEntity.age = with.unsignedData?.age ?: with.originServerTs
}


} }


@ -54,7 +48,3 @@ internal fun EventEntity.asDomain(): Event {
internal fun Event.asEntity(): EventEntity { internal fun Event.asEntity(): EventEntity {
return EventMapper.map(this) return EventMapper.map(this)
} }

internal fun EventEntity.fillWith(event: Event) {
EventMapper.fill(this, with = event)
}

View File

@ -3,13 +3,11 @@ package im.vector.matrix.android.internal.session.events.prune
import android.content.Context import android.content.Context
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import arrow.core.Option
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.mapper.ContentMapper
import im.vector.matrix.android.internal.database.mapper.asEntity
import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.util.WorkerParamsFactory import im.vector.matrix.android.internal.util.WorkerParamsFactory
@ -33,7 +31,7 @@ internal class PruneEventWorker(context: Context,


override fun doWork(): Result { override fun doWork(): Result {
val params = WorkerParamsFactory.fromData<Params>(inputData) val params = WorkerParamsFactory.fromData<Params>(inputData)
?: return Result.failure() ?: return Result.failure()


val result = monarchy.tryTransactionAsync { realm -> val result = monarchy.tryTransactionAsync { realm ->
params.updateIndexes.forEach { index -> params.updateIndexes.forEach { index ->
@ -48,39 +46,36 @@ internal class PruneEventWorker(context: Context,
if (redactionEvent == null || redactionEvent.redacts.isNullOrEmpty()) { if (redactionEvent == null || redactionEvent.redacts.isNullOrEmpty()) {
return return
} }
val eventToPrune = EventEntity.where(realm, eventId = redactionEvent.redacts).findFirst()?.asDomain() val eventToPrune = EventEntity.where(realm, eventId = redactionEvent.redacts).findFirst()
?: return ?: return


val allowedKeys = computeAllowedKeys(eventToPrune.type) val allowedKeys = computeAllowedKeys(eventToPrune.type)
val prunedContent = allowedKeys.fold( if (allowedKeys.isNotEmpty()) {
{ eventToPrune.content }, val prunedContent = ContentMapper.map(eventToPrune.content)?.filterKeys { key -> allowedKeys.contains(key) }
{ eventToPrune.content?.filterKeys { key -> it.contains(key) } } eventToPrune.content = ContentMapper.map(prunedContent)
) }
val eventToPruneEntity = eventToPrune.copy(content = prunedContent).asEntity()
realm.insertOrUpdate(eventToPruneEntity)
} }


private fun computeAllowedKeys(type: String): Option<List<String>> { private fun computeAllowedKeys(type: String): List<String> {
// Add filtered content, allowed keys in content depends on the event type // Add filtered content, allowed keys in content depends on the event type
val result = when (type) { return when (type) {
EventType.STATE_ROOM_MEMBER -> listOf("membership") EventType.STATE_ROOM_MEMBER -> listOf("membership")
EventType.STATE_ROOM_CREATE -> listOf("creator") EventType.STATE_ROOM_CREATE -> listOf("creator")
EventType.STATE_ROOM_JOIN_RULES -> listOf("join_rule") EventType.STATE_ROOM_JOIN_RULES -> listOf("join_rule")
EventType.STATE_ROOM_POWER_LEVELS -> listOf("users", EventType.STATE_ROOM_POWER_LEVELS -> listOf("users",
"users_default", "users_default",
"events", "events",
"events_default", "events_default",
"state_default", "state_default",
"ban", "ban",
"kick", "kick",
"redact", "redact",
"invite") "invite")
EventType.STATE_ROOM_ALIASES -> listOf("aliases") EventType.STATE_ROOM_ALIASES -> listOf("aliases")
EventType.STATE_CANONICAL_ALIAS -> listOf("alias") EventType.STATE_CANONICAL_ALIAS -> listOf("alias")
EventType.FEEDBACK -> listOf("type", "target_event_id") EventType.FEEDBACK -> listOf("type", "target_event_id")
else -> null else -> emptyList()
} }
return Option.fromNullable(result)
} }


} }