From b995f4b927c230e0ae15d51920390dc6afff6caa Mon Sep 17 00:00:00 2001 From: Robert Jaros Date: Thu, 20 Dec 2018 10:19:55 +0100 Subject: Refactor server side modules. --- .../pl/treksoft/kvision/remote/JoobyRemoteAgent.kt | 370 -------------------- .../treksoft/kvision/remote/JoobyServiceManager.kt | 129 ------- .../pl/treksoft/kvision/remote/KVRemoteAgent.kt | 382 +++++++++++++++++++++ .../pl/treksoft/kvision/remote/KVServiceManager.kt | 142 ++++++++ .../treksoft/kvision/remote/SpringRemoteAgent.kt | 382 --------------------- .../kvision/remote/SpringServiceManager.kt | 136 -------- 6 files changed, 524 insertions(+), 1017 deletions(-) delete mode 100644 kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/JoobyRemoteAgent.kt delete mode 100644 kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/JoobyServiceManager.kt create mode 100644 kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVRemoteAgent.kt create mode 100644 kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt delete mode 100644 kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/SpringRemoteAgent.kt delete mode 100644 kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/SpringServiceManager.kt (limited to 'kvision-modules/kvision-remote/src') diff --git a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/JoobyRemoteAgent.kt b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/JoobyRemoteAgent.kt deleted file mode 100644 index 318f77ea..00000000 --- a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/JoobyRemoteAgent.kt +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (c) 2017-present Robert Jaros - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package pl.treksoft.kvision.remote - -import kotlinx.coroutines.asDeferred -import kotlinx.serialization.ImplicitReflectionSerializer -import kotlinx.serialization.list -import kotlinx.serialization.serializer -import pl.treksoft.kvision.utils.JSON -import kotlin.js.js -import kotlin.reflect.KClass -import kotlin.js.JSON as NativeJSON - -/** - * Client side agent for JSON-RPC remote calls with Jooby. - */ -@Suppress("LargeClass", "TooManyFunctions") -@UseExperimental(ImplicitReflectionSerializer::class) -open class JoobyRemoteAgent(val serviceManager: JoobyServiceManager) : RemoteAgent { - - val callAgent = CallAgent() - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call(noinline function: suspend T.(Request?) -> RET): RET { - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, method = method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(Request?) -> List - ): List { - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, method = method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR, Request?) -> RET, p: PAR - ): RET { - val data = serialize(p) - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data), method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR, Request?) -> List, p: PAR - ): List { - val data = serialize(p) - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data), method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, Request?) -> RET, p1: PAR1, p2: PAR2 - ): RET { - val data1 = serialize(p1) - val data2 = serialize(p2) - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2), method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, Request?) -> List, p1: PAR1, p2: PAR2 - ): List { - val data1 = serialize(p1) - val data2 = serialize(p2) - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2), method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3, Request?) -> RET, p1: PAR1, p2: PAR2, p3: PAR3 - ): RET { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3), method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3, Request?) -> List, p1: PAR1, p2: PAR2, p3: PAR3 - ): List { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3), method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, Request?) -> RET, p1: PAR1, p2: PAR2, p3: PAR3, p4: PAR4 - ): RET { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val data4 = serialize(p4) - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4), method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, Request?) -> List, - p1: PAR1, - p2: PAR2, - p3: PAR3, - p4: PAR4 - ): List { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val data4 = serialize(p4) - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4), method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - @Suppress("LongParameterList") - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5, Request?) -> RET, - p1: PAR1, - p2: PAR2, - p3: PAR3, - p4: PAR4, - p5: PAR5 - ): RET { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val data4 = serialize(p4) - val data5 = serialize(p5) - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4, data5), method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - @Suppress("LongParameterList") - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5, Request?) -> List, - p1: PAR1, - p2: PAR2, - p3: PAR3, - p4: PAR4, - p5: PAR5 - ): List { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val data4 = serialize(p4) - val data5 = serialize(p5) - val (url, method) = - serviceManager.getCalls()[function.toString()] ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4, data5), method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - - /** - * @suppress - * Internal function - */ - inline fun serialize(value: PAR): String? { - return value?.let { - @Suppress("UNCHECKED_CAST") - trySerialize((PAR::class as KClass), it as Any) - } - } - -} diff --git a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/JoobyServiceManager.kt b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/JoobyServiceManager.kt deleted file mode 100644 index 0d3515a1..00000000 --- a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/JoobyServiceManager.kt +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2017-present Robert Jaros - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package pl.treksoft.kvision.remote - -/** - * Multiplatform service manager for Jooby. - */ -actual open class JoobyServiceManager actual constructor(service: T) : ServiceManager { - - protected val calls: MutableMap> = mutableMapOf() - var counter: Int = 0 - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(Request?) -> RET, - route: String?, method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString()] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(PAR, Request?) -> RET, - route: String?, method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString()] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(PAR1, PAR2, Request?) -> RET, - route: String?, method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString()] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(PAR1, PAR2, PAR3, Request?) -> RET, - route: String?, method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString()] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, Request?) -> RET, - route: String?, method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString()] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5, Request?) -> RET, - route: String?, - method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString()] = Pair("/kv/$routeDef", method) - } - - /** - * Applies all defined routes to the given server. - * Not used on the js platform. - */ - actual fun applyRoutes(k: KVServer) { - } - - /** - * Returns the map of defined paths. - */ - override fun getCalls(): Map> = calls -} diff --git a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVRemoteAgent.kt b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVRemoteAgent.kt new file mode 100644 index 00000000..a157a313 --- /dev/null +++ b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVRemoteAgent.kt @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package pl.treksoft.kvision.remote + +import kotlinx.coroutines.asDeferred +import kotlinx.serialization.ImplicitReflectionSerializer +import kotlinx.serialization.list +import kotlinx.serialization.serializer +import pl.treksoft.kvision.utils.JSON +import kotlin.js.js +import kotlin.reflect.KClass +import kotlin.js.JSON as NativeJSON + +/** + * Client side agent for JSON-RPC remote calls. + */ +@Suppress("LargeClass", "TooManyFunctions") +@UseExperimental(ImplicitReflectionSerializer::class) +open class KVRemoteAgent(val serviceManager: KVServiceManager) : RemoteAgent { + + val callAgent = CallAgent() + + /** + * Executes defined call to a remote web service. + */ + suspend inline fun call(noinline function: suspend T.() -> RET): RET { + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, method = method).then { + try { + @Suppress("UNCHECKED_CAST") + deserialize(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnum(RET::class as KClass, it) as RET + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer(), it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + suspend inline fun call( + noinline function: suspend T.() -> List + ): List { + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, method = method).then { + try { + deserializeList(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnumList(RET::class as KClass, it) as List + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer().list, it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + suspend inline fun call( + noinline function: suspend T.(PAR) -> RET, p: PAR + ): RET { + val data = serialize(p) + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, listOf(data), method).then { + try { + @Suppress("UNCHECKED_CAST") + deserialize(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnum(RET::class as KClass, it) as RET + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer(), it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + suspend inline fun call( + noinline function: suspend T.(PAR) -> List, p: PAR + ): List { + val data = serialize(p) + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, listOf(data), method).then { + try { + deserializeList(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnumList(RET::class as KClass, it) as List + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer().list, it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + suspend inline fun call( + noinline function: suspend T.(PAR1, PAR2) -> RET, p1: PAR1, p2: PAR2 + ): RET { + val data1 = serialize(p1) + val data2 = serialize(p2) + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, listOf(data1, data2), method).then { + try { + @Suppress("UNCHECKED_CAST") + deserialize(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnum(RET::class as KClass, it) as RET + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer(), it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + suspend inline fun call( + noinline function: suspend T.(PAR1, PAR2) -> List, p1: PAR1, p2: PAR2 + ): List { + val data1 = serialize(p1) + val data2 = serialize(p2) + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, listOf(data1, data2), method).then { + try { + deserializeList(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnumList(RET::class as KClass, it) as List + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer().list, it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + suspend inline fun call( + noinline function: suspend T.(PAR1, PAR2, PAR3) -> RET, p1: PAR1, p2: PAR2, p3: PAR3 + ): RET { + val data1 = serialize(p1) + val data2 = serialize(p2) + val data3 = serialize(p3) + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, listOf(data1, data2, data3), method).then { + try { + @Suppress("UNCHECKED_CAST") + deserialize(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnum(RET::class as KClass, it) as RET + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer(), it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + suspend inline fun call( + noinline function: suspend T.(PAR1, PAR2, PAR3) -> List, p1: PAR1, p2: PAR2, p3: PAR3 + ): List { + val data1 = serialize(p1) + val data2 = serialize(p2) + val data3 = serialize(p3) + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, listOf(data1, data2, data3), method).then { + try { + deserializeList(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnumList(RET::class as KClass, it) as List + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer().list, it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + suspend inline fun call( + noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> RET, p1: PAR1, p2: PAR2, p3: PAR3, p4: PAR4 + ): RET { + val data1 = serialize(p1) + val data2 = serialize(p2) + val data3 = serialize(p3) + val data4 = serialize(p4) + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4), method).then { + try { + @Suppress("UNCHECKED_CAST") + deserialize(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnum(RET::class as KClass, it) as RET + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer(), it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + suspend inline fun call( + noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> List, + p1: PAR1, + p2: PAR2, + p3: PAR3, + p4: PAR4 + ): List { + val data1 = serialize(p1) + val data2 = serialize(p2) + val data3 = serialize(p3) + val data4 = serialize(p4) + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4), method).then { + try { + deserializeList(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnumList(RET::class as KClass, it) as List + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer().list, it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + @Suppress("LongParameterList") + suspend inline fun call( + noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> RET, + p1: PAR1, + p2: PAR2, + p3: PAR3, + p4: PAR4, + p5: PAR5 + ): RET { + val data1 = serialize(p1) + val data2 = serialize(p2) + val data3 = serialize(p3) + val data4 = serialize(p4) + val data5 = serialize(p5) + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4, data5), method).then { + try { + @Suppress("UNCHECKED_CAST") + deserialize(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnum(RET::class as KClass, it) as RET + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer(), it) + } + } + }.asDeferred().await() + } + + /** + * Executes defined call to a remote web service. + */ + @Suppress("LongParameterList") + suspend inline fun call( + noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> List, + p1: PAR1, + p2: PAR2, + p3: PAR3, + p4: PAR4, + p5: PAR5 + ): List { + val data1 = serialize(p1) + val data2 = serialize(p2) + val data3 = serialize(p3) + val data4 = serialize(p4) + val data5 = serialize(p5) + val (url, method) = + serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] + ?: throw IllegalStateException("Function not specified!") + return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4, data5), method).then { + try { + deserializeList(it, RET::class.js.name) + } catch (t: NotStandardTypeException) { + try { + @Suppress("UNCHECKED_CAST") + tryDeserializeEnumList(RET::class as KClass, it) as List + } catch (t: NotEnumTypeException) { + JSON.nonstrict.parse(RET::class.serializer().list, it) + } + } + }.asDeferred().await() + } + + + /** + * @suppress + * Internal function + */ + inline fun serialize(value: PAR): String? { + return value?.let { + @Suppress("UNCHECKED_CAST") + trySerialize((PAR::class as KClass), it as Any) + } + } + +} diff --git a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt new file mode 100644 index 00000000..383e8bb2 --- /dev/null +++ b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/KVServiceManager.kt @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-present Robert Jaros + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package pl.treksoft.kvision.remote + +import kotlin.reflect.KClass + +/** + * Multiplatform service manager. + */ +actual open class KVServiceManager actual constructor(serviceClass: KClass) : ServiceManager { + + protected val calls: MutableMap> = mutableMapOf() + var counter: Int = 0 + + /** + * Binds a given route with a function of the receiver. + * @param function a function of the receiver + * @param route a route + * @param method a HTTP method + */ + protected actual inline fun bind( + noinline function: suspend T.() -> RET, + route: String?, method: RpcHttpMethod + ) { + val routeDef = route ?: "route${this::class.simpleName}${counter++}" + calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) + } + + /** + * Binds a given route with a function of the receiver. + * @param function a function of the receiver + * @param route a route + * @param method a HTTP method + */ + protected actual inline fun bind( + noinline function: suspend T.(PAR) -> RET, + route: String?, method: RpcHttpMethod + ) { + val routeDef = route ?: "route${this::class.simpleName}${counter++}" + calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) + } + + /** + * Binds a given route with a function of the receiver. + * @param function a function of the receiver + * @param route a route + * @param method a HTTP method + */ + protected actual inline fun bind( + noinline function: suspend T.(PAR1, PAR2) -> RET, + route: String?, method: RpcHttpMethod + ) { + val routeDef = route ?: "route${this::class.simpleName}${counter++}" + calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) + } + + /** + * Binds a given route with a function of the receiver. + * @param function a function of the receiver + * @param route a route + * @param method a HTTP method + */ + protected actual inline fun bind( + noinline function: suspend T.(PAR1, PAR2, PAR3) -> RET, + route: String?, method: RpcHttpMethod + ) { + val routeDef = route ?: "route${this::class.simpleName}${counter++}" + calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) + } + + /** + * Binds a given route with a function of the receiver. + * @param function a function of the receiver + * @param route a route + * @param method a HTTP method + */ + protected actual inline fun bind( + noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> RET, + route: String?, method: RpcHttpMethod + ) { + val routeDef = route ?: "route${this::class.simpleName}${counter++}" + calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) + } + + /** + * Binds a given route with a function of the receiver. + * @param function a function of the receiver + * @param route a route + * @param method a HTTP method + */ + protected actual inline fun bind( + noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> RET, + route: String?, + method: RpcHttpMethod + ) { + val routeDef = route ?: "route${this::class.simpleName}${counter++}" + calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) + } + + /** + * Binds a given function of the receiver as a select options source + * @param function a function of the receiver + */ + protected actual fun bind( + function: T.(String?, String?) -> List + ) { + val routeDef = "route${this::class.simpleName}${counter++}" + calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", RpcHttpMethod.POST) + } + + /** + * Returns the map of defined paths. + */ + override fun getCalls(): Map> = calls + + /** + * Applies all defined routes to the given server. + * Not used on the js platform. + */ + actual fun applyRoutes(k: KVServer) { + } +} diff --git a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/SpringRemoteAgent.kt b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/SpringRemoteAgent.kt deleted file mode 100644 index 2f6b765a..00000000 --- a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/SpringRemoteAgent.kt +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (c) 2017-present Robert Jaros - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package pl.treksoft.kvision.remote - -import kotlinx.coroutines.asDeferred -import kotlinx.serialization.ImplicitReflectionSerializer -import kotlinx.serialization.list -import kotlinx.serialization.serializer -import pl.treksoft.kvision.utils.JSON -import kotlin.js.js -import kotlin.reflect.KClass -import kotlin.js.JSON as NativeJSON - -/** - * Client side agent for JSON-RPC remote calls with Spring Boot. - */ -@Suppress("LargeClass", "TooManyFunctions") -@UseExperimental(ImplicitReflectionSerializer::class) -open class SpringRemoteAgent(val serviceManager: SpringServiceManager) : RemoteAgent { - - val callAgent = CallAgent() - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call(noinline function: suspend T.() -> RET): RET { - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, method = method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.() -> List - ): List { - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, method = method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR) -> RET, p: PAR - ): RET { - val data = serialize(p) - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data), method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR) -> List, p: PAR - ): List { - val data = serialize(p) - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data), method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2) -> RET, p1: PAR1, p2: PAR2 - ): RET { - val data1 = serialize(p1) - val data2 = serialize(p2) - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2), method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2) -> List, p1: PAR1, p2: PAR2 - ): List { - val data1 = serialize(p1) - val data2 = serialize(p2) - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2), method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3) -> RET, p1: PAR1, p2: PAR2, p3: PAR3 - ): RET { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3), method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3) -> List, p1: PAR1, p2: PAR2, p3: PAR3 - ): List { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3), method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> RET, p1: PAR1, p2: PAR2, p3: PAR3, p4: PAR4 - ): RET { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val data4 = serialize(p4) - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4), method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> List, - p1: PAR1, - p2: PAR2, - p3: PAR3, - p4: PAR4 - ): List { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val data4 = serialize(p4) - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4), method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - @Suppress("LongParameterList") - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> RET, - p1: PAR1, - p2: PAR2, - p3: PAR3, - p4: PAR4, - p5: PAR5 - ): RET { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val data4 = serialize(p4) - val data5 = serialize(p5) - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4, data5), method).then { - try { - @Suppress("UNCHECKED_CAST") - deserialize(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnum(RET::class as KClass, it) as RET - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer(), it) - } - } - }.asDeferred().await() - } - - /** - * Executes defined call to a remote web service. - */ - @Suppress("LongParameterList") - suspend inline fun call( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> List, - p1: PAR1, - p2: PAR2, - p3: PAR3, - p4: PAR4, - p5: PAR5 - ): List { - val data1 = serialize(p1) - val data2 = serialize(p2) - val data3 = serialize(p3) - val data4 = serialize(p4) - val data5 = serialize(p5) - val (url, method) = - serviceManager.getCalls()[function.toString().replace("\\s".toRegex(), "")] - ?: throw IllegalStateException("Function not specified!") - return callAgent.jsonRpcCall(url, listOf(data1, data2, data3, data4, data5), method).then { - try { - deserializeList(it, RET::class.js.name) - } catch (t: NotStandardTypeException) { - try { - @Suppress("UNCHECKED_CAST") - tryDeserializeEnumList(RET::class as KClass, it) as List - } catch (t: NotEnumTypeException) { - JSON.nonstrict.parse(RET::class.serializer().list, it) - } - } - }.asDeferred().await() - } - - - /** - * @suppress - * Internal function - */ - inline fun serialize(value: PAR): String? { - return value?.let { - @Suppress("UNCHECKED_CAST") - trySerialize((PAR::class as KClass), it as Any) - } - } - -} diff --git a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/SpringServiceManager.kt b/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/SpringServiceManager.kt deleted file mode 100644 index 61ae32ba..00000000 --- a/kvision-modules/kvision-remote/src/main/kotlin/pl/treksoft/kvision/remote/SpringServiceManager.kt +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2017-present Robert Jaros - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package pl.treksoft.kvision.remote - -import kotlin.reflect.KClass - -/** - * Multiplatform service manager for Spring Boot. - */ -actual open class SpringServiceManager actual constructor(serviceClass: KClass) : ServiceManager { - - protected val calls: MutableMap> = mutableMapOf() - var counter: Int = 0 - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.() -> RET, - route: String?, method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(PAR) -> RET, - route: String?, method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(PAR1, PAR2) -> RET, - route: String?, method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(PAR1, PAR2, PAR3) -> RET, - route: String?, method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4) -> RET, - route: String?, method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given route with a function of the receiver. - * @param function a function of the receiver - * @param route a route - * @param method a HTTP method - */ - protected actual inline fun bind( - noinline function: suspend T.(PAR1, PAR2, PAR3, PAR4, PAR5) -> RET, - route: String?, - method: RpcHttpMethod - ) { - val routeDef = route ?: "route${this::class.simpleName}${counter++}" - calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", method) - } - - /** - * Binds a given function of the receiver as a select options source - * @param function a function of the receiver - */ - protected actual fun bind( - function: T.(String) -> List - ) { - val routeDef = "route${this::class.simpleName}${counter++}" - calls[function.toString().replace("\\s".toRegex(), "")] = Pair("/kv/$routeDef", RpcHttpMethod.POST) - } - - /** - * Returns the map of defined paths. - */ - override fun getCalls(): Map> = calls - -} -- cgit