From 6787f34832a959c233f03ff39109bf967b0d3c8c Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski <janne@kuschku.de> Date: Sat, 6 Mar 2021 00:32:33 +0100 Subject: [PATCH] Continue invoker implementation --- .../libquassel/client/ClientSession.kt | 201 ++++++++++++++++++ .../libquassel/client/ClientSessionState.kt | 40 ++++ .../client/syncables/ClientBacklogManager.kt | 2 +- .../client/syncables/ClientIrcListHelper.kt | 2 +- .../libquassel/generator/Constants.kt | 64 ++++++ .../libquassel/generator/InvokerProcessor.kt | 25 ++- .../generator/InvokerRegistryGenerator.kt | 67 ++++++ .../generator/kotlinmodel/KotlinModel.kt | 2 +- .../generator/visitors/KotlinSaver.kt | 23 +- .../generator/visitors/RpcModelProcessor.kt | 47 +--- .../generator/visitors/RpcObjectCollector.kt | 23 ++ .../RpcInvocationFailedException.kt | 33 +++ .../StatusMessage.kt} | 10 +- .../libquassel/protocol/models/alias/Alias.kt | 13 +- .../serializers/quassel/IdentitySerializer.kt | 2 +- .../quassel/IrcChannelSerializer.kt | 2 +- .../serializers/quassel/IrcUserSerializer.kt | 2 +- .../protocol/syncables/HeartBeatHandler.kt | 43 ++++ .../protocol/syncables/ObjectHandler.kt | 24 --- .../protocol/syncables/ObjectIdentifier.kt | 17 ++ .../protocol/syncables/ObjectRepository.kt | 89 ++++++++ .../syncables/ObjectRepositoryState.kt | 15 ++ .../libquassel/protocol/syncables/Session.kt | 58 ++--- .../syncables/StatefulSyncableObject.kt | 7 +- .../syncables/StatefulSyncableStub.kt | 37 ++++ .../protocol/syncables/SyncableObject.kt | 3 +- .../protocol/syncables/SyncableStub.kt | 25 +-- .../syncables/{ => common}/AliasManager.kt | 20 +- .../syncables/{ => common}/BacklogManager.kt | 12 +- .../syncables/{ => common}/BufferSyncer.kt | 9 +- .../{ => common}/BufferViewConfig.kt | 7 +- .../{ => common}/BufferViewManager.kt | 5 +- .../syncables/{ => common}/CertManager.kt | 5 +- .../syncables/{ => common}/CoreInfo.kt | 5 +- .../syncables/{ => common}/DccConfig.kt | 5 +- .../{ => common}/HighlightRuleManager.kt | 5 +- .../syncables/{ => common}/Identity.kt | 5 +- .../{ => common}/IgnoreListManager.kt | 5 +- .../syncables/{ => common}/IrcChannel.kt | 8 +- .../syncables/{ => common}/IrcListHelper.kt | 11 +- .../syncables/{ => common}/IrcUser.kt | 5 +- .../syncables/{ => common}/Network.kt | 5 +- .../syncables/{ => common}/NetworkConfig.kt | 5 +- .../protocol/syncables/common/RpcHandler.kt | 42 ++++ .../protocol/syncables/invoker/Invoker.kt | 10 +- .../invoker/InvokerRegistry.kt} | 10 +- .../protocol/syncables/invoker/Invokers.kt | 38 ++++ .../syncables/state/AliasManagerState.kt | 55 +++-- .../syncables/state/BufferViewManagerState.kt | 2 +- .../syncables/state/IrcChannelState.kt | 2 + .../protocol/syncables/state/NetworkState.kt | 4 +- .../syncables/stubs/AliasManagerStub.kt | 4 +- .../syncables/stubs/BufferSyncerStub.kt | 4 +- .../syncables/stubs/BufferViewConfigStub.kt | 4 +- .../syncables/stubs/BufferViewManagerStub.kt | 4 +- .../syncables/stubs/CertManagerStub.kt | 4 +- .../protocol/syncables/stubs/CoreInfoStub.kt | 4 +- .../protocol/syncables/stubs/DccConfigStub.kt | 4 +- .../stubs/HighlightRuleManagerStub.kt | 4 +- .../protocol/syncables/stubs/IdentityStub.kt | 4 +- .../syncables/stubs/IgnoreListManagerStub.kt | 4 +- .../syncables/stubs/IrcChannelStub.kt | 4 +- .../protocol/syncables/stubs/IrcUserStub.kt | 4 +- .../syncables/stubs/NetworkConfigStub.kt | 4 +- .../protocol/syncables/stubs/NetworkStub.kt | 4 +- .../syncables/stubs/RpcHandlerStub.kt | 2 +- .../syncables/stubs/TransferManagerStub.kt | 4 +- .../protocol/syncables/stubs/TransferStub.kt | 4 +- .../protocol/util/{ => reflect}/instanceof.kt | 2 +- .../protocol/util/reflect/objectByName.kt | 28 +++ .../protocol/util/{ => reflect}/subtype.kt | 2 +- .../libquassel/protocol/variant/QVariant.kt | 4 +- 72 files changed, 992 insertions(+), 266 deletions(-) create mode 100644 libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/ClientSession.kt create mode 100644 libquassel-client/src/main/kotlin/de/justjanne/libquassel/client/ClientSessionState.kt create mode 100644 libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/Constants.kt create mode 100644 libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/InvokerRegistryGenerator.kt create mode 100644 libquassel-generator/src/main/kotlin/de/justjanne/libquassel/generator/visitors/RpcObjectCollector.kt create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/exceptions/RpcInvocationFailedException.kt rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/{exceptions/WrongObjectTypeException.kt => models/StatusMessage.kt} (66%) create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/HeartBeatHandler.kt delete mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectHandler.kt create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectIdentifier.kt create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectRepository.kt create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/ObjectRepositoryState.kt create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/StatefulSyncableStub.kt rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/AliasManager.kt (87%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/BacklogManager.kt (61%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/BufferSyncer.kt (95%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/BufferViewConfig.kt (97%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/BufferViewManager.kt (92%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/CertManager.kt (94%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/CoreInfo.kt (92%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/DccConfig.kt (95%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/HighlightRuleManager.kt (97%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/Identity.kt (97%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/IgnoreListManager.kt (96%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/IrcChannel.kt (96%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/IrcListHelper.kt (52%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/IrcUser.kt (97%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/Network.kt (99%) rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/{ => common}/NetworkConfig.kt (94%) create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/common/RpcHandler.kt rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/{exceptions/UnknownMethodException.kt => syncables/invoker/InvokerRegistry.kt} (61%) create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/invoker/Invokers.kt rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/{ => reflect}/instanceof.kt (87%) create mode 100644 libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/reflect/objectByName.kt rename libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/{ => reflect}/subtype.kt (88%) 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 0000000..d194481 --- /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 0000000..179ee40 --- /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 989f281..d66caab 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 e615644..a46a04b 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 0000000..3df1190 --- /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 1c43f8d..a154144 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 0000000..2828887 --- /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 e8601cd..4ef05f4 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 8177194..6566541 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 f41fcdd..417d161 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 0000000..ad7d474 --- /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 0000000..67a2eea --- /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 7fd23ed..e3a90dd 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 37c4a61..d6c0c89 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 fe615e7..e19e9d2 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 9748b62..986acd1 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 f303f07..9b73020 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 0000000..5435687 --- /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 9a08938..0000000 --- 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 0000000..56a2fca --- /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 0000000..38bc680 --- /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 0000000..f8416aa --- /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 88ce4c5..6a13f0d 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 8871dfb..f30a163 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 0000000..7ce9fac --- /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 bd0d34e..12549e5 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 9f39230..20b6b59 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 283c811..2a91ad3 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 7338b79..96bca3d 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 b7e9eec..03d1c17 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 60b878e..bc35bae 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 168e999..4529cd9 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 182ff8c..df15b19 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 b3cdd35..69da65c 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 87ddf62..49c553f 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 f32fdbb..35cecdd 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 daa2909..9229292 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 bfd6d0c..c470818 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 d47d37f..e27c6da 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 3b71bca..768f620 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 894167e..ea4abb8 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 f659dab..84fdab8 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 78dcf1e..9c7eab8 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 0000000..b322027 --- /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 94a86f6..1c0c137 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 153b72e..4b5353b 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 0000000..1dad049 --- /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 6aedb90..5b3754c 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 a24e8c7..f61d11f 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 5a122da..f26b197 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 0f2abfa..c8cd134 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 92e16df..c34a0d4 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 24eac36..7735bf6 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 9fe8c77..e9900b2 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 9947ba1..b1acc8e 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 5c04f1e..bb665e5 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 5d2f829..0b17814 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 3d7192d..417f8f8 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 9ebac41..8ee5fd5 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 be7364a..f0ce775 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 9185a9a..ac88010 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 daffa75..fa0269a 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 95443f4..1be59e6 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 be77e5c..fe3861d 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 f665584..7d8808c 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 4a36c7b..0fc058e 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 79ac7ed..4b628af 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 9cca9a4..79b7184 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 e82109b..2a84139 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 0000000..7e59350 --- /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 d128e3a..610835c 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 b5edcf6..38f03d7 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 /** -- GitLab