diff --git a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/ClientSession.kt b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/ClientSession.kt new file mode 100644 index 0000000000000000000000000000000000000000..d194481a26865333203fda8109aa17db08db7f18 --- /dev/null +++ b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/ClientSession.kt @@ -0,0 +1,201 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ +package de.justjanne.libquassel.client + +import de.justjanne.libquassel.annotations.ProtocolSide +import de.justjanne.libquassel.protocol.exceptions.RpcInvocationFailedException +import de.justjanne.libquassel.protocol.models.Message +import de.justjanne.libquassel.protocol.models.SignalProxyMessage +import de.justjanne.libquassel.protocol.models.StatusMessage +import de.justjanne.libquassel.protocol.models.ids.IdentityId +import de.justjanne.libquassel.protocol.models.ids.NetworkId +import de.justjanne.libquassel.protocol.serializers.qt.StringSerializerUtf8 +import de.justjanne.libquassel.protocol.syncables.HeartBeatHandler +import de.justjanne.libquassel.protocol.syncables.ObjectRepository +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.common.AliasManager +import de.justjanne.libquassel.protocol.syncables.common.BacklogManager +import de.justjanne.libquassel.protocol.syncables.common.BufferSyncer +import de.justjanne.libquassel.protocol.syncables.common.BufferViewManager +import de.justjanne.libquassel.protocol.syncables.common.CoreInfo +import de.justjanne.libquassel.protocol.syncables.common.DccConfig +import de.justjanne.libquassel.protocol.syncables.common.HighlightRuleManager +import de.justjanne.libquassel.protocol.syncables.common.Identity +import de.justjanne.libquassel.protocol.syncables.common.IgnoreListManager +import de.justjanne.libquassel.protocol.syncables.common.IrcListHelper +import de.justjanne.libquassel.protocol.syncables.common.Network +import de.justjanne.libquassel.protocol.syncables.common.NetworkConfig +import de.justjanne.libquassel.protocol.syncables.common.RpcHandler +import de.justjanne.libquassel.protocol.syncables.invoker.Invokers +import de.justjanne.libquassel.protocol.syncables.state.NetworkState +import de.justjanne.libquassel.protocol.util.update +import de.justjanne.libquassel.protocol.variant.QVariantMap +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import java.nio.ByteBuffer + +class ClientSession : Session { + override val protocolSide = ProtocolSide.CLIENT + override val objectRepository = ObjectRepository() + override val rpcHandler = ClientRpcHandler(this) + val heartBeatHandler = HeartBeatHandler() + + override fun network(id: NetworkId) = state().networks[id] + override fun addNetwork(id: NetworkId) { + val network = Network(this, state = NetworkState(id)) + synchronize(network) + state.update { + copy(networks = networks + Pair(id, network)) + } + } + + override fun removeNetwork(id: NetworkId) { + val network = network(id) ?: return + stopSynchronize(network) + state.update { + copy(networks = networks - id) + } + } + + override fun identity(id: IdentityId) = state().identities[id] + + override fun addIdentity(properties: QVariantMap) { + val identity = Identity(this) + identity.fromVariantMap(properties) + synchronize(identity) + state.update { + copy(identities = identities + Pair(identity.id(), identity)) + } + } + + override fun removeIdentity(id: IdentityId) { + val identity = identity(id) ?: return + stopSynchronize(identity) + state.update { + copy(identities = identities - id) + } + } + + override val aliasManager get() = state().aliasManager + + override val backlogManager get() = state().backlogManager + + override val bufferSyncer get() = state().bufferSyncer + + override val bufferViewManager get() = state().bufferViewManager + + override val highlightRuleManager get() = state().highlightRuleManager + + override val ignoreListManager get() = state().ignoreListManager + + override val ircListHelper get() = state().ircListHelper + + override val coreInfo get() = state().coreInfo + + override val dccConfig get() = state().dccConfig + + override val networkConfig get() = state().networkConfig + + override fun synchronize(syncable: SyncableStub) { + if (objectRepository.add(syncable)) { + dispatch(SignalProxyMessage.InitRequest(syncable.className, syncable.objectName)) + } + } + + override fun stopSynchronize(syncable: SyncableStub) { + objectRepository.remove(syncable) + } + + override fun emit(message: SignalProxyMessage) { + TODO("Not yet implemented") + } + + override fun dispatch(message: SignalProxyMessage) { + when (message) { + is SignalProxyMessage.HeartBeat -> emit(SignalProxyMessage.HeartBeatReply(message.timestamp)) + is SignalProxyMessage.HeartBeatReply -> heartBeatHandler.recomputeLatency(message.timestamp, force = true) + is SignalProxyMessage.InitData -> objectRepository.init( + objectRepository.find(message.className, message.objectName) ?: return, + message.initData + ) + is SignalProxyMessage.InitRequest -> { + // Ignore incoming requests, we’re a client, we shouldn’t ever receive these + } + is SignalProxyMessage.Rpc -> { + val invoker = Invokers.get(ProtocolSide.CLIENT, "RpcHandler") + ?: throw RpcInvocationFailedException.InvokerNotFoundException("RpcHandler") + invoker.invoke(rpcHandler, message.slotName, message.params) + } + is SignalProxyMessage.Sync -> { + val invoker = Invokers.get(ProtocolSide.CLIENT, message.className) + ?: throw RpcInvocationFailedException.InvokerNotFoundException(message.className) + val syncable = objectRepository.find(message.className, message.objectName) + ?: throw RpcInvocationFailedException.SyncableNotFoundException(message.className, message.objectName) + invoker.invoke(syncable, message.slotName, message.params) + } + } + } + + @Suppress("NOTHING_TO_INLINE") + inline fun state(): ClientSessionState = state.value + + @Suppress("NOTHING_TO_INLINE") + inline fun flow(): Flow<ClientSessionState> = state + + @PublishedApi + internal val state = MutableStateFlow( + ClientSessionState( + networks = mapOf(), + identities = mapOf(), + aliasManager = AliasManager(this), + backlogManager = BacklogManager(this), + bufferSyncer = BufferSyncer(this), + bufferViewManager = BufferViewManager(this), + highlightRuleManager = HighlightRuleManager(this), + ignoreListManager = IgnoreListManager(this), + ircListHelper = IrcListHelper(this), + coreInfo = CoreInfo(this), + dccConfig = DccConfig(this), + networkConfig = NetworkConfig(this) + ) + ) + + class ClientRpcHandler(session: Session) : RpcHandler(session) { + override fun objectRenamed(classname: ByteBuffer, newName: String?, oldName: String?) { + val objectRepository = session?.objectRepository ?: return + val className = StringSerializerUtf8.deserializeRaw(classname) + val syncable = objectRepository.find(className, oldName ?: return) + ?: return + objectRepository.rename(syncable, newName ?: return) + } + + override fun displayMsg(message: Message) { + messages.tryEmit(message) + } + + override fun displayStatusMsg(net: String?, msg: String?) { + statusMessage.tryEmit(StatusMessage(net, msg ?: return)) + } + + @Suppress("NOTHING_TO_INLINE") + inline fun messages(): Flow<Message> = messages + + @PublishedApi + internal val messages = MutableSharedFlow<Message>() + + @Suppress("NOTHING_TO_INLINE") + inline fun statusMessage(): StateFlow<StatusMessage?> = statusMessage + + @PublishedApi + internal val statusMessage = MutableStateFlow<StatusMessage?>(null) + } +} diff --git a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/ClientSessionState.kt b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/ClientSessionState.kt new file mode 100644 index 0000000000000000000000000000000000000000..179ee40dafc52b1f025cd6ee2b615ef7bfe814c4 --- /dev/null +++ b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/ClientSessionState.kt @@ -0,0 +1,40 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.client + +import de.justjanne.libquassel.protocol.models.ids.IdentityId +import de.justjanne.libquassel.protocol.models.ids.NetworkId +import de.justjanne.libquassel.protocol.syncables.common.AliasManager +import de.justjanne.libquassel.protocol.syncables.common.BacklogManager +import de.justjanne.libquassel.protocol.syncables.common.BufferSyncer +import de.justjanne.libquassel.protocol.syncables.common.BufferViewManager +import de.justjanne.libquassel.protocol.syncables.common.CoreInfo +import de.justjanne.libquassel.protocol.syncables.common.DccConfig +import de.justjanne.libquassel.protocol.syncables.common.HighlightRuleManager +import de.justjanne.libquassel.protocol.syncables.common.Identity +import de.justjanne.libquassel.protocol.syncables.common.IgnoreListManager +import de.justjanne.libquassel.protocol.syncables.common.IrcListHelper +import de.justjanne.libquassel.protocol.syncables.common.Network +import de.justjanne.libquassel.protocol.syncables.common.NetworkConfig + +data class ClientSessionState( + val networks: Map<NetworkId, Network>, + val identities: Map<IdentityId, Identity>, + val aliasManager: AliasManager, + val backlogManager: BacklogManager, + val bufferSyncer: BufferSyncer, + val bufferViewManager: BufferViewManager, + val ignoreListManager: IgnoreListManager, + val highlightRuleManager: HighlightRuleManager, + val ircListHelper: IrcListHelper, + val coreInfo: CoreInfo, + val dccConfig: DccConfig, + val networkConfig: NetworkConfig +) diff --git a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/syncables/ClientBacklogManager.kt b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/syncables/ClientBacklogManager.kt index 989f2816391532e8c01dfdbd15d4d27fb9a02f54..d66caabf9f2fc58bd5cdd6a96407163a967b9a9c 100644 --- a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/syncables/ClientBacklogManager.kt +++ b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/syncables/ClientBacklogManager.kt @@ -16,8 +16,8 @@ import de.justjanne.libquassel.protocol.models.flags.MessageType import de.justjanne.libquassel.protocol.models.flags.MessageTypes import de.justjanne.libquassel.protocol.models.ids.BufferId import de.justjanne.libquassel.protocol.models.ids.MsgId -import de.justjanne.libquassel.protocol.syncables.BacklogManager import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.common.BacklogManager import de.justjanne.libquassel.protocol.variant.QVariantList import kotlin.coroutines.Continuation import kotlin.coroutines.resume diff --git a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/syncables/ClientIrcListHelper.kt b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/syncables/ClientIrcListHelper.kt index e615644f42955d13c4e054c1524676985fd79e05..a46a04bebef2ac8ec8217b002cfb5cd00788e0dd 100644 --- a/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/syncables/ClientIrcListHelper.kt +++ b/libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/syncables/ClientIrcListHelper.kt @@ -12,8 +12,8 @@ package de.justjanne.libquassel.client.syncables import de.justjanne.libquassel.client.exceptions.IrcListException import de.justjanne.libquassel.protocol.models.QStringList import de.justjanne.libquassel.protocol.models.ids.NetworkId -import de.justjanne.libquassel.protocol.syncables.IrcListHelper import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.common.IrcListHelper import de.justjanne.libquassel.protocol.variant.QVariantList import de.justjanne.libquassel.protocol.variant.into import kotlin.coroutines.Continuation diff --git a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/Constants.kt b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/Constants.kt new file mode 100644 index 0000000000000000000000000000000000000000..3df1190c7db3be3ca5f4e1baeae856218f7b75ea --- /dev/null +++ b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/Constants.kt @@ -0,0 +1,64 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.generator + +import com.squareup.kotlinpoet.ANY +import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.MAP +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import com.squareup.kotlinpoet.STRING +import de.justjanne.libquassel.annotations.ProtocolSide +import de.justjanne.libquassel.generator.rpcmodel.RpcModel + +object Constants { + fun invokerName(model: RpcModel.ObjectModel, side: ProtocolSide) = ClassName( + TYPENAME_INVOKER.packageName, + "${model.rpcName}${side.name.toLowerCase().capitalize()}Invoker" + ) + + val TYPENAME_ANY = ANY.copy(nullable = true) + val TYPENAME_SYNCABLESTUB = ClassName( + "de.justjanne.libquassel.protocol.syncables", + "SyncableStub" + ) + val TYPENAME_INVOKER = ClassName( + "de.justjanne.libquassel.protocol.syncables.invoker", + "Invoker" + ) + val TYPENAME_INVOKERREGISTRY = ClassName( + "de.justjanne.libquassel.protocol.syncables.invoker", + "InvokerRegistry" + ) + val TYPENAME_INVOKERMAP = MAP.parameterizedBy(STRING, TYPENAME_INVOKER) + val TYPENAME_UNKNOWN_METHOD_EXCEPTION = ClassName( + "de.justjanne.libquassel.protocol.exceptions", + "RpcInvocationFailedException", "UnknownMethodException" + ) + val TYPENAME_WRONG_OBJECT_TYPE_EXCEPTION = ClassName( + "de.justjanne.libquassel.protocol.exceptions", + "RpcInvocationFailedException", "WrongObjectTypeException" + ) + val TYPENAME_QVARIANTLIST = ClassName( + "de.justjanne.libquassel.protocol.variant", + "QVariantList" + ) + val TYPENAME_QVARIANT_INTOORTHROW = ClassName( + "de.justjanne.libquassel.protocol.variant", + "intoOrThrow" + ) + val TYPENAME_GENERATED = ClassName( + "de.justjanne.libquassel.annotations", + "Generated" + ) + + init { + System.setProperty("idea.io.use.nio2", "true") + } +} diff --git a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/InvokerProcessor.kt b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/InvokerProcessor.kt index 1c43f8d1c30218d5a6caaeebd9a60d98f0fd44b1..a154144c21f58f09fc9bc402a687bb0b65313a8d 100644 --- a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/InvokerProcessor.kt +++ b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/InvokerProcessor.kt @@ -19,6 +19,7 @@ import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.generator.visitors.KSDeclarationParser import de.justjanne.libquassel.generator.visitors.KotlinSaver import de.justjanne.libquassel.generator.visitors.RpcModelProcessor +import de.justjanne.libquassel.generator.visitors.RpcObjectCollector class InvokerProcessor : SymbolProcessor { lateinit var codeGenerator: CodeGenerator @@ -35,15 +36,21 @@ class InvokerProcessor : SymbolProcessor { } override fun process(resolver: Resolver): List<KSAnnotated> { - resolver.getSymbolsWithAnnotation(SyncedObject::class.java.canonicalName) - .mapNotNull { it.accept(KSDeclarationParser(resolver, logger), Unit) } - .flatMap { - listOfNotNull( - it.accept(RpcModelProcessor(), ProtocolSide.CLIENT), - it.accept(RpcModelProcessor(), ProtocolSide.CORE), - ) - } - .map { it.accept(KotlinSaver(), codeGenerator) } + val annotationModels = resolver.getSymbolsWithAnnotation(SyncedObject::class.java.canonicalName) + val rpcModels = annotationModels.mapNotNull { it.accept(KSDeclarationParser(resolver, logger), Unit) } + val invokerFiles = rpcModels.flatMap { + listOfNotNull( + it.accept(RpcModelProcessor(), ProtocolSide.CLIENT), + it.accept(RpcModelProcessor(), ProtocolSide.CORE), + ) + InvokerRegistryGenerator.generateRegistry( + RpcObjectCollector().apply { + rpcModels.forEach { it.accept(this, Unit) } + }.objects + ) + } + invokerFiles.forEach { + it.accept(KotlinSaver(), codeGenerator) + } return emptyList() } diff --git a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/InvokerRegistryGenerator.kt b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/InvokerRegistryGenerator.kt new file mode 100644 index 0000000000000000000000000000000000000000..28288873b6df6d6c29e590efe851ce8786105747 --- /dev/null +++ b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/InvokerRegistryGenerator.kt @@ -0,0 +1,67 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.generator + +import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.FileSpec +import com.squareup.kotlinpoet.KModifier +import com.squareup.kotlinpoet.PropertySpec +import com.squareup.kotlinpoet.TypeSpec +import com.squareup.kotlinpoet.buildCodeBlock +import de.justjanne.libquassel.annotations.ProtocolSide +import de.justjanne.libquassel.generator.kotlinmodel.KotlinModel +import de.justjanne.libquassel.generator.rpcmodel.RpcModel +import de.justjanne.libquassel.generator.util.kotlinpoet.withIndent + +object InvokerRegistryGenerator { + private fun generateCodeBlock( + objects: List<RpcModel.ObjectModel>, + side: ProtocolSide + ) = buildCodeBlock { + add("mapOf(\n") + withIndent { + for (syncable in objects) { + addStatement("%S to %T,", syncable.rpcName, Constants.invokerName(syncable, side)) + } + } + if (objects.isEmpty()) { + add("\n") + } + add(")") + } + + fun generateRegistry(objects: List<RpcModel.ObjectModel>): KotlinModel.FileModel { + val name = ClassName( + Constants.TYPENAME_INVOKER.packageName, + "GeneratedInvokerRegistry" + ) + return KotlinModel.FileModel( + objects.map(RpcModel.ObjectModel::source), + FileSpec.builder(name.packageName, name.simpleName) + .addType( + TypeSpec.objectBuilder("GeneratedInvokerRegistry") + .addSuperinterface(Constants.TYPENAME_INVOKERREGISTRY) + .addProperty( + PropertySpec.builder("clientInvokers", Constants.TYPENAME_INVOKERMAP) + .addModifiers(KModifier.OVERRIDE) + .initializer(generateCodeBlock(objects, ProtocolSide.CLIENT)) + .build() + ) + .addProperty( + PropertySpec.builder("coreInvokers", Constants.TYPENAME_INVOKERMAP) + .addModifiers(KModifier.OVERRIDE) + .initializer(generateCodeBlock(objects, ProtocolSide.CORE)) + .build() + ) + .build() + ).build() + ) + } +} diff --git a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/kotlinmodel/KotlinModel.kt b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/kotlinmodel/KotlinModel.kt index e8601cdc4e14f0d1a0e2214a1743d4038a9290f2..4ef05f46aa417e192c5798e6c9e15ba708539c14 100644 --- a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/kotlinmodel/KotlinModel.kt +++ b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/kotlinmodel/KotlinModel.kt @@ -16,7 +16,7 @@ import com.squareup.kotlinpoet.FileSpec sealed class KotlinModel { data class FileModel( - val source: KSClassDeclaration, + val source: List<KSClassDeclaration>, val data: FileSpec ) : KotlinModel() { override fun <D, R> accept(visitor: KotlinModelVisitor<D, R>, data: D) = diff --git a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/KotlinSaver.kt b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/KotlinSaver.kt index 81771943423fd1c88e56cc21706e833e5e8a4c94..6566541fab41e4a1fe24e8d9768a177dbf7c7c1c 100644 --- a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/KotlinSaver.kt +++ b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/KotlinSaver.kt @@ -11,17 +11,32 @@ package de.justjanne.libquassel.generator.visitors import com.google.devtools.ksp.processing.CodeGenerator import com.google.devtools.ksp.processing.Dependencies +import com.google.devtools.ksp.symbol.KSClassDeclaration import de.justjanne.libquassel.generator.kotlinmodel.KotlinModel import de.justjanne.libquassel.generator.kotlinmodel.KotlinModelVisitor +import java.io.IOException class KotlinSaver : KotlinModelVisitor<CodeGenerator, Unit> { + private fun generateDependencies(sources: List<KSClassDeclaration>): Dependencies { + val sourceFiles = sources.mapNotNull(KSClassDeclaration::containingFile) + return Dependencies(sourceFiles.size > 1, *sourceFiles.toTypedArray()) + } + override fun visitFileModel(model: KotlinModel.FileModel, data: CodeGenerator) { - data.createNewFile( - Dependencies(false, model.source.containingFile!!), + require(model.source.isNotEmpty()) { + "Source may not be empty. Sources was empty for $model" + } + + val writer = data.createNewFile( + generateDependencies(model.source), model.data.packageName, model.data.name - ).bufferedWriter(Charsets.UTF_8).use { - model.data.writeTo(it) + ).bufferedWriter(Charsets.UTF_8) + model.data.writeTo(writer) + try { + writer.close() + } catch (_: IOException) { + // Ignored } } diff --git a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcModelProcessor.kt b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcModelProcessor.kt index f41fcdda1f0cea1353087d434bbd48b36a7aff9d..417d161dcfb5d86a9d1b1d4cd2786f2a5e0348cc 100644 --- a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcModelProcessor.kt +++ b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcModelProcessor.kt @@ -9,18 +9,23 @@ package de.justjanne.libquassel.generator.visitors -import com.squareup.kotlinpoet.ANY import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.ParameterSpec -import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.TypeSpec import com.squareup.kotlinpoet.asTypeName import com.squareup.kotlinpoet.buildCodeBlock import de.justjanne.libquassel.annotations.ProtocolSide +import de.justjanne.libquassel.generator.Constants.TYPENAME_GENERATED +import de.justjanne.libquassel.generator.Constants.TYPENAME_INVOKER +import de.justjanne.libquassel.generator.Constants.TYPENAME_QVARIANTLIST +import de.justjanne.libquassel.generator.Constants.TYPENAME_QVARIANT_INTOORTHROW +import de.justjanne.libquassel.generator.Constants.TYPENAME_SYNCABLESTUB +import de.justjanne.libquassel.generator.Constants.TYPENAME_UNKNOWN_METHOD_EXCEPTION +import de.justjanne.libquassel.generator.Constants.TYPENAME_WRONG_OBJECT_TYPE_EXCEPTION import de.justjanne.libquassel.generator.kotlinmodel.KotlinModel import de.justjanne.libquassel.generator.rpcmodel.RpcModel import de.justjanne.libquassel.generator.rpcmodel.RpcModelVisitor @@ -35,7 +40,7 @@ class RpcModelProcessor : RpcModelVisitor<ProtocolSide, KotlinModel?> { "${model.rpcName}${data.name.toLowerCase().capitalize()}Invoker" ) return KotlinModel.FileModel( - model.source, + listOf(model.source), FileSpec.builder(name.packageName, name.simpleName) .addImport( TYPENAME_QVARIANT_INTOORTHROW.packageName, @@ -44,7 +49,7 @@ class RpcModelProcessor : RpcModelVisitor<ProtocolSide, KotlinModel?> { .addAnnotation(TYPENAME_GENERATED) .addType( TypeSpec.objectBuilder(name.simpleName) - .addSuperinterface(TYPENAME_INVOKER.parameterizedBy(model.name)) + .addSuperinterface(TYPENAME_INVOKER) .addAnnotation(TYPENAME_GENERATED) .addProperty( PropertySpec.builder( @@ -63,7 +68,7 @@ class RpcModelProcessor : RpcModelVisitor<ProtocolSide, KotlinModel?> { .addParameter( ParameterSpec.builder( "on", - TYPENAME_ANY + TYPENAME_SYNCABLESTUB ).build() ).addParameter( ParameterSpec.builder( @@ -127,36 +132,4 @@ class RpcModelProcessor : RpcModelVisitor<ProtocolSide, KotlinModel?> { ) override fun visitParameterModel(model: RpcModel.ParameterModel, data: ProtocolSide): KotlinModel? = null - - companion object { - private val TYPENAME_INVOKER = ClassName( - "de.justjanne.libquassel.protocol.syncables.invoker", - "Invoker" - ) - private val TYPENAME_UNKNOWN_METHOD_EXCEPTION = ClassName( - "de.justjanne.libquassel.protocol.exceptions", - "UnknownMethodException" - ) - private val TYPENAME_WRONG_OBJECT_TYPE_EXCEPTION = ClassName( - "de.justjanne.libquassel.protocol.exceptions", - "WrongObjectTypeException" - ) - private val TYPENAME_QVARIANTLIST = ClassName( - "de.justjanne.libquassel.protocol.variant", - "QVariantList" - ) - private val TYPENAME_QVARIANT_INTOORTHROW = ClassName( - "de.justjanne.libquassel.protocol.variant", - "intoOrThrow" - ) - private val TYPENAME_GENERATED = ClassName( - "de.justjanne.libquassel.annotations", - "Generated" - ) - private val TYPENAME_ANY = ANY.copy(nullable = true) - - init { - System.setProperty("idea.io.use.nio2", "true") - } - } } diff --git a/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcObjectCollector.kt b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcObjectCollector.kt new file mode 100644 index 0000000000000000000000000000000000000000..ad7d474f533a8b09a6a96717f6f93fdf1bff9a1a --- /dev/null +++ b/libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcObjectCollector.kt @@ -0,0 +1,23 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.generator.visitors + +import de.justjanne.libquassel.generator.rpcmodel.RpcModel +import de.justjanne.libquassel.generator.rpcmodel.RpcModelVisitor + +class RpcObjectCollector : RpcModelVisitor<Unit, Unit> { + val objects = mutableListOf<RpcModel.ObjectModel>() + override fun visitObjectModel(model: RpcModel.ObjectModel, data: Unit) { + objects.add(model) + } + + override fun visitFunctionModel(model: RpcModel.FunctionModel, data: Unit) = Unit + override fun visitParameterModel(model: RpcModel.ParameterModel, data: Unit) = Unit +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/exceptions/RpcInvocationFailedException.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/exceptions/RpcInvocationFailedException.kt new file mode 100644 index 0000000000000000000000000000000000000000..67a2eeaa4667efc17e943534f86b42ed0a7077cf --- /dev/null +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/exceptions/RpcInvocationFailedException.kt @@ -0,0 +1,33 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.protocol.exceptions + +import java.lang.Exception + +sealed class RpcInvocationFailedException(message: String) : Exception(message) { + data class InvokerNotFoundException( + val className: String + ) : RpcInvocationFailedException("Could not find invoker for $className") + + data class SyncableNotFoundException( + val className: String, + val objectName: String + ) : RpcInvocationFailedException("Could not find syncable $objectName for type $className") + + data class UnknownMethodException( + val className: String, + val methodName: String + ) : RpcInvocationFailedException("Could not find method $methodName for type $className") + + data class WrongObjectTypeException( + val obj: Any?, + val type: String + ) : RpcInvocationFailedException("Wrong type for invoker, expected $type but got $obj") +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/exceptions/WrongObjectTypeException.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/StatusMessage.kt similarity index 66% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/exceptions/WrongObjectTypeException.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/StatusMessage.kt index 7fd23edc4f79f0643f6af7cb03d41644fa43717d..e3a90dd6983ab17c6af302a21c2117dfc947fc43 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/exceptions/WrongObjectTypeException.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/StatusMessage.kt @@ -7,9 +7,9 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.exceptions +package de.justjanne.libquassel.protocol.models -data class WrongObjectTypeException( - val obj: Any?, - val type: String -) : Exception() +data class StatusMessage( + val network: String?, + val message: String +) diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/alias/Alias.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/alias/Alias.kt index 37c4a619eb4e95a29eade7c699140b95aa06910b..d6c0c896ad5114601e0485bf569335b03c3a9df5 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/alias/Alias.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/alias/Alias.kt @@ -10,6 +10,13 @@ package de.justjanne.libquassel.protocol.models.alias data class Alias( - val name: String?, - val expansion: String? -) + val name: String, + val expansion: String +) { + companion object { + fun of(name: String?, expansion: String?) = Alias( + name ?: "", + expansion ?: "" + ) + } +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentitySerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentitySerializer.kt index fe615e7ce8efb585953e1a88ee17ab451103bd95..e19e9d2c80fd0e737fee7b19aa7bba31d2615996 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentitySerializer.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IdentitySerializer.kt @@ -13,7 +13,7 @@ import de.justjanne.libquassel.protocol.features.FeatureSet import de.justjanne.libquassel.protocol.io.ChainedByteBuffer import de.justjanne.libquassel.protocol.serializers.PrimitiveSerializer import de.justjanne.libquassel.protocol.serializers.qt.QVariantMapSerializer -import de.justjanne.libquassel.protocol.syncables.Identity +import de.justjanne.libquassel.protocol.syncables.common.Identity import de.justjanne.libquassel.protocol.variant.QVariantMap import java.nio.ByteBuffer diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializer.kt index 9748b62a1e3005f0f142a2b519ee8931dba65c2a..986acd1bf6f770c284a301431ffd990fb7f8bd7c 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializer.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcChannelSerializer.kt @@ -13,7 +13,7 @@ import de.justjanne.libquassel.protocol.features.FeatureSet import de.justjanne.libquassel.protocol.io.ChainedByteBuffer import de.justjanne.libquassel.protocol.serializers.PrimitiveSerializer import de.justjanne.libquassel.protocol.serializers.qt.QVariantMapSerializer -import de.justjanne.libquassel.protocol.syncables.IrcChannel +import de.justjanne.libquassel.protocol.syncables.common.IrcChannel import de.justjanne.libquassel.protocol.variant.QVariantMap import java.nio.ByteBuffer diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializer.kt index f303f07daf61a211e52a22f6f8e2a49c816d3f4c..9b73020d7ac897f4e56d5011c88ce8f3faa00dcd 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializer.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/serializers/quassel/IrcUserSerializer.kt @@ -13,7 +13,7 @@ import de.justjanne.libquassel.protocol.features.FeatureSet import de.justjanne.libquassel.protocol.io.ChainedByteBuffer import de.justjanne.libquassel.protocol.serializers.PrimitiveSerializer import de.justjanne.libquassel.protocol.serializers.qt.QVariantMapSerializer -import de.justjanne.libquassel.protocol.syncables.IrcUser +import de.justjanne.libquassel.protocol.syncables.common.IrcUser import de.justjanne.libquassel.protocol.variant.QVariantMap import java.nio.ByteBuffer diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/HeartBeatHandler.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/HeartBeatHandler.kt new file mode 100644 index 0000000000000000000000000000000000000000..5435687b09edfe2570ba9ea004f88c8285b8581b --- /dev/null +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/HeartBeatHandler.kt @@ -0,0 +1,43 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.protocol.syncables + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import org.threeten.bp.Instant + +class HeartBeatHandler { + private var lastReceived: Instant? = null + + /** + * Utility function to recompute the latency value, + * usually should be called by a timer. + */ + fun recomputeLatency() { + recomputeLatency(Instant.now(), force = false) + } + + /** + * Utility function to recompute the latency value with a given heartbeat value + */ + fun recomputeLatency(current: Instant, force: Boolean) { + val last = lastReceived?.toEpochMilli() ?: return + val roundtripLatency = current.toEpochMilli() - last + if (force || roundtripLatency > this.roundtripLatency.value ?: return) { + this.roundtripLatency.value = roundtripLatency + } + } + + @Suppress("NOTHING_TO_INLINE") + inline fun flow(): Flow<Long?> = roundtripLatency + + @PublishedApi + internal val roundtripLatency = MutableStateFlow<Long?>(null) +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectHandler.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectHandler.kt deleted file mode 100644 index 9a08938c53ca85843f7c57e33ef67057bf8dbbc4..0000000000000000000000000000000000000000 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectHandler.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * libquassel - * Copyright (c) 2021 Janne Mareike Koschinski - * - * This Source Code Form is subject to the terms of the Mozilla Public License, - * v. 2.0. If a copy of the MPL was not distributed with this file, You can - * obtain one at https://mozilla.org/MPL/2.0/. - */ - -package de.justjanne.libquassel.protocol.syncables - -import de.justjanne.libquassel.protocol.variant.QVariantMap - -interface ObjectRepository { - fun register(syncable: SyncableStub, batch: Boolean) - fun init(syncable: SyncableStub, data: QVariantMap) - fun rename(syncable: SyncableStub, newName: String) - fun remove(syncable: SyncableStub) - - fun <T : SyncableStub> find(type: Class<T>, objectName: String): T -} - -inline fun <reified T : SyncableStub> ObjectRepository.find(objectName: String): T = - find(T::class.java, objectName) diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectIdentifier.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectIdentifier.kt new file mode 100644 index 0000000000000000000000000000000000000000..56a2fca7047af279798ecf695ee89b0039012775 --- /dev/null +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectIdentifier.kt @@ -0,0 +1,17 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.protocol.syncables + +data class ObjectIdentifier( + val className: String, + val objectName: String +) { + constructor(syncable: SyncableStub) : this(syncable.className, syncable.objectName) +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectRepository.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectRepository.kt new file mode 100644 index 0000000000000000000000000000000000000000..38bc68054a7994ed4eac7f2f14dcf02045f9e748 --- /dev/null +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectRepository.kt @@ -0,0 +1,89 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.protocol.syncables + +import de.justjanne.libquassel.protocol.util.update +import de.justjanne.libquassel.protocol.variant.QVariantMap +import kotlinx.coroutines.flow.MutableStateFlow + +class ObjectRepository { + fun add(syncable: SyncableStub): Boolean { + val identifier = ObjectIdentifier(syncable) + if (syncable is StatefulSyncableStub) { + state.update { + copy( + syncables = syncables + Pair( + identifier, + syncable + ), + waiting = waiting + syncable + ) + } + return true + } else { + state.update { + copy( + syncables = syncables + Pair( + identifier, + syncable + ) + ) + } + return false + } + } + + fun init(syncable: SyncableStub, properties: QVariantMap) { + if (syncable is StatefulSyncableStub) { + syncable.fromVariantMap(properties) + syncable.initialized = true + state.update { + copy(waiting = waiting - syncable) + } + } + } + + fun rename(syncable: SyncableStub, newName: String) { + val identifier = ObjectIdentifier(syncable) + state.update { + copy( + syncables = syncables - identifier + Pair( + identifier.copy(objectName = newName), + syncable + ) + ) + } + } + + fun remove(syncable: SyncableStub) { + val identifier = ObjectIdentifier(syncable) + syncable.initialized = false + state.update { + copy(syncables = syncables - identifier) + } + } + + fun find(className: String, objectName: String): SyncableStub? { + return state().syncables[ObjectIdentifier(objectName, className)] + } + + inline fun <reified T : SyncableStub> find(objectName: String): T? { + return find(T::class.java.simpleName, objectName) as? T + } + + @Suppress("NOTHING_TO_INLINE") + inline fun state() = flow().value + + @Suppress("NOTHING_TO_INLINE") + inline fun flow() = state + + @PublishedApi + internal val state = MutableStateFlow(ObjectRepositoryState()) +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectRepositoryState.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectRepositoryState.kt new file mode 100644 index 0000000000000000000000000000000000000000..f8416aa533758cda31135dfb21d2b0cb5344ae3a --- /dev/null +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectRepositoryState.kt @@ -0,0 +1,15 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.protocol.syncables + +data class ObjectRepositoryState( + val syncables: Map<ObjectIdentifier, SyncableStub> = emptyMap(), + val waiting: Set<SyncableStub> = emptySet() +) diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/Session.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/Session.kt index 88ce4c5aac166394a63b08c53d1299dcf19f2e9c..6a13f0d25d8026efd410afacd2bb8e7b1dd98e53 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/Session.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/Session.kt @@ -13,33 +13,49 @@ import de.justjanne.libquassel.annotations.ProtocolSide import de.justjanne.libquassel.protocol.models.SignalProxyMessage import de.justjanne.libquassel.protocol.models.ids.IdentityId import de.justjanne.libquassel.protocol.models.ids.NetworkId -import de.justjanne.libquassel.protocol.syncables.stubs.BacklogManagerStub -import de.justjanne.libquassel.protocol.syncables.stubs.IgnoreListManagerStub -import de.justjanne.libquassel.protocol.syncables.stubs.IrcListHelperStub -import de.justjanne.libquassel.protocol.syncables.stubs.RpcHandlerStub +import de.justjanne.libquassel.protocol.syncables.common.AliasManager +import de.justjanne.libquassel.protocol.syncables.common.BacklogManager +import de.justjanne.libquassel.protocol.syncables.common.BufferSyncer +import de.justjanne.libquassel.protocol.syncables.common.BufferViewManager +import de.justjanne.libquassel.protocol.syncables.common.CoreInfo +import de.justjanne.libquassel.protocol.syncables.common.DccConfig +import de.justjanne.libquassel.protocol.syncables.common.HighlightRuleManager +import de.justjanne.libquassel.protocol.syncables.common.Identity +import de.justjanne.libquassel.protocol.syncables.common.IgnoreListManager +import de.justjanne.libquassel.protocol.syncables.common.IrcListHelper +import de.justjanne.libquassel.protocol.syncables.common.Network +import de.justjanne.libquassel.protocol.syncables.common.NetworkConfig +import de.justjanne.libquassel.protocol.syncables.common.RpcHandler import de.justjanne.libquassel.protocol.variant.QVariantList +import de.justjanne.libquassel.protocol.variant.QVariantMap -interface Session : RpcHandlerStub { +interface Session { val protocolSide: ProtocolSide val objectRepository: ObjectRepository + val rpcHandler: RpcHandler fun network(id: NetworkId): Network? - fun identity(id: IdentityId): Identity + fun addNetwork(id: NetworkId) + fun removeNetwork(id: NetworkId) - fun aliasManager(): AliasManager - fun bufferSyncer(): BufferSyncer - fun backlogManager(): BacklogManagerStub - fun bufferViewManager(): BufferViewManager - fun ignoreListManager(): IgnoreListManagerStub - fun highlightRuleManager(): HighlightRuleManager - fun ircListHelper(): IrcListHelperStub + fun identity(id: IdentityId): Identity? + fun addIdentity(properties: QVariantMap) + fun removeIdentity(id: IdentityId) - fun coreInfo(): CoreInfo - fun dccConfig(): DccConfig - fun networkConfig(): NetworkConfig + val aliasManager: AliasManager + val backlogManager: BacklogManager + val bufferSyncer: BufferSyncer + val bufferViewManager: BufferViewManager + val highlightRuleManager: HighlightRuleManager + val ignoreListManager: IgnoreListManager + val ircListHelper: IrcListHelper - fun synchronize(it: SyncableObject) - fun stopSynchronize(it: SyncableObject) + val coreInfo: CoreInfo + val dccConfig: DccConfig + val networkConfig: NetworkConfig + + fun synchronize(syncable: SyncableStub) + fun stopSynchronize(syncable: SyncableStub) fun sync( target: ProtocolSide, @@ -77,10 +93,4 @@ interface Session : RpcHandlerStub { fun emit(message: SignalProxyMessage) fun dispatch(message: SignalProxyMessage) - fun dispatch(message: SignalProxyMessage.Sync) - fun dispatch(message: SignalProxyMessage.Rpc) - fun dispatch(message: SignalProxyMessage.InitRequest) - fun dispatch(message: SignalProxyMessage.InitData) - fun dispatch(message: SignalProxyMessage.HeartBeat) - fun dispatch(message: SignalProxyMessage.HeartBeatReply) } diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/StatefulSyncableObject.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/StatefulSyncableObject.kt index 8871dfbeb524b76924f42461891b8a4dd61bbe0b..f30a16390f52e39921d36d5317b0397ddf26f1d3 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/StatefulSyncableObject.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/StatefulSyncableObject.kt @@ -9,13 +9,14 @@ package de.justjanne.libquassel.protocol.syncables +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow abstract class StatefulSyncableObject<T>( session: Session?, className: String, state: T -) : SyncableObject(session, className) { +) : SyncableObject(session, className), StatefulSyncableStub { override fun toString(): String { return "$className(objectName=$objectName, state=${state()})" } @@ -37,10 +38,10 @@ abstract class StatefulSyncableObject<T>( } @Suppress("NOTHING_TO_INLINE") - inline fun state() = flow().value + inline fun state(): T = state.value @Suppress("NOTHING_TO_INLINE") - inline fun flow() = state + inline fun flow(): Flow<T> = state @PublishedApi internal val state = MutableStateFlow(state) diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/StatefulSyncableStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/StatefulSyncableStub.kt new file mode 100644 index 0000000000000000000000000000000000000000..7ce9faca19b4e9711428ed70a396f901053f3ecd --- /dev/null +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/StatefulSyncableStub.kt @@ -0,0 +1,37 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.protocol.syncables + +import de.justjanne.libquassel.annotations.ProtocolSide +import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.variant.QVariantMap +import de.justjanne.libquassel.protocol.variant.qVariant + +interface StatefulSyncableStub : SyncableStub { + fun fromVariantMap(properties: QVariantMap) + fun toVariantMap(): QVariantMap + + fun update(properties: QVariantMap) { + fromVariantMap(properties) + sync( + target = ProtocolSide.CLIENT, + "update", + qVariant(properties, QtType.QVariantMap) + ) + } + + fun requestUpdate(properties: QVariantMap = toVariantMap()) { + sync( + target = ProtocolSide.CORE, + "requestUpdate", + qVariant(properties, QtType.QVariantMap) + ) + } +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/SyncableObject.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/SyncableObject.kt index bd0d34e45f29c29e89b1f19c0129d607caafd99c..12549e5146cc845933c01f88c34545038902b409 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/SyncableObject.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/SyncableObject.kt @@ -18,7 +18,6 @@ abstract class SyncableObject( final override var objectName: String = "" internal set final override var initialized: Boolean = false - internal set protected fun renameObject( newName: String @@ -29,7 +28,7 @@ abstract class SyncableObject( } else if (oldName != newName) { objectName = newName session?.objectRepository?.rename(this, newName) - session?.objectRenamed( + session?.rpcHandler?.objectRenamed( StringSerializerUtf8.serializeRaw(className), oldName, newName diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/SyncableStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/SyncableStub.kt index 9f39230aecf83533289fd576d26c09aebb817450..20b6b59aacb9d5dfaf8f887ca38be4880b18928c 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/SyncableStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/SyncableStub.kt @@ -10,20 +10,14 @@ package de.justjanne.libquassel.protocol.syncables import de.justjanne.libquassel.annotations.ProtocolSide -import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.QVariant_ -import de.justjanne.libquassel.protocol.variant.qVariant interface SyncableStub { val className: String val objectName: String - val initialized: Boolean + var initialized: Boolean val session: Session? - fun fromVariantMap(properties: QVariantMap) - fun toVariantMap(): QVariantMap - fun sync(target: ProtocolSide, function: String, vararg arg: QVariant_) { if (initialized) { session?.sync(target, className, objectName, function, arg.toList()) @@ -35,21 +29,4 @@ interface SyncableStub { session?.rpc(target, function, arg.toList()) } } - - fun update(properties: QVariantMap) { - fromVariantMap(properties) - sync( - target = ProtocolSide.CLIENT, - "update", - qVariant(properties, QtType.QVariantMap) - ) - } - - fun requestUpdate(properties: QVariantMap = toVariantMap()) { - sync( - target = ProtocolSide.CORE, - "requestUpdate", - qVariant(properties, QtType.QVariantMap) - ) - } } diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/AliasManager.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/AliasManager.kt similarity index 87% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/AliasManager.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/AliasManager.kt index 283c81196ce8cd8057dae272e845623226226518..2a91ad354275e950e7503decb4bb7490fea23291 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/AliasManager.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/AliasManager.kt @@ -7,13 +7,15 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.BufferInfo import de.justjanne.libquassel.protocol.models.QStringList import de.justjanne.libquassel.protocol.models.alias.Alias import de.justjanne.libquassel.protocol.models.alias.Command import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.AliasManagerState import de.justjanne.libquassel.protocol.syncables.stubs.AliasManagerStub import de.justjanne.libquassel.protocol.util.update @@ -46,8 +48,9 @@ open class AliasManager( } state.update { - copy(aliases = names.zip(expansions, ::Alias)) + copy(aliases = names.zip(expansions, Alias::of)) } + initialized = true } override fun addAlias(name: String, expansion: String) { @@ -86,17 +89,4 @@ open class AliasManager( message, previousCommands ) - - fun expand( - expansion: String, - bufferInfo: BufferInfo, - arguments: String, - previousCommands: MutableList<Command> - ) = state().expand( - expansion, - bufferInfo, - session?.network(bufferInfo.networkId)?.state(), - arguments, - previousCommands - ) } diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BacklogManager.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BacklogManager.kt similarity index 61% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BacklogManager.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BacklogManager.kt index 7338b791d158ee2bcdd1b0b5cb487ea1ac2236d9..96bca3d14806fa79df363e0a9c1e6be5df5c5a17 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BacklogManager.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BacklogManager.kt @@ -7,16 +7,12 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.SyncableObject import de.justjanne.libquassel.protocol.syncables.stubs.BacklogManagerStub -import de.justjanne.libquassel.protocol.variant.QVariantMap -import de.justjanne.libquassel.protocol.variant.QVariant_ open class BacklogManager( session: Session? = null -) : SyncableObject(session, "BacklogManager"), BacklogManagerStub { - - override fun fromVariantMap(properties: QVariantMap) = Unit - override fun toVariantMap() = mapOf<String, QVariant_>() -} +) : SyncableObject(session, "BacklogManager"), BacklogManagerStub diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferSyncer.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BufferSyncer.kt similarity index 95% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferSyncer.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BufferSyncer.kt index b7e9eec957a72795f0ae98e6256785d19cb87a4b..03d1c17a396a92c298a070619ed6ae0402b39d37 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferSyncer.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BufferSyncer.kt @@ -7,7 +7,7 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.bitflags.none import de.justjanne.bitflags.of @@ -20,6 +20,8 @@ import de.justjanne.libquassel.protocol.models.ids.MsgId import de.justjanne.libquassel.protocol.models.ids.isValid import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.BufferSyncerState import de.justjanne.libquassel.protocol.syncables.stubs.BufferSyncerStub import de.justjanne.libquassel.protocol.util.collections.pairs @@ -102,6 +104,7 @@ open class BufferSyncer( }?.filterNotNull()?.toMap().orEmpty() ) } + initialized = true } fun lastSeenMsg(buffer: BufferId): MsgId = state().lastSeenMsg[buffer] ?: MsgId(0) @@ -178,7 +181,7 @@ open class BufferSyncer( val bufferInfo = bufferInfo(buffer) if (bufferInfo != null) { - session?.bufferViewManager()?.handleBuffer(bufferInfo, true) + session?.bufferViewManager?.handleBuffer(bufferInfo, true) } } @@ -200,7 +203,7 @@ open class BufferSyncer( } if (oldInfo != null) { - session?.bufferViewManager()?.handleBuffer(info) + session?.bufferViewManager?.handleBuffer(info) } } } diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfig.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BufferViewConfig.kt similarity index 97% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfig.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BufferViewConfig.kt index 60b878ec966aa060f16d8837b18a9c9fe409a06c..bc35bae2c2845dd4baedf241171e462a1a1e7724 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfig.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BufferViewConfig.kt @@ -7,7 +7,7 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.bitflags.of import de.justjanne.bitflags.toBits @@ -18,6 +18,8 @@ import de.justjanne.libquassel.protocol.models.ids.BufferId import de.justjanne.libquassel.protocol.models.ids.NetworkId import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.BufferViewConfigState import de.justjanne.libquassel.protocol.syncables.stubs.BufferViewConfigStub import de.justjanne.libquassel.protocol.util.collections.insert @@ -64,6 +66,7 @@ open class BufferViewConfig( showSearch = properties["showSearch"].into(showSearch), ) } + initialized = true } override fun toVariantMap() = mapOf( @@ -248,7 +251,7 @@ open class BufferViewConfig( .mapNotNull { (index, value) -> IndexedValue( index, - session?.bufferSyncer()?.bufferInfo(value) + session?.bufferSyncer?.bufferInfo(value) ?: return@mapNotNull null ) } diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewManager.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BufferViewManager.kt similarity index 92% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewManager.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BufferViewManager.kt index 168e99916a028943d5caa35d95159871a9c84078..4529cd9cec0e3f5530c7eec779a73bc3c27ad0d2 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewManager.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/BufferViewManager.kt @@ -7,10 +7,12 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.BufferInfo import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.BufferViewConfigState import de.justjanne.libquassel.protocol.syncables.state.BufferViewManagerState import de.justjanne.libquassel.protocol.syncables.stubs.BufferViewManagerStub @@ -30,6 +32,7 @@ open class BufferViewManager( properties["BufferViewIds"].into<QVariantList>() ?.mapNotNull<QVariant_, Int>(QVariant_::into) ?.forEach(this::addBufferViewConfig) + initialized = true } override fun toVariantMap() = mapOf( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/CertManager.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/CertManager.kt similarity index 94% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/CertManager.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/CertManager.kt index 182ff8cd91857f04a8fa5270e7991a1c89497f54..df15b194374f9b097042a9b95ed85712e3c11099 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/CertManager.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/CertManager.kt @@ -7,10 +7,12 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.serializers.qt.StringSerializerUtf8 +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.CertManagerState import de.justjanne.libquassel.protocol.syncables.stubs.CertManagerStub import de.justjanne.libquassel.protocol.util.update @@ -43,6 +45,7 @@ open class CertManager( certificate = readCertificate(certPem) ) } + initialized = true } override fun toVariantMap() = mapOf( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/CoreInfo.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/CoreInfo.kt similarity index 92% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/CoreInfo.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/CoreInfo.kt index b3cdd35d926cdac899a70fdb4b2e9d9696038f31..69da65c4f8245238a10ab36279abbce293ade426 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/CoreInfo.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/CoreInfo.kt @@ -7,10 +7,12 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.ConnectedClient import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.CoreInfoState import de.justjanne.libquassel.protocol.syncables.stubs.CoreInfoStub import de.justjanne.libquassel.protocol.util.update @@ -43,6 +45,7 @@ open class CoreInfo( .orEmpty() ) } + initialized = true } override fun toVariantMap() = mapOf( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/DccConfig.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/DccConfig.kt similarity index 95% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/DccConfig.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/DccConfig.kt index 87ddf62f89df81491d512967f92bf8da41fda748..49c553f1b4c82253b7ae31f2df562103e39ad363 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/DccConfig.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/DccConfig.kt @@ -7,12 +7,14 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.dcc.DccIpDetectionMode import de.justjanne.libquassel.protocol.models.dcc.DccPortSelectionMode import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.DccConfigState import de.justjanne.libquassel.protocol.syncables.stubs.DccConfigStub import de.justjanne.libquassel.protocol.util.update @@ -45,6 +47,7 @@ open class DccConfig( useFastSend = properties["useFastSend"].into(useFastSend), ) } + initialized = true } override fun toVariantMap() = mapOf( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/HighlightRuleManager.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/HighlightRuleManager.kt similarity index 97% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/HighlightRuleManager.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/HighlightRuleManager.kt index f32fdbb66960a8169b25d5f3dd85d7fd3d3131f1..35cecdd867657bf12a212dd99fd5ea5a5d83c429 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/HighlightRuleManager.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/HighlightRuleManager.kt @@ -7,12 +7,14 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.QStringList import de.justjanne.libquassel.protocol.models.rules.HighlightNickType import de.justjanne.libquassel.protocol.models.rules.HighlightRule import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.HighlightRuleManagerState import de.justjanne.libquassel.protocol.syncables.stubs.HighlightRuleManagerStub import de.justjanne.libquassel.protocol.util.update @@ -80,6 +82,7 @@ open class HighlightRuleManager( } ) } + initialized = true } override fun toVariantMap() = mapOf( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/Identity.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/Identity.kt similarity index 97% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/Identity.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/Identity.kt index daa29091b1f934d835973b7f55c12b8384a3242c..922929205dc4146cfc461c7eb33a604dcd253cf4 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/Identity.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/Identity.kt @@ -7,12 +7,14 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.QStringList import de.justjanne.libquassel.protocol.models.ids.IdentityId import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.IdentityState import de.justjanne.libquassel.protocol.syncables.stubs.IdentityStub import de.justjanne.libquassel.protocol.util.update @@ -54,6 +56,7 @@ open class Identity( ) } renameObject(state().identifier()) + initialized = true } override fun toVariantMap() = mapOf( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IgnoreListManager.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IgnoreListManager.kt similarity index 96% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IgnoreListManager.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IgnoreListManager.kt index bfd6d0c39e7628e5923baae6859cad78ca23827f..c4708181e55533c3d8609436e9b56cc69691dd54 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IgnoreListManager.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IgnoreListManager.kt @@ -7,7 +7,7 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.QStringList import de.justjanne.libquassel.protocol.models.flags.MessageTypes @@ -16,6 +16,8 @@ import de.justjanne.libquassel.protocol.models.rules.IgnoreType import de.justjanne.libquassel.protocol.models.rules.ScopeType import de.justjanne.libquassel.protocol.models.rules.StrictnessType import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.IgnoreListManagerState import de.justjanne.libquassel.protocol.syncables.stubs.IgnoreListManagerStub import de.justjanne.libquassel.protocol.util.collections.removeAt @@ -124,6 +126,7 @@ class IgnoreListManager( } ) } + initialized = true } fun indexOf(ignoreRule: String?): Int = state().indexOf(ignoreRule) diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannel.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcChannel.kt similarity index 96% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannel.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcChannel.kt index d47d37f6b7d13f42202df2cd9a4488e7aded3370..e27c6dac33daf3c795664c3adf43c28dc24b8a06 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannel.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcChannel.kt @@ -7,12 +7,14 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.QStringList import de.justjanne.libquassel.protocol.models.network.ChannelModeType import de.justjanne.libquassel.protocol.models.network.ChannelModes import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.IrcChannelState import de.justjanne.libquassel.protocol.syncables.stubs.IrcChannelStub import de.justjanne.libquassel.protocol.util.update @@ -30,7 +32,7 @@ open class IrcChannel( require(name().isNotEmpty()) { "IrcChannel: channelName is empty" } - renameObject("${network().id}/${name()}") + renameObject(state().identifier()) } override fun fromVariantMap(properties: QVariantMap) = @@ -50,6 +52,8 @@ open class IrcChannel( .orEmpty() ) } + renameObject(state().identifier()) + initialized = true } override fun toVariantMap(): QVariantMap { diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcListHelper.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcListHelper.kt similarity index 52% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcListHelper.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcListHelper.kt index 3b71bcad50f7dfdcc3bd98938fd0fe3a03244d25..768f620e5ac523a1de923a893605f9496b94531f 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcListHelper.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcListHelper.kt @@ -7,15 +7,12 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.SyncableObject import de.justjanne.libquassel.protocol.syncables.stubs.IrcListHelperStub -import de.justjanne.libquassel.protocol.variant.QVariantMap -import de.justjanne.libquassel.protocol.variant.QVariant_ open class IrcListHelper( session: Session? = null -) : SyncableObject(session, "IrcListHelper"), IrcListHelperStub { - override fun fromVariantMap(properties: QVariantMap) = Unit - override fun toVariantMap() = emptyMap<String, QVariant_>() -} +) : SyncableObject(session, "IrcListHelper"), IrcListHelperStub diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcUser.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcUser.kt similarity index 97% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcUser.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcUser.kt index 894167e254a73edf7e75d84b8ed00c1543895c2f..ea4abb820083808fe955f455625b417fa4559096 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcUser.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/IrcUser.kt @@ -7,9 +7,11 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.IrcUserState import de.justjanne.libquassel.protocol.syncables.stubs.IrcUserStub import de.justjanne.libquassel.protocol.util.irc.HostmaskHelper @@ -59,6 +61,7 @@ open class IrcUser( ) } renameObject(state().identifier()) + initialized = true } override fun toVariantMap() = mapOf( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/Network.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/Network.kt similarity index 99% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/Network.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/Network.kt index f659dab56a94db6f7a96d1670563433a94eadbfd..84fdab8428d73fc6b98dc5aea9902a539ae636ed 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/Network.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/Network.kt @@ -7,7 +7,7 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.QStringList import de.justjanne.libquassel.protocol.models.ids.IdentityId @@ -17,6 +17,8 @@ import de.justjanne.libquassel.protocol.models.network.NetworkServer import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType import de.justjanne.libquassel.protocol.serializers.qt.StringSerializerUtf8 +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.IrcChannelState import de.justjanne.libquassel.protocol.syncables.state.IrcUserState import de.justjanne.libquassel.protocol.syncables.state.NetworkState @@ -134,6 +136,7 @@ open class Network( .orEmpty() ) } + initialized = true } override fun toVariantMap() = mapOf( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/NetworkConfig.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/NetworkConfig.kt similarity index 94% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/NetworkConfig.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/NetworkConfig.kt index 78dcf1ea4233c907d6e3e9415934e7a840d7fa70..9c7eab876f354e4d53ce4c0601436cc16e5f1862 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/NetworkConfig.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/NetworkConfig.kt @@ -7,9 +7,11 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.syncables +package de.justjanne.libquassel.protocol.syncables.common import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableObject import de.justjanne.libquassel.protocol.syncables.state.NetworkConfigState import de.justjanne.libquassel.protocol.syncables.stubs.NetworkConfigStub import de.justjanne.libquassel.protocol.util.update @@ -39,6 +41,7 @@ open class NetworkConfig( standardCtcp = properties["standardCtcp"].into(standardCtcp), ) } + initialized = true } override fun toVariantMap() = mapOf( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/RpcHandler.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/RpcHandler.kt new file mode 100644 index 0000000000000000000000000000000000000000..b3220279d0464909c1971d59ca72df40d561d68c --- /dev/null +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/RpcHandler.kt @@ -0,0 +1,42 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.protocol.syncables.common + +import de.justjanne.libquassel.protocol.models.BufferInfo +import de.justjanne.libquassel.protocol.models.ids.IdentityId +import de.justjanne.libquassel.protocol.models.ids.NetworkId +import de.justjanne.libquassel.protocol.syncables.Session +import de.justjanne.libquassel.protocol.syncables.SyncableObject +import de.justjanne.libquassel.protocol.syncables.stubs.RpcHandlerStub +import de.justjanne.libquassel.protocol.variant.QVariantMap + +open class RpcHandler( + session: Session? = null +) : SyncableObject(session, ""), RpcHandlerStub { + override fun bufferInfoUpdated(bufferInfo: BufferInfo) { + session?.bufferSyncer?.bufferInfoUpdated(bufferInfo) + } + + override fun identityCreated(identity: QVariantMap) { + session?.addIdentity(identity) + } + + override fun identityRemoved(identityId: IdentityId) { + session?.removeIdentity(identityId) + } + + override fun networkCreated(networkId: NetworkId) { + session?.addNetwork(networkId) + } + + override fun networkRemoved(networkId: NetworkId) { + session?.removeNetwork(networkId) + } +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/Invoker.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/Invoker.kt index 94a86f6b053eb1276d609a83bf3822d1f03ccc82..1c0c137a33174c51be910193673e098827dd926e 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/Invoker.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/Invoker.kt @@ -9,13 +9,13 @@ package de.justjanne.libquassel.protocol.syncables.invoker -import de.justjanne.libquassel.protocol.exceptions.UnknownMethodException -import de.justjanne.libquassel.protocol.exceptions.WrongObjectTypeException +import de.justjanne.libquassel.protocol.exceptions.RpcInvocationFailedException +import de.justjanne.libquassel.protocol.syncables.SyncableStub import de.justjanne.libquassel.protocol.variant.QVariantList -interface Invoker<out T> { +interface Invoker { val className: String - @Throws(WrongObjectTypeException::class, UnknownMethodException::class) - fun invoke(on: Any?, method: String, params: QVariantList) + @Throws(RpcInvocationFailedException::class) + fun invoke(on: SyncableStub, method: String, params: QVariantList) } diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/exceptions/UnknownMethodException.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/InvokerRegistry.kt similarity index 61% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/exceptions/UnknownMethodException.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/InvokerRegistry.kt index 153b72e9025178b2d59cf096e46a37848ce3aaf4..4b5353bb3906f4afefcc02fe7470dd57fe7fb12f 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/exceptions/UnknownMethodException.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/InvokerRegistry.kt @@ -7,9 +7,9 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.exceptions +package de.justjanne.libquassel.protocol.syncables.invoker -data class UnknownMethodException( - val className: String, - val methodName: String -) : Exception() +interface InvokerRegistry { + val clientInvokers: Map<String, Invoker> + val coreInvokers: Map<String, Invoker> +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/Invokers.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/Invokers.kt new file mode 100644 index 0000000000000000000000000000000000000000..1dad0495513c04cb0f0ceb7830f2c0b50dc9fa18 --- /dev/null +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/Invokers.kt @@ -0,0 +1,38 @@ +/* + * Quasseldroid - Quassel client for Android + * + * Copyright (c) 2020 Janne Mareike Koschinski + * Copyright (c) 2020 The Quassel Project + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.justjanne.libquassel.protocol.syncables.invoker + +import de.justjanne.libquassel.annotations.ProtocolSide +import de.justjanne.libquassel.protocol.util.reflect.objectByName + +object Invokers { + private val registry: InvokerRegistry = + objectByName("${Invokers::class.java.`package`.name}.GeneratedInvokerRegistry") + + fun get(side: ProtocolSide, name: String): Invoker? = when (side) { + ProtocolSide.CLIENT -> registry.clientInvokers[name] + ProtocolSide.CORE -> registry.coreInvokers[name] + } + + fun list(side: ProtocolSide): Set<String> = when (side) { + ProtocolSide.CLIENT -> registry.clientInvokers.keys + ProtocolSide.CORE -> registry.coreInvokers.keys + } +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/AliasManagerState.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/AliasManagerState.kt index 6aedb90fa799f9207d90b89ceea310ddb53488ae..5b3754cd50e14081122a125dc815d92582176448 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/AliasManagerState.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/AliasManagerState.kt @@ -43,7 +43,7 @@ data class AliasManagerState( } else { val found = aliases.firstOrNull { it.name.equals(command, true) } if (found != null) { - expand(found.expansion ?: "", info, networkState, arguments, previousCommands) + expand(found.expansion, info, networkState, arguments, previousCommands) } else { previousCommands.add(Command(info, message)) } @@ -57,15 +57,17 @@ data class AliasManagerState( arguments: String, previousCommands: MutableList<Command> ) { - val params = arguments.split(' ') + val params = + if (arguments.isBlank()) emptyList() + else arguments.split(Regex(" ")) previousCommands.add( Command( bufferInfo, expansion.split(';') .map(String::trimStart) .map(Expansion.Companion::parse) - .map { - it.map { + .joinToString(";") { + it.joinToString("") { when (it) { is Expansion.Constant -> when (it.field) { Expansion.ConstantField.CHANNEL -> @@ -75,37 +77,35 @@ data class AliasManagerState( Expansion.ConstantField.NETWORK -> networkState?.networkName } - is Expansion.Parameter -> when (it.field) { - Expansion.ParameterField.HOSTNAME -> - networkState?.ircUser(params[it.index])?.host() ?: "*" - Expansion.ParameterField.VERIFIED_IDENT -> - params.getOrNull(it.index)?.let { param -> - networkState?.ircUser(param)?.verifiedUser() ?: "*" - } - Expansion.ParameterField.IDENT -> - params.getOrNull(it.index)?.let { param -> - networkState?.ircUser(param)?.user() ?: "*" - } - Expansion.ParameterField.ACCOUNT -> - params.getOrNull(it.index)?.let { param -> - networkState?.ircUser(param)?.account() ?: "*" - } - null -> params.getOrNull(it.index) ?: it.source - } + is Expansion.Parameter -> + if (it.index == 0) arguments + else params.getOrNull(it.index - 1)?.let { param -> + when (it.field) { + Expansion.ParameterField.HOSTNAME -> + networkState?.ircUser(param)?.host() + Expansion.ParameterField.VERIFIED_IDENT -> + networkState?.ircUser(param)?.verifiedUser() + Expansion.ParameterField.IDENT -> + networkState?.ircUser(param)?.user() + Expansion.ParameterField.ACCOUNT -> + networkState?.ircUser(param)?.account() + null -> param + } ?: "*" + } ?: it.source is Expansion.ParameterRange -> - params.subList(it.from, it.to ?: params.size) + params.subList(it.from - 1, it.to ?: params.size ) .joinToString(" ") is Expansion.Text -> it.source } ?: it.source } - }.joinToString(";") + } ) ) } companion object { - private fun determineMessageCommand(message: String) = when { + internal fun determineMessageCommand(message: String) = when { // Only messages starting with a forward slash are commands !message.startsWith("/") -> Pair(null, message) @@ -115,9 +115,8 @@ data class AliasManagerState( // If the first word of a message contains more than one slash, it is // usually a regex of format /[a-z][a-z0-9]*/g, or a path of format // /usr/bin/powerline-go. In that case we also pass it right through - message.startsWith("/") && - message.substringBefore(' ').indexOf('/', 1) != -1 - -> Pair(null, message) + message.substringBefore(' ').indexOf('/', 1) != -1 -> + Pair(null, message) // If the first word is purely a /, we won’t consider it a command either message.substringBefore(' ') == "/" -> Pair(null, message) @@ -125,7 +124,7 @@ data class AliasManagerState( // arguments else -> Pair( message.trimStart('/').substringBefore(' '), - message.substringAfter(' ') + message.substringAfter(' ', missingDelimiterValue = "") ) } } diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/BufferViewManagerState.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/BufferViewManagerState.kt index a24e8c7c9ce2e39faf82a7978f0f171792721b28..f61d11ff514f97042caf28899c7df533c801c104 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/BufferViewManagerState.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/BufferViewManagerState.kt @@ -9,7 +9,7 @@ package de.justjanne.libquassel.protocol.syncables.state -import de.justjanne.libquassel.protocol.syncables.BufferViewConfig +import de.justjanne.libquassel.protocol.syncables.common.BufferViewConfig data class BufferViewManagerState( val bufferViewConfigs: Map<Int, BufferViewConfig> = emptyMap() diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/IrcChannelState.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/IrcChannelState.kt index 5a122da10581e694262332325413b0defc489825..f26b197b5e652780968dbaa94f8a765c602756bc 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/IrcChannelState.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/IrcChannelState.kt @@ -22,6 +22,8 @@ data class IrcChannelState( val channelModes: ChannelModes = ChannelModes(), val userModes: Map<String, Set<Char>> = emptyMap() ) { + fun identifier() = "${network.id}/$name" + fun channelModeString() = channelModes.modeString() fun ircUsers(networkState: NetworkState?) = networkState?.let { network -> diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/NetworkState.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/NetworkState.kt index 0f2abfacbbe5e52336008ee33fe7314cad628690..c8cd134cb81762838fd87c525e66c71a0cbb15e8 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/NetworkState.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/NetworkState.kt @@ -14,8 +14,8 @@ import de.justjanne.libquassel.protocol.models.ids.NetworkId import de.justjanne.libquassel.protocol.models.network.ChannelModeType import de.justjanne.libquassel.protocol.models.network.ConnectionState import de.justjanne.libquassel.protocol.models.network.NetworkServer -import de.justjanne.libquassel.protocol.syncables.IrcChannel -import de.justjanne.libquassel.protocol.syncables.IrcUser +import de.justjanne.libquassel.protocol.syncables.common.IrcChannel +import de.justjanne.libquassel.protocol.syncables.common.IrcUser import de.justjanne.libquassel.protocol.util.irc.IrcCapability import de.justjanne.libquassel.protocol.util.irc.IrcCaseMapper import de.justjanne.libquassel.protocol.util.irc.IrcISupport diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/AliasManagerStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/AliasManagerStub.kt index 92e16dfd043bf19970cadb8afb6425f91c2ce1dc..c34a0d4c009ad4eab8b19a5f9ee16390d5806dfe 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/AliasManagerStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/AliasManagerStub.kt @@ -13,12 +13,12 @@ import de.justjanne.libquassel.annotations.ProtocolSide import de.justjanne.libquassel.annotations.SyncedCall import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant @SyncedObject("AliasManager") -interface AliasManagerStub : SyncableStub { +interface AliasManagerStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CORE) fun addAlias(name: String, expansion: String) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferSyncerStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferSyncerStub.kt index 24eac36c2b95627caf1b98574f6e668e79e32543..7735bf63bf225d7709efd698e381b03aa988005f 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferSyncerStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferSyncerStub.kt @@ -16,12 +16,12 @@ import de.justjanne.libquassel.protocol.models.ids.BufferId import de.justjanne.libquassel.protocol.models.ids.MsgId import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant @SyncedObject("BufferSyncer") -interface BufferSyncerStub : SyncableStub { +interface BufferSyncerStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun markBufferAsRead(buffer: BufferId) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewConfigStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewConfigStub.kt index 9fe8c77603ab51114ba43a6e61050416d79e1e0c..e9900b29e5e2498951345a65dab786add324dbcf 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewConfigStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewConfigStub.kt @@ -16,12 +16,12 @@ import de.justjanne.libquassel.protocol.models.ids.BufferId import de.justjanne.libquassel.protocol.models.ids.NetworkId import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant @SyncedObject("BufferViewConfig") -interface BufferViewConfigStub : SyncableStub { +interface BufferViewConfigStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun addBuffer(buffer: BufferId, pos: Int) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewManagerStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewManagerStub.kt index 9947ba1700a4a0861fc72d6b844bcc786d9d3e04..b1acc8ebfb7e1c1d91d63983ebc82854ed5c1913 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewManagerStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewManagerStub.kt @@ -13,13 +13,13 @@ import de.justjanne.libquassel.annotations.ProtocolSide import de.justjanne.libquassel.annotations.SyncedCall import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantList import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant @SyncedObject("BufferViewManager") -interface BufferViewManagerStub : SyncableStub { +interface BufferViewManagerStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun addBufferViewConfig(bufferViewConfigId: Int) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/CertManagerStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/CertManagerStub.kt index 5c04f1ec428c79da6a40cec1e5036446c16c41ab..bb665e5f7cd574c7c17a3762e027c26826c51595 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/CertManagerStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/CertManagerStub.kt @@ -13,13 +13,13 @@ import de.justjanne.libquassel.annotations.ProtocolSide import de.justjanne.libquassel.annotations.SyncedCall import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant import java.nio.ByteBuffer @SyncedObject("CertManager") -interface CertManagerStub : SyncableStub { +interface CertManagerStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun setSslCert(encoded: ByteBuffer) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/CoreInfoStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/CoreInfoStub.kt index 5d2f829cfd4baf19b46d28ee1f4c9c00939b6965..0b17814497677e05fb598236f9f326f7287b2973 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/CoreInfoStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/CoreInfoStub.kt @@ -13,12 +13,12 @@ import de.justjanne.libquassel.annotations.ProtocolSide import de.justjanne.libquassel.annotations.SyncedCall import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant @SyncedObject("CoreInfo") -interface CoreInfoStub : SyncableStub { +interface CoreInfoStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun setCoreData(data: QVariantMap) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/DccConfigStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/DccConfigStub.kt index 3d7192d0629661ddc6b308789dfe0fd55e2eddc9..417f8f821d6dc1af61a2e958c6d20d7ba4f482e4 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/DccConfigStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/DccConfigStub.kt @@ -16,13 +16,13 @@ import de.justjanne.libquassel.protocol.models.dcc.DccIpDetectionMode import de.justjanne.libquassel.protocol.models.dcc.DccPortSelectionMode import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant import java.net.InetAddress @SyncedObject("DccConfig") -interface DccConfigStub : SyncableStub { +interface DccConfigStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun setDccEnabled(enabled: Boolean) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/HighlightRuleManagerStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/HighlightRuleManagerStub.kt index 9ebac411d98238ca8d086b77b5d9d6af4e165bc3..8ee5fd51d14f2fbecd4a73c3dec3d2094239cfac 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/HighlightRuleManagerStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/HighlightRuleManagerStub.kt @@ -13,12 +13,12 @@ import de.justjanne.libquassel.annotations.ProtocolSide import de.justjanne.libquassel.annotations.SyncedCall import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant @SyncedObject("HighlightRuleManager") -interface HighlightRuleManagerStub : SyncableStub { +interface HighlightRuleManagerStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CORE) fun requestRemoveHighlightRule(highlightRule: Int) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IdentityStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IdentityStub.kt index be7364a2edb6a70ba3a6d7b1c8782889c87beffb..f0ce775856ba6634c2e88d02080a898ed20a4196 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IdentityStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IdentityStub.kt @@ -16,12 +16,12 @@ import de.justjanne.libquassel.protocol.models.QStringList import de.justjanne.libquassel.protocol.models.ids.IdentityId import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant @SyncedObject("Identity") -interface IdentityStub : SyncableStub { +interface IdentityStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun setAutoAwayEnabled(enabled: Boolean) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IgnoreListManagerStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IgnoreListManagerStub.kt index 9185a9a2963fb218063cb0834387beb039cb8311..ac88010f53681c0b3d5d56134e4019bc68fa2399 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IgnoreListManagerStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IgnoreListManagerStub.kt @@ -13,12 +13,12 @@ import de.justjanne.libquassel.annotations.ProtocolSide import de.justjanne.libquassel.annotations.SyncedCall import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant @SyncedObject(name = "IgnoreListManager") -interface IgnoreListManagerStub : SyncableStub { +interface IgnoreListManagerStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun addIgnoreListItem( type: Int, diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IrcChannelStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IrcChannelStub.kt index daffa7580da8d6a01f51adfc36095ddb3e7692fd..fa0269ad70ba819590ad3aa30a85210f4d3b3514 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IrcChannelStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IrcChannelStub.kt @@ -14,12 +14,12 @@ import de.justjanne.libquassel.annotations.SyncedCall import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.protocol.models.QStringList import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant @SyncedObject("IrcChannel") -interface IrcChannelStub : SyncableStub { +interface IrcChannelStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun addChannelMode(mode: Char, value: String? = null) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IrcUserStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IrcUserStub.kt index 95443f4e6ce0606a94734cdf03b00acea3c87097..1be59e65812d8f27b8aaa56189b952bd13e08cee 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IrcUserStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/IrcUserStub.kt @@ -13,13 +13,13 @@ import de.justjanne.libquassel.annotations.ProtocolSide import de.justjanne.libquassel.annotations.SyncedCall import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant import org.threeten.bp.temporal.Temporal @SyncedObject("IrcUser") -interface IrcUserStub : SyncableStub { +interface IrcUserStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun addUserModes(modes: String) { diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/NetworkConfigStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/NetworkConfigStub.kt index be77e5c1b037c892e25bcc28bb8747da243f6ea5..fe3861db97a1bc41b20013f827508ad222e01d8c 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/NetworkConfigStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/NetworkConfigStub.kt @@ -13,12 +13,12 @@ import de.justjanne.libquassel.annotations.ProtocolSide import de.justjanne.libquassel.annotations.SyncedCall import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.protocol.models.types.QtType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant @SyncedObject("NetworkConfig") -interface NetworkConfigStub : SyncableStub { +interface NetworkConfigStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CORE) fun requestSetAutoWhoDelay(delay: Int) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/NetworkStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/NetworkStub.kt index f6655846b78808e1cb633d9ee428a016927410c4..7d8808c29fcf978fbaf7f9991694ea02f2270f98 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/NetworkStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/NetworkStub.kt @@ -17,14 +17,14 @@ import de.justjanne.libquassel.protocol.models.ids.IdentityId import de.justjanne.libquassel.protocol.models.network.NetworkInfo import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantList import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant import java.nio.ByteBuffer @SyncedObject("Network") -interface NetworkStub : SyncableStub { +interface NetworkStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun setNetworkName(networkName: String) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/RpcHandlerStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/RpcHandlerStub.kt index 4a36c7b1493bde0573412408380ccca7b7297b59..0fc058e1f28439e1a45da97cc6c6455e5fada482 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/RpcHandlerStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/RpcHandlerStub.kt @@ -66,7 +66,7 @@ interface RpcHandlerStub : SyncableStub { } @SyncedCall(name = "2identityCreated(Identity)", target = ProtocolSide.CLIENT) - fun identityCreated(identity: IdentityStub) { + fun identityCreated(identity: QVariantMap) { rpc( target = ProtocolSide.CLIENT, "2identityCreated(Identity)", diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/TransferManagerStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/TransferManagerStub.kt index 79ac7ed71e2254e4e9d57e841520184090289b28..4b628af70abc8b92e173bca554a037d7a95c4799 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/TransferManagerStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/TransferManagerStub.kt @@ -15,13 +15,13 @@ import de.justjanne.libquassel.annotations.SyncedObject import de.justjanne.libquassel.protocol.models.dcc.TransferIdList import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant import java.util.UUID @SyncedObject("TransferManager") -interface TransferManagerStub : SyncableStub { +interface TransferManagerStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun setTransferIds(transferIds: TransferIdList) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/TransferStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/TransferStub.kt index 9cca9a4a55a154aceea8ab670ca629233f52537d..79b718472465e83b3e79b1db1604c446f3fb041d 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/TransferStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/TransferStub.kt @@ -16,14 +16,14 @@ import de.justjanne.libquassel.protocol.models.dcc.TransferDirection import de.justjanne.libquassel.protocol.models.dcc.TransferStatus import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType -import de.justjanne.libquassel.protocol.syncables.SyncableStub +import de.justjanne.libquassel.protocol.syncables.StatefulSyncableStub import de.justjanne.libquassel.protocol.variant.QVariantMap import de.justjanne.libquassel.protocol.variant.qVariant import java.net.InetAddress import java.nio.ByteBuffer @SyncedObject("Transfer") -interface TransferStub : SyncableStub { +interface TransferStub : StatefulSyncableStub { @SyncedCall(target = ProtocolSide.CLIENT) fun accept(savePath: String) { sync( diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/instanceof.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/reflect/instanceof.kt similarity index 87% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/instanceof.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/reflect/instanceof.kt index e82109bbe9916c9c523dc66e65a9005d8905f9ae..2a841390872cf9edf076b3672b60263079eb86e1 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/instanceof.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/reflect/instanceof.kt @@ -7,7 +7,7 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.util +package de.justjanne.libquassel.protocol.util.reflect internal infix fun <T> Any?.instanceof(other: Class<T>?): Boolean = other?.isInstance(this) != false diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/reflect/objectByName.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/reflect/objectByName.kt new file mode 100644 index 0000000000000000000000000000000000000000..7e59350243eb79fd91c08a93908c343384cc185f --- /dev/null +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/reflect/objectByName.kt @@ -0,0 +1,28 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.protocol.util.reflect + +inline fun <reified T> objectByName(name: String): T { + val clazz = try { + Class.forName(name) + } catch (t: Throwable) { + throw IllegalArgumentException("Could not load class $name", t) + } + val element = clazz.getDeclaredField("INSTANCE").get(null) + require(element != null) { + "No object found for $name" + } + require(element is T) { + "Object of wrong type found for $name:" + + "expected ${T::class.java.canonicalName}, " + + "got ${element::class.java.canonicalName}" + } + return element +} diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/subtype.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/reflect/subtype.kt similarity index 88% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/subtype.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/reflect/subtype.kt index d128e3aa847b2e6cadb8068a8567f79867910a2c..610835c67e6fbd30a5244bb636db314dbbc32b65 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/subtype.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/reflect/subtype.kt @@ -7,7 +7,7 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.util +package de.justjanne.libquassel.protocol.util.reflect internal infix fun <T> Class<*>?.subtype(other: Class<T>?): Boolean = this != null && other?.isAssignableFrom(this) == true diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariant.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariant.kt index b5edcf621a8b23b62041b6796810bc3a44893450..38f03d7ee0e104ad74da966ed36bb9bda3c5584b 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariant.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/variant/QVariant.kt @@ -15,8 +15,8 @@ import de.justjanne.libquassel.protocol.io.contentToString import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.models.types.QuasselType import de.justjanne.libquassel.protocol.serializers.PrimitiveSerializer -import de.justjanne.libquassel.protocol.util.instanceof -import de.justjanne.libquassel.protocol.util.subtype +import de.justjanne.libquassel.protocol.util.reflect.instanceof +import de.justjanne.libquassel.protocol.util.reflect.subtype import java.nio.ByteBuffer /**