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.UnsignedData
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.di.MoshiProvider
internal object EventMapper {
private val moshi = MoshiProvider.providesMoshi()
private val adapter = moshi.adapter<Map<String, Any>>(Event.CONTENT_TYPE)
fun map(event: Event): 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
}
@ -21,8 +27,8 @@ internal object EventMapper {
return Event(
type = eventEntity.type,
eventId = eventEntity.eventId,
content = adapter.fromJson(eventEntity.content),
prevContent = adapter.fromJson(eventEntity.prevContent ?: ""),
content = ContentMapper.map(eventEntity.content),
prevContent = ContentMapper.map(eventEntity.prevContent),
originServerTs = eventEntity.originServerTs,
sender = eventEntity.sender,
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 {
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 androidx.work.Worker
import androidx.work.WorkerParameters
import arrow.core.Option
import com.squareup.moshi.JsonClass
import com.zhuinden.monarchy.Monarchy
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.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.mapper.asEntity
import im.vector.matrix.android.internal.database.mapper.ContentMapper
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.util.WorkerParamsFactory
@ -33,7 +31,7 @@ internal class PruneEventWorker(context: Context,
override fun doWork(): Result {
val params = WorkerParamsFactory.fromData<Params>(inputData)
?: return Result.failure()
?: return Result.failure()
val result = monarchy.tryTransactionAsync { realm ->
params.updateIndexes.forEach { index ->
@ -48,39 +46,36 @@ internal class PruneEventWorker(context: Context,
if (redactionEvent == null || redactionEvent.redacts.isNullOrEmpty()) {
return
}
val eventToPrune = EventEntity.where(realm, eventId = redactionEvent.redacts).findFirst()?.asDomain()
?: return
val eventToPrune = EventEntity.where(realm, eventId = redactionEvent.redacts).findFirst()
?: return
val allowedKeys = computeAllowedKeys(eventToPrune.type)
val prunedContent = allowedKeys.fold(
{ eventToPrune.content },
{ eventToPrune.content?.filterKeys { key -> it.contains(key) } }
)
val eventToPruneEntity = eventToPrune.copy(content = prunedContent).asEntity()
realm.insertOrUpdate(eventToPruneEntity)
if (allowedKeys.isNotEmpty()) {
val prunedContent = ContentMapper.map(eventToPrune.content)?.filterKeys { key -> allowedKeys.contains(key) }
eventToPrune.content = ContentMapper.map(prunedContent)
}
}
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
val result = when (type) {
EventType.STATE_ROOM_MEMBER -> listOf("membership")
EventType.STATE_ROOM_CREATE -> listOf("creator")
EventType.STATE_ROOM_JOIN_RULES -> listOf("join_rule")
return when (type) {
EventType.STATE_ROOM_MEMBER -> listOf("membership")
EventType.STATE_ROOM_CREATE -> listOf("creator")
EventType.STATE_ROOM_JOIN_RULES -> listOf("join_rule")
EventType.STATE_ROOM_POWER_LEVELS -> listOf("users",
"users_default",
"events",
"events_default",
"state_default",
"ban",
"kick",
"redact",
"invite")
EventType.STATE_ROOM_ALIASES -> listOf("aliases")
EventType.STATE_CANONICAL_ALIAS -> listOf("alias")
EventType.FEEDBACK -> listOf("type", "target_event_id")
else -> null
"users_default",
"events",
"events_default",
"state_default",
"ban",
"kick",
"redact",
"invite")
EventType.STATE_ROOM_ALIASES -> listOf("aliases")
EventType.STATE_CANONICAL_ALIAS -> listOf("alias")
EventType.FEEDBACK -> listOf("type", "target_event_id")
else -> emptyList()
}
return Option.fromNullable(result)
}
}