From 7fe99ad67bf73190b9d4fbe6cd575083a1d20bcd Mon Sep 17 00:00:00 2001 From: Ross Anderson Date: Wed, 1 Jul 2026 15:17:23 +0100 Subject: [PATCH] feat: parse optional trailing query parameters off subjects (#49) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AntPatternNamespace had no notion of an optional trailing query string, which (a) polluted the last path variable when a subject carried a `?query`, and (b) left consumers no way to read query parameters. util: - Strip an optional trailing `?query` before match/extractPathVariables so path variables are never polluted (fixes the bug). - Add extractQueryParameters(subject): parses `?a=b&c=d` into a map (empty when absent), via a shared pure parseQueryString helper (URL-decoding, empty values, last-wins on repeated keys). - URL-decode path variables too, for consistency with the Spring DataSourceMessageHandler which already decodes destination variables. NOTE: this changes query-less subjects like /X/EUR%2FUSD to yield EUR/USD instead of EUR%2FUSD. - Expose a shared CHARSET constant; DataSourceServerBootstrap sources its bootstrapCharset from it. reactive DSL: - Thread the parsed query map to all supplier shapes via a Request / ChannelRequest object (path, pathVariables, queryParameters[, receive]) instead of positional params, avoiding the same-typed adjacent-map footgun and making future additions non-breaking. - RequestSupplier / ChannelRequestSupplier are receiver-style SAMs, so Kotlin gets `{ this.path }` ergonomics with no overload ambiguity while Java implements a clean `invoke(request)`. - Retain the previous positional shapes as @Deprecated PathVariablesSupplier / PathVariablesChannelSupplier overloads for source back-compat. Public API: additive to util; the reactive supplier interfaces are reshaped (deprecated overloads retained) — a major bump. .api snapshots regenerated. --- buildSrc/src/main/kotlin/Active.kt | 87 ++++++++-- buildSrc/src/main/kotlin/ActiveContainer.kt | 71 +++++++- buildSrc/src/main/kotlin/Channel.kt | 157 ++++++++++++++++-- buildSrc/src/main/kotlin/Constants.kt | 10 +- buildSrc/src/main/kotlin/GenerateApi.kt | 10 +- reactive/api/api/datasourcex-reactive-api.api | 23 +++ .../reactive/api/ChannelRequest.kt | 17 ++ .../reactive/api/ChannelRequestSupplier.kt | 5 + .../api/PathVariablesChannelSupplier.kt | 4 + .../reactive/api/PathVariablesSupplier.kt | 4 + .../datasourcex/reactive/api/Request.kt | 15 ++ .../reactive/api/RequestSupplier.kt | 5 + .../datasourcex/reactive/core/Binder.kt | 24 ++- .../java-flow/api/datasourcex-java-flow.api | 38 +++++ .../src/samples/kotlin/samples/Samples.kt | 6 +- reactive/kotlin/api/datasourcex-kotlin.api | 38 +++++ .../src/samples/kotlin/samples/Samples.kt | 6 +- .../datasourcex/reactive/kotlin/BindTest.kt | 54 ++++-- .../api/datasourcex-reactivestreams.api | 38 +++++ .../src/samples/kotlin/samples/Samples.kt | 6 +- .../internal/DataSourceServerBootstrap.kt | 27 ++- util/api/datasourcex-util.api | 2 + .../datasourcex/util/AntPatternNamespace.kt | 48 +++++- .../util/AntPatternNamespaceTest.kt | 64 +++++++ 24 files changed, 676 insertions(+), 83 deletions(-) create mode 100644 reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/ChannelRequest.kt create mode 100644 reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier.kt create mode 100644 reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/Request.kt create mode 100644 reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/RequestSupplier.kt diff --git a/buildSrc/src/main/kotlin/Active.kt b/buildSrc/src/main/kotlin/Active.kt index 544aa8c..2754a0c 100644 --- a/buildSrc/src/main/kotlin/Active.kt +++ b/buildSrc/src/main/kotlin/Active.kt @@ -1,3 +1,4 @@ +import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FunSpec @@ -40,7 +41,7 @@ object Active : FunctionProvider { val publisherPatternSupplierParameter = ParameterSpec.builder( "supplier", - pathVariablesSupplierClassName.parameterizedBy( + requestSupplierClassName.parameterizedBy( publisherType.className.parameterizedBy(projectedParameterTypeName), ), ) @@ -61,7 +62,7 @@ object Active : FunctionProvider { .addParameter(publisherPatternSupplierParameter) .addCode( """ - %N.%N(%N, %N) { %N.asFlow(%N(it, %N.extractPathVariables(it))) } + %N.%N(%N, %N) { %N.asFlow(with(%N) { %T(it, %N.extractPathVariables(it), %N.extractQueryParameters(it)).invoke() }) } """ .trimIndent(), binderProperty, @@ -70,6 +71,8 @@ object Active : FunctionProvider { antNamespaceParameter, adapterProperty, publisherPatternSupplierParameter, + requestClassName, + antNamespaceParameter, antNamespaceParameter, ) .build() @@ -101,6 +104,66 @@ object Active : FunctionProvider { ) .build() + val deprecatedSupplierParameter = + ParameterSpec.builder( + "supplier", + pathVariablesSupplierClassName.parameterizedBy( + publisherType.className.parameterizedBy(projectedParameterTypeName), + ), + ) + .build() + + val deprecatedAnnotation = + AnnotationSpec.builder(Deprecated::class) + .addMember( + "%S", + "Use the supplier overload taking a Request, which also carries query parameters.", + ) + .build() + + val suppressDeprecationAnnotation = + AnnotationSpec.builder(Suppress::class).addMember("%S", "DEPRECATION").build() + + val byNamespaceDeprecatedFunction = + FunSpec.builder("namespace") + .addAnnotation(deprecatedAnnotation) + .addAnnotation(suppressDeprecationAnnotation) + .addAnnotation(JvmOverloads::class) + .addParameter(antNamespaceParameter) + .addParameter(configureParameter) + .addParameter(deprecatedSupplierParameter) + .addCode( + "%N(%N, %N, %T { %N(path, pathVariables) })", + byNamespaceFunction, + antNamespaceParameter, + configureParameter, + requestSupplierClassName, + deprecatedSupplierParameter, + ) + .build() + + val byPatternDeprecatedFunction = + FunSpec.builder("pattern") + .addAnnotation(deprecatedAnnotation) + .addAnnotation(suppressDeprecationAnnotation) + .addAnnotation(JvmOverloads::class) + .addParameter(patternParameter) + .addParameter(configureParameter) + .addParameter(deprecatedSupplierParameter) + .addCode( + """ + val namespace = %T(%N) + %N(namespace, %N, %N) + """ + .trimIndent(), + antPatternNamespaceClassName, + patternParameter, + byNamespaceDeprecatedFunction, + configureParameter, + deprecatedSupplierParameter, + ) + .build() + val byPathFunction = FunSpec.builder("path") .addAnnotation(JvmOverloads::class) @@ -112,7 +175,7 @@ object Active : FunctionProvider { """ val namespace = %T(%N) check(namespace.isExact) { %S } - %N(namespace, %N) { _, _ -> %N } + %N(namespace, %N) { %N } """ .trimIndent(), antPatternNamespaceClassName, @@ -151,7 +214,9 @@ object Active : FunctionProvider { return Functions( listOf( byNamespaceFunction, + byNamespaceDeprecatedFunction, byPatternFunction, + byPatternDeprecatedFunction, byPathFunction, byPathValueFunction, ), @@ -169,14 +234,14 @@ object Active : FunctionProvider { Bind a [%N] to a [%N] of data publishers. For example, if a [%T] for /fx/ is bound then when a request for /fx/gbpusd is received - the [%N] will be called with /fx/gbpusd as the %N parameter to return a [%T] which will be subscribed to + the [%N] will be called with a [%T] whose path is /fx/gbpusd to return a [%T] which will be subscribed to in order to provide data. - + @param %N A namespace for matching subjects for which this [%N] will be invoked. @param %N A configuration block that can be used to set up the behaviour of this publisher. @param %N This will be invoked on each incoming request. It should parse the `subject` and provide a %T capable of supplying data in response. - + @see %T @see %T @see %T @@ -186,7 +251,7 @@ object Active : FunctionProvider { flowSupplierParameter, prefixNamespaceClassName, flowSupplierParameter, - pathParameter, + requestClassName, publisherType, antNamespaceParameter, flowSupplierParameter, @@ -210,21 +275,21 @@ object Active : FunctionProvider { Bind an ant pattern to a [%N] of data publishers. For example, if [%N] is provided as /fx/* then when a request for /fx/gbpusd is received - the [%N] will be called with /fx/gbpusd as the %N parameter to return a [%T] which will be subscribed to + the [%N] will be called with a [%T] whose path is /fx/gbpusd to return a [%T] which will be subscribed to in order to provide data. - + @param %N The ant pattern for matching subjects for which this [%N] will be invoked. @param %N A configuration block that can be used to set up the behaviour of this publisher. @param %N This will be invoked on each incoming request. It should parse the `subject` and provide a %T capable of supplying data in response. - + @see %T """ .trimIndent(), flowSupplierParameter, patternParameter, flowSupplierParameter, - pathParameter, + requestClassName, publisherType, patternParameter, flowSupplierParameter, diff --git a/buildSrc/src/main/kotlin/ActiveContainer.kt b/buildSrc/src/main/kotlin/ActiveContainer.kt index 9af8511..15cac4e 100644 --- a/buildSrc/src/main/kotlin/ActiveContainer.kt +++ b/buildSrc/src/main/kotlin/ActiveContainer.kt @@ -1,3 +1,4 @@ +import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.MemberName @@ -46,7 +47,7 @@ object ActiveContainer : FunctionProvider { val publisherPatternSupplierParameter = ParameterSpec.builder( "supplier", - pathVariablesSupplierClassName.parameterizedBy( + requestSupplierClassName.parameterizedBy( publisherType.className.parameterizedBy(containerEventTypeName), ), ) @@ -60,7 +61,7 @@ object ActiveContainer : FunctionProvider { .addParameter(publisherPatternSupplierParameter) .addCode( """ - %N.%N(%N, %N) { path -> %N.asFlow(%N(path, %N.extractPathVariables(path))) } + %N.%N(%N, %N) { path -> %N.asFlow(with(%N) { %T(path, %N.extractPathVariables(path), %N.extractQueryParameters(path)).invoke() }) } """ .trimIndent(), binderProperty, @@ -69,6 +70,8 @@ object ActiveContainer : FunctionProvider { antNamespaceParameter, adapterProperty, publisherPatternSupplierParameter, + requestClassName, + antNamespaceParameter, antNamespaceParameter, ) .build() @@ -93,6 +96,66 @@ object ActiveContainer : FunctionProvider { ) .build() + val deprecatedSupplierParameter = + ParameterSpec.builder( + "supplier", + pathVariablesSupplierClassName.parameterizedBy( + publisherType.className.parameterizedBy(containerEventTypeName), + ), + ) + .build() + + val deprecatedAnnotation = + AnnotationSpec.builder(Deprecated::class) + .addMember( + "%S", + "Use the supplier overload taking a Request, which also carries query parameters.", + ) + .build() + + val suppressDeprecationAnnotation = + AnnotationSpec.builder(Suppress::class).addMember("%S", "DEPRECATION").build() + + val byNamespaceDeprecatedFunction = + FunSpec.builder("namespace") + .addAnnotation(deprecatedAnnotation) + .addAnnotation(suppressDeprecationAnnotation) + .addAnnotation(JvmOverloads::class) + .addParameter(antNamespaceParameter) + .addParameter(configureParameter) + .addParameter(deprecatedSupplierParameter) + .addCode( + "%N(%N, %N, %T { %N(path, pathVariables) })", + primaryFunction, + antNamespaceParameter, + configureParameter, + requestSupplierClassName, + deprecatedSupplierParameter, + ) + .build() + + val byPatternDeprecatedFunction = + FunSpec.builder("pattern") + .addAnnotation(deprecatedAnnotation) + .addAnnotation(suppressDeprecationAnnotation) + .addAnnotation(JvmOverloads::class) + .addParameter(patternParameter) + .addParameter(configureParameter) + .addParameter(deprecatedSupplierParameter) + .addCode( + """ + val namespace = %T(%N) + %N(namespace, %N, %N) + """ + .trimIndent(), + antPatternNamespaceClassName, + patternParameter, + byNamespaceDeprecatedFunction, + configureParameter, + deprecatedSupplierParameter, + ) + .build() + val byPathFunction = FunSpec.builder("path") .addAnnotation(JvmOverloads::class) @@ -103,7 +166,7 @@ object ActiveContainer : FunctionProvider { """ val namespace = %T(%N) check(namespace.isExact) { %S } - %N(namespace, %N) { _, _ -> %N } + %N(namespace, %N) { %N } """ .trimIndent(), antPatternNamespaceClassName, @@ -142,7 +205,9 @@ object ActiveContainer : FunctionProvider { return Functions( listOf( primaryFunction, + byNamespaceDeprecatedFunction, byPatternFunction, + byPatternDeprecatedFunction, byPathFunction, byPathValueFunction, ), diff --git a/buildSrc/src/main/kotlin/Channel.kt b/buildSrc/src/main/kotlin/Channel.kt index ce3c96e..6843935 100644 --- a/buildSrc/src/main/kotlin/Channel.kt +++ b/buildSrc/src/main/kotlin/Channel.kt @@ -1,4 +1,5 @@ import com.squareup.kotlinpoet.ANY +import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.FunSpec @@ -57,6 +58,13 @@ object Channel : FunctionProvider { if (publisherType.requiresProjection) WildcardTypeName.producerOf(parameterTypeName) else parameterTypeName + val channelRequestReceiveType = + channelRequestClassName.parameterizedBy( + publisherType.className.parameterizedBy( + if (parameterTypeName == ANY) r else parameterTypeName, + ), + ) + val channelSupplierParameter = ParameterSpec.builder( "supplier", @@ -69,10 +77,10 @@ object Channel : FunctionProvider { ) .build() - val pathVariablesChannelSupplierParameter = + val channelRequestSupplierParameter = ParameterSpec.builder( "supplier", - pathVariablesChannelSupplierClassName.parameterizedBy( + channelRequestSupplierClassName.parameterizedBy( publisherType.className.parameterizedBy( if (parameterTypeName == ANY) r else parameterTypeName, ), @@ -91,10 +99,10 @@ object Channel : FunctionProvider { } } .addParameter(configureParameter) - .addParameter(pathVariablesChannelSupplierParameter) + .addParameter(channelRequestSupplierParameter) .addCode( """ - %N.%N(%N, %N,%L) { path, pathVariables, receive -> %N.asFlow(%N(path, pathVariables, %N.asPublisher(receive))) } + %N.%N(%N, %N,%L) { request -> %N.asFlow(with(%N) { %T(request.path, request.pathVariables, request.queryParameters, %N.asPublisher(request.receive)).invoke() }) } """ .trimIndent(), binderProperty, @@ -104,7 +112,8 @@ object Channel : FunctionProvider { if (parameterTypeName == ANY) CodeBlock.of(" %N,", receiveType) else CodeBlock.of(""), adapterProperty, - pathVariablesChannelSupplierParameter, + channelRequestSupplierParameter, + channelRequestReceiveType, adapterProperty, ) .build() @@ -120,7 +129,7 @@ object Channel : FunctionProvider { } } .addParameter(configureParameter) - .addParameter(pathVariablesChannelSupplierParameter) + .addParameter(channelRequestSupplierParameter) .addCode( """ %N(%N, %T::class.java, %N, %N) @@ -130,7 +139,7 @@ object Channel : FunctionProvider { antNamespaceParameter, r, configureParameter, - pathVariablesChannelSupplierParameter, + channelRequestSupplierParameter, ) .build() else null @@ -145,7 +154,7 @@ object Channel : FunctionProvider { } } .addParameter(configureParameter) - .addParameter(pathVariablesChannelSupplierParameter) + .addParameter(channelRequestSupplierParameter) .addCode( """ val namespace = %T(%N) @@ -158,7 +167,7 @@ object Channel : FunctionProvider { if (parameterTypeName == ANY) CodeBlock.of(" %N,", receiveType) else CodeBlock.of(""), configureParameter, - pathVariablesChannelSupplierParameter, + channelRequestSupplierParameter, ) .build() @@ -173,7 +182,7 @@ object Channel : FunctionProvider { } } .addParameter(configureParameter) - .addParameter(pathVariablesChannelSupplierParameter) + .addParameter(channelRequestSupplierParameter) .addCode( """ %N(%N, %T::class.java, %N, %N) @@ -183,6 +192,126 @@ object Channel : FunctionProvider { patternParameter, r, configureParameter, + channelRequestSupplierParameter, + ) + .build() + else null + + val receiveTypeCode = + if (parameterTypeName == ANY) CodeBlock.of(" %N,", receiveType) else CodeBlock.of("") + + val pathVariablesChannelSupplierParameter = + ParameterSpec.builder( + "supplier", + pathVariablesChannelSupplierClassName.parameterizedBy( + publisherType.className.parameterizedBy( + if (parameterTypeName == ANY) r else parameterTypeName, + ), + publisherType.className.parameterizedBy(projectedParameterTypeName), + ), + ) + .build() + + val deprecatedAnnotation = + AnnotationSpec.builder(Deprecated::class) + .addMember( + "%S", + "Use the supplier overload taking a ChannelRequest, which also carries query parameters.", + ) + .build() + + val suppressDeprecationAnnotation = + AnnotationSpec.builder(Suppress::class).addMember("%S", "DEPRECATION").build() + + val byNamespaceDeprecatedFunction = + FunSpec.builder("namespace") + .addAnnotation(deprecatedAnnotation) + .addAnnotation(suppressDeprecationAnnotation) + .addParameter(antNamespaceParameter) + .apply { + if (parameterTypeName == ANY) { + addTypeVariable(r) + addParameter(receiveType) + } + } + .addParameter(configureParameter) + .addParameter(pathVariablesChannelSupplierParameter) + .addCode( + "%N(%N,%L %N, %T { %N(path, pathVariables, receive) })", + byNamespaceFunction, + antNamespaceParameter, + receiveTypeCode, + configureParameter, + channelRequestSupplierClassName, + pathVariablesChannelSupplierParameter, + ) + .build() + + val byNamespaceReifiedDeprecatedFunction = + if (parameterTypeName == ANY) + FunSpec.builder("namespace") + .addAnnotation(deprecatedAnnotation) + .addAnnotation(suppressDeprecationAnnotation) + .addModifiers(INLINE) + .addTypeVariable(r.copy(reified = true)) + .addParameter(antNamespaceParameter) + .addParameter(configureParameter) + .addParameter(pathVariablesChannelSupplierParameter) + .addCode( + "%N(%N, %T::class.java, %N, %N)", + byNamespaceDeprecatedFunction, + antNamespaceParameter, + r, + configureParameter, + pathVariablesChannelSupplierParameter, + ) + .build() + else null + + val byPatternDeprecatedFunction = + FunSpec.builder("pattern") + .addAnnotation(deprecatedAnnotation) + .addAnnotation(suppressDeprecationAnnotation) + .addParameter(patternParameter) + .apply { + if (parameterTypeName == ANY) { + addTypeVariable(r) + addParameter(receiveType) + } + } + .addParameter(configureParameter) + .addParameter(pathVariablesChannelSupplierParameter) + .addCode( + """ + val namespace = %T(%N) + %N(namespace,%L %N, %N) + """ + .trimIndent(), + antPatternNamespaceClassName, + patternParameter, + byNamespaceDeprecatedFunction, + receiveTypeCode, + configureParameter, + pathVariablesChannelSupplierParameter, + ) + .build() + + val byPatternReifiedDeprecatedFunction = + if (parameterTypeName == ANY) + FunSpec.builder("pattern") + .addAnnotation(deprecatedAnnotation) + .addAnnotation(suppressDeprecationAnnotation) + .addModifiers(INLINE) + .addTypeVariable(r.copy(reified = true)) + .addParameter(patternParameter) + .addParameter(configureParameter) + .addParameter(pathVariablesChannelSupplierParameter) + .addCode( + "%N(%N, %T::class.java, %N, %N)", + byPatternDeprecatedFunction, + patternParameter, + r, + configureParameter, pathVariablesChannelSupplierParameter, ) .build() @@ -210,7 +339,7 @@ object Channel : FunctionProvider { """ val namespace = %T(%N) check(namespace.isExact) { %S } - %N(namespace,%L %N) { _, _, %N -> %N(%N) } + %N(namespace,%L %N) { %N(receive) } """ .trimIndent(), antPatternNamespaceClassName, @@ -220,9 +349,7 @@ object Channel : FunctionProvider { if (parameterTypeName == ANY) CodeBlock.of(" %N,", receiveType) else CodeBlock.of(""), configureParameter, - receivedFlowParameter, channelSupplierParameter, - receivedFlowParameter, ) .build() @@ -256,8 +383,12 @@ object Channel : FunctionProvider { listOfNotNull( byNamespaceFunction, byNamespaceReifiedFunction, + byNamespaceDeprecatedFunction, + byNamespaceReifiedDeprecatedFunction, byPatternFunction, byPatternReifiedFunction, + byPatternDeprecatedFunction, + byPatternReifiedDeprecatedFunction, byPathFunction, byPathReifiedFunction, ), diff --git a/buildSrc/src/main/kotlin/Constants.kt b/buildSrc/src/main/kotlin/Constants.kt index ac8dc4a..55325c8 100644 --- a/buildSrc/src/main/kotlin/Constants.kt +++ b/buildSrc/src/main/kotlin/Constants.kt @@ -45,10 +45,18 @@ val containerEventBulkClassName = ClassName(apiPackageName, "ContainerEvent.Bulk val containerEventRowEventUpsertClassName = ClassName(apiPackageName, "ContainerEvent.RowEvent.Upsert") val pathSupplierClassName = ClassName(apiPackageName, "PathSupplier") +val requestClassName = ClassName(apiPackageName, "Request") +val requestSupplierClassName = ClassName(apiPackageName, "RequestSupplier") +val channelRequestClassName = ClassName(apiPackageName, "ChannelRequest") +val channelRequestSupplierClassName = ClassName(apiPackageName, "ChannelRequestSupplier") +val channelSupplierClassName = ClassName(apiPackageName, "ChannelSupplier") + +@Suppress("DEPRECATION") val pathVariablesSupplierClassName = ClassName(apiPackageName, "PathVariablesSupplier") + +@Suppress("DEPRECATION") val pathVariablesChannelSupplierClassName = ClassName(apiPackageName, "PathVariablesChannelSupplier") -val channelSupplierClassName = ClassName(apiPackageName, "ChannelSupplier") val configBlockClassName = ClassName(apiPackageName, "ConfigBlock") val pathParameter = ParameterSpec.builder("path", STRING).build() diff --git a/buildSrc/src/main/kotlin/GenerateApi.kt b/buildSrc/src/main/kotlin/GenerateApi.kt index 9fc949f..1bf3ce2 100644 --- a/buildSrc/src/main/kotlin/GenerateApi.kt +++ b/buildSrc/src/main/kotlin/GenerateApi.kt @@ -1,4 +1,5 @@ import com.squareup.kotlinpoet.ANY +import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec @@ -161,7 +162,14 @@ abstract class GenerateApi : DefaultTask() { .build() val packageName = "$rootPackageName.${publisherType.packageName}" - val fileBuilder = FileSpec.builder(packageName, bindTypeName) + val fileBuilder = + FileSpec.builder(packageName, bindTypeName) + .addAnnotation( + AnnotationSpec.builder(Suppress::class) + .useSiteTarget(AnnotationSpec.UseSiteTarget.FILE) + .addMember("%S", "DEPRECATION") + .build(), + ) val classBuilder = TypeSpec.classBuilder(ClassName(packageName, bindTypeName)) diff --git a/reactive/api/api/datasourcex-reactive-api.api b/reactive/api/api/datasourcex-reactive-api.api index a4a99a9..50d0ef1 100644 --- a/reactive/api/api/datasourcex-reactive-api.api +++ b/reactive/api/api/datasourcex-reactive-api.api @@ -103,6 +103,18 @@ public final class com/caplin/integration/datasourcex/reactive/api/ChannelConfig public final fun setRecordType (Lcom/caplin/integration/datasourcex/reactive/api/RecordType;)V } +public final class com/caplin/integration/datasourcex/reactive/api/ChannelRequest { + public fun (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/lang/Object;)V + public final fun getPath ()Ljava/lang/String; + public final fun getPathVariables ()Ljava/util/Map; + public final fun getQueryParameters ()Ljava/util/Map; + public final fun getReceive ()Ljava/lang/Object; +} + +public abstract interface class com/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier { + public abstract fun invoke (Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequest;)Ljava/lang/Object; +} + public abstract interface class com/caplin/integration/datasourcex/reactive/api/ChannelSupplier { public abstract fun invoke (Ljava/lang/Object;)Ljava/lang/Object; } @@ -189,6 +201,17 @@ public final class com/caplin/integration/datasourcex/reactive/api/RecordType : public static fun values ()[Lcom/caplin/integration/datasourcex/reactive/api/RecordType; } +public final class com/caplin/integration/datasourcex/reactive/api/Request { + public fun (Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;)V + public final fun getPath ()Ljava/lang/String; + public final fun getPathVariables ()Ljava/util/Map; + public final fun getQueryParameters ()Ljava/util/Map; +} + +public abstract interface class com/caplin/integration/datasourcex/reactive/api/RequestSupplier { + public abstract fun invoke (Lcom/caplin/integration/datasourcex/reactive/api/Request;)Ljava/lang/Object; +} + public final class com/caplin/integration/datasourcex/reactive/api/ServiceConfig { public fun (Ljava/lang/String;)V public final fun getDiscardTimeout ()Ljava/time/Duration; diff --git a/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/ChannelRequest.kt b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/ChannelRequest.kt new file mode 100644 index 0000000..8454c5b --- /dev/null +++ b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/ChannelRequest.kt @@ -0,0 +1,17 @@ +package com.caplin.integration.datasourcex.reactive.api + +/** + * A decomposed subject request passed to a supplier for a channel bind. + * + * @property path The full requested subject. + * @property pathVariables The path variables extracted from the subject, keyed by name. + * @property queryParameters The query parameters parsed from the subject's optional trailing + * `?a=b&c=d`, or empty when there is no query. + * @property receive The flow of messages received from the client on this channel. + */ +class ChannelRequest( + val path: String, + val pathVariables: Map, + val queryParameters: Map, + val receive: R, +) diff --git a/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier.kt b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier.kt new file mode 100644 index 0000000..9605197 --- /dev/null +++ b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier.kt @@ -0,0 +1,5 @@ +package com.caplin.integration.datasourcex.reactive.api + +fun interface ChannelRequestSupplier { + operator fun ChannelRequest.invoke(): T +} diff --git a/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier.kt b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier.kt index 2360019..6b0e9f4 100644 --- a/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier.kt +++ b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier.kt @@ -1,5 +1,9 @@ package com.caplin.integration.datasourcex.reactive.api +@Deprecated( + "Use ChannelRequestSupplier, whose ChannelRequest also carries the subject's query parameters.", + ReplaceWith("ChannelRequestSupplier"), +) fun interface PathVariablesChannelSupplier { operator fun invoke(path: String, pathVariables: Map, receive: R): T } diff --git a/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier.kt b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier.kt index 706e1e2..a847ff6 100644 --- a/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier.kt +++ b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier.kt @@ -1,5 +1,9 @@ package com.caplin.integration.datasourcex.reactive.api +@Deprecated( + "Use RequestSupplier, whose Request also carries the subject's query parameters.", + ReplaceWith("RequestSupplier"), +) fun interface PathVariablesSupplier { operator fun invoke(path: String, pathVariables: Map): T } diff --git a/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/Request.kt b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/Request.kt new file mode 100644 index 0000000..41c1f32 --- /dev/null +++ b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/Request.kt @@ -0,0 +1,15 @@ +package com.caplin.integration.datasourcex.reactive.api + +/** + * A decomposed subject request passed to a supplier for an active or container bind. + * + * @property path The full requested subject. + * @property pathVariables The path variables extracted from the subject, keyed by name. + * @property queryParameters The query parameters parsed from the subject's optional trailing + * `?a=b&c=d`, or empty when there is no query. + */ +class Request( + val path: String, + val pathVariables: Map, + val queryParameters: Map, +) diff --git a/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/RequestSupplier.kt b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/RequestSupplier.kt new file mode 100644 index 0000000..fac71d2 --- /dev/null +++ b/reactive/api/src/main/kotlin/com/caplin/integration/datasourcex/reactive/api/RequestSupplier.kt @@ -0,0 +1,5 @@ +package com.caplin.integration.datasourcex.reactive.api + +fun interface RequestSupplier { + operator fun Request.invoke(): T +} diff --git a/reactive/core/src/main/kotlin/com/caplin/integration/datasourcex/reactive/core/Binder.kt b/reactive/core/src/main/kotlin/com/caplin/integration/datasourcex/reactive/core/Binder.kt index 47d81fd..a410bb3 100644 --- a/reactive/core/src/main/kotlin/com/caplin/integration/datasourcex/reactive/core/Binder.kt +++ b/reactive/core/src/main/kotlin/com/caplin/integration/datasourcex/reactive/core/Binder.kt @@ -29,12 +29,12 @@ import com.caplin.integration.datasourcex.reactive.api.ActiveContainerConfig import com.caplin.integration.datasourcex.reactive.api.BroadcastConfig import com.caplin.integration.datasourcex.reactive.api.BroadcastEvent import com.caplin.integration.datasourcex.reactive.api.ChannelConfig +import com.caplin.integration.datasourcex.reactive.api.ChannelRequest import com.caplin.integration.datasourcex.reactive.api.ChannelType import com.caplin.integration.datasourcex.reactive.api.ConfigBlock import com.caplin.integration.datasourcex.reactive.api.ContainerEvent import com.caplin.integration.datasourcex.reactive.api.InsertAt import com.caplin.integration.datasourcex.reactive.api.PathSupplier -import com.caplin.integration.datasourcex.reactive.api.PathVariablesChannelSupplier import com.caplin.integration.datasourcex.reactive.api.RecordType import com.caplin.integration.datasourcex.reactive.api.ServiceConfig import com.caplin.integration.datasourcex.util.AntPatternNamespace @@ -223,7 +223,7 @@ private constructor(val dataSource: ScopedDataSource, private val serviceInfo: S fun bindChannelRecord( configure: ConfigBlock, namespace: AntPatternNamespace, - supplier: PathVariablesChannelSupplier>, Flow>>, + supplier: (ChannelRequest>>) -> Flow>, ) { val config = with(configure) { ChannelConfig.Record().apply { invoke() } } serviceInfo?.registerNamespace(namespace, config.objectMappings) @@ -285,9 +285,12 @@ private constructor(val dataSource: ScopedDataSource, private val serviceInfo: S val sendToClientJob = supplier( - channel.subject, - namespace.extractPathVariables(channel.subject), - fromClientChannel.consumeAsFlow(), + ChannelRequest( + channel.subject, + namespace.extractPathVariables(channel.subject), + namespace.extractQueryParameters(channel.subject), + fromClientChannel.consumeAsFlow(), + ), ) .onEach { value -> channel.sendMessage(channel.createMessage(value)) } .onCompletion { throwable -> @@ -316,7 +319,7 @@ private constructor(val dataSource: ScopedDataSource, private val serviceInfo: S configure: ConfigBlock, namespace: AntPatternNamespace, receiveType: Class, - supplier: PathVariablesChannelSupplier, Flow>, + supplier: (ChannelRequest>) -> Flow, ) { val config = with(configure) { ChannelConfig.Json().apply { invoke() } } serviceInfo?.registerNamespace(namespace, config.objectMappings) @@ -366,9 +369,12 @@ private constructor(val dataSource: ScopedDataSource, private val serviceInfo: S val sendToClientJob = supplier( - channel.subject, - namespace.extractPathVariables(channel.subject), - fromClientChannel.consumeAsFlow(), + ChannelRequest( + channel.subject, + namespace.extractPathVariables(channel.subject), + namespace.extractQueryParameters(channel.subject), + fromClientChannel.consumeAsFlow(), + ), ) .onEach { value -> channel.send(value) } .onCompletion { throwable -> diff --git a/reactive/java-flow/api/datasourcex-java-flow.api b/reactive/java-flow/api/datasourcex-java-flow.api index 5f40c6f..fbc7a76 100644 --- a/reactive/java-flow/api/datasourcex-java-flow.api +++ b/reactive/java-flow/api/datasourcex-java-flow.api @@ -39,8 +39,11 @@ public final class com/caplin/integration/datasourcex/reactive/java/BindActiveCo public final class com/caplin/integration/datasourcex/reactive/java/BindActiveContainerJson { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/util/Map;)V public final fun path (Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Ljava/util/concurrent/Flow$Publisher;)V @@ -48,14 +51,20 @@ public final class com/caplin/integration/datasourcex/reactive/java/BindActiveCo public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerJson;Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerJson;Ljava/lang/String;Ljava/util/concurrent/Flow$Publisher;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/java/BindActiveContainerRecord { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/util/Map;)V public final fun path (Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Ljava/util/concurrent/Flow$Publisher;)V @@ -63,14 +72,20 @@ public final class com/caplin/integration/datasourcex/reactive/java/BindActiveCo public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerRecord;Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerRecord;Ljava/lang/String;Ljava/util/concurrent/Flow$Publisher;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveContainerRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/java/BindActiveJson { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/Object;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Ljava/util/concurrent/Flow$Publisher;)V @@ -78,14 +93,20 @@ public final class com/caplin/integration/datasourcex/reactive/java/BindActiveJs public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveJson;Ljava/lang/String;Ljava/lang/Object;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveJson;Ljava/lang/String;Ljava/util/concurrent/Flow$Publisher;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/java/BindActiveMapping { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveMapping;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveMapping;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/String;)V public final fun path (Ljava/lang/String;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Ljava/util/concurrent/Flow$Publisher;)V @@ -93,14 +114,20 @@ public final class com/caplin/integration/datasourcex/reactive/java/BindActiveMa public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveMapping;Ljava/lang/String;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveMapping;Ljava/lang/String;Ljava/util/concurrent/Flow$Publisher;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveMapping;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveMapping;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/java/BindActiveRecord { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/util/Map;)V public final fun path (Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Ljava/util/concurrent/Flow$Publisher;)V @@ -108,8 +135,11 @@ public final class com/caplin/integration/datasourcex/reactive/java/BindActiveRe public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveRecord;Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveRecord;Ljava/lang/String;Ljava/util/concurrent/Flow$Publisher;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindActiveRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/java/BindBroadcast { @@ -157,20 +187,28 @@ public final class com/caplin/integration/datasourcex/reactive/java/BindChannel } public final class com/caplin/integration/datasourcex/reactive/java/BindChannelJson { + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindChannelJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindChannelJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindChannelJson;Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;ILjava/lang/Object;)V + public final fun pattern (Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun pattern (Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindChannelJson;Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindChannelJson;Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/java/BindChannelRecord { + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindChannelRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/java/BindChannelRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/java/BindChannelRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;ILjava/lang/Object;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindChannelRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/java/BindChannelRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V } diff --git a/reactive/java-flow/src/samples/kotlin/samples/Samples.kt b/reactive/java-flow/src/samples/kotlin/samples/Samples.kt index 51868dd..f40cbbe 100644 --- a/reactive/java-flow/src/samples/kotlin/samples/Samples.kt +++ b/reactive/java-flow/src/samples/kotlin/samples/Samples.kt @@ -31,9 +31,9 @@ class Samples { pattern( pattern = "/example/{username}/subjectPattern/{myKey}", configure = { objectMappings = mapOf("username" to "%u") }, - supplier = { _, parameters -> - val username = parameters["username"] - val myKey = parameters["myKey"] + supplier = { + val username = pathVariables["username"] + val myKey = pathVariables["myKey"] FlowAdapters.toFlowPublisher( Flux.interval(Duration.ofSeconds(1)).map { count: Long -> JsonObject("$username $myKey $count") diff --git a/reactive/kotlin/api/datasourcex-kotlin.api b/reactive/kotlin/api/datasourcex-kotlin.api index c4e255f..5cd2ac0 100644 --- a/reactive/kotlin/api/datasourcex-kotlin.api +++ b/reactive/kotlin/api/datasourcex-kotlin.api @@ -26,8 +26,11 @@ public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActive public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerJson { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/util/Map;)V public final fun path (Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Lkotlinx/coroutines/flow/Flow;)V @@ -35,14 +38,20 @@ public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActive public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerJson;Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerJson;Ljava/lang/String;Lkotlinx/coroutines/flow/Flow;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerRecord { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/util/Map;)V public final fun path (Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Lkotlinx/coroutines/flow/Flow;)V @@ -50,14 +59,20 @@ public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActive public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerRecord;Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerRecord;Ljava/lang/String;Lkotlinx/coroutines/flow/Flow;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveContainerRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActiveJson { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/Object;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Lkotlinx/coroutines/flow/Flow;)V @@ -65,14 +80,20 @@ public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActive public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveJson;Ljava/lang/String;Ljava/lang/Object;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveJson;Ljava/lang/String;Lkotlinx/coroutines/flow/Flow;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActiveMapping { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveMapping;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveMapping;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/String;)V public final fun path (Ljava/lang/String;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Lkotlinx/coroutines/flow/Flow;)V @@ -80,14 +101,20 @@ public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActive public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveMapping;Ljava/lang/String;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveMapping;Ljava/lang/String;Lkotlinx/coroutines/flow/Flow;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveMapping;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveMapping;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActiveRecord { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/util/Map;)V public final fun path (Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Lkotlinx/coroutines/flow/Flow;)V @@ -95,8 +122,11 @@ public final class com/caplin/integration/datasourcex/reactive/kotlin/BindActive public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveRecord;Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveRecord;Ljava/lang/String;Lkotlinx/coroutines/flow/Flow;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindActiveRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/kotlin/BindBroadcast { @@ -144,20 +174,28 @@ public final class com/caplin/integration/datasourcex/reactive/kotlin/BindChanne } public final class com/caplin/integration/datasourcex/reactive/kotlin/BindChannelJson { + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindChannelJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindChannelJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindChannelJson;Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;ILjava/lang/Object;)V + public final fun pattern (Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun pattern (Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindChannelJson;Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindChannelJson;Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/kotlin/BindChannelRecord { + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindChannelRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindChannelRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindChannelRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;ILjava/lang/Object;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindChannelRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/kotlin/BindChannelRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V } diff --git a/reactive/kotlin/src/samples/kotlin/samples/Samples.kt b/reactive/kotlin/src/samples/kotlin/samples/Samples.kt index 5ff16b9..e753277 100644 --- a/reactive/kotlin/src/samples/kotlin/samples/Samples.kt +++ b/reactive/kotlin/src/samples/kotlin/samples/Samples.kt @@ -30,9 +30,9 @@ class Samples { pattern( pattern = "/{username}/example/subjectPattern/{myKey}", configure = { objectMappings = mapOf("username" to "%u") }, - ) { _, parameters -> - val username: String by parameters - val myKey: String by parameters + ) { + val username: String by pathVariables + val myKey: String by pathVariables flow { var count = 0 while (true) { diff --git a/reactive/kotlin/src/test/kotlin/com/caplin/integration/datasourcex/reactive/kotlin/BindTest.kt b/reactive/kotlin/src/test/kotlin/com/caplin/integration/datasourcex/reactive/kotlin/BindTest.kt index 916402f..eb33d0b 100644 --- a/reactive/kotlin/src/test/kotlin/com/caplin/integration/datasourcex/reactive/kotlin/BindTest.kt +++ b/reactive/kotlin/src/test/kotlin/com/caplin/integration/datasourcex/reactive/kotlin/BindTest.kt @@ -15,6 +15,8 @@ import com.caplin.integration.datasourcex.reactive.api.ContainerEvent import com.caplin.integration.datasourcex.reactive.api.ContainerEvent.RowEvent.Remove import com.caplin.integration.datasourcex.reactive.api.ContainerEvent.RowEvent.Upsert import com.caplin.integration.datasourcex.reactive.api.InsertAt.HEAD +import com.caplin.integration.datasourcex.reactive.api.Request +import com.caplin.integration.datasourcex.reactive.api.RequestSupplier import com.caplin.integration.datasourcex.util.AntPatternNamespace import com.caplin.integration.datasourcex.util.flow.ValueOrCompletion import com.caplin.integration.datasourcex.util.flow.ValueOrCompletion.Completion @@ -97,30 +99,27 @@ class BindTest : String, MutableSharedFlow>>>, >() - val genericContainerFunction: - (String, Map) -> Flow>> = - { containerSubject: String, _: Map -> + val genericContainerFunction: RequestSupplier>>> = + RequestSupplier { MutableSharedFlow>>>() - .also { requestedContainerSubjects[containerSubject] = it } + .also { requestedContainerSubjects[path] = it } .dematerialize() } val requestedGenericSubjects = ConcurrentHashMap>>>() - val genericSubjectFunction: (String, Map) -> Flow> = - { subject: String, _: Map -> - MutableSharedFlow>>() - .also { requestedGenericSubjects[subject] = it } - .dematerialize() - } + val genericSubjectFunction: RequestSupplier>> = RequestSupplier { + MutableSharedFlow>>() + .also { requestedGenericSubjects[path] = it } + .dematerialize() + } val requestedJsonSubjects = mutableMapOf>>() - val jsonSubjectFunction: (String, Map) -> Flow = - { subject: String, _: Map -> - MutableSharedFlow>() - .also { requestedJsonSubjects[subject] = it } - .dematerialize() - } + val jsonSubjectFunction: RequestSupplier> = RequestSupplier { + MutableSharedFlow>() + .also { requestedJsonSubjects[path] = it } + .dematerialize() + } test("Generic Container - Emits empty update after timeout") { dataSource.bind(scope = backgroundScope) { @@ -664,4 +663,27 @@ class BindTest : sharedFlow.subscriptionCount.value shouldBeEqual 0 } + + test("Json - receiver supplier receives decoded path variables and query parameters") { + var captured: Request? = null + dataSource.bind(scope = backgroundScope) { + active { + json { + namespace(AntPatternNamespace("/QUERY/{productPair}")) { + captured = this + MutableSharedFlow>().dematerialize() + } + } + } + } + + dataProviderCaptor.onRequest("/QUERY/EUR%2FUSD?location=ONSHORE&tenor=SPOT") + delay(1.milliseconds) + + captured!!.also { request -> + request.path shouldBeEqual "/QUERY/EUR%2FUSD?location=ONSHORE&tenor=SPOT" + request.pathVariables shouldBeEqual mapOf("productPair" to "EUR/USD") + request.queryParameters shouldBeEqual mapOf("location" to "ONSHORE", "tenor" to "SPOT") + } + } }) diff --git a/reactive/reactivestreams/api/datasourcex-reactivestreams.api b/reactive/reactivestreams/api/datasourcex-reactivestreams.api index 60e63ee..085460f 100644 --- a/reactive/reactivestreams/api/datasourcex-reactivestreams.api +++ b/reactive/reactivestreams/api/datasourcex-reactivestreams.api @@ -39,8 +39,11 @@ public final class com/caplin/integration/datasourcex/reactive/reactivestreams/B public final class com/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerJson { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/util/Map;)V public final fun path (Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Lorg/reactivestreams/Publisher;)V @@ -48,14 +51,20 @@ public final class com/caplin/integration/datasourcex/reactive/reactivestreams/B public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerJson;Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerJson;Ljava/lang/String;Lorg/reactivestreams/Publisher;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerRecord { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/util/Map;)V public final fun path (Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Lorg/reactivestreams/Publisher;)V @@ -63,14 +72,20 @@ public final class com/caplin/integration/datasourcex/reactive/reactivestreams/B public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerRecord;Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerRecord;Ljava/lang/String;Lorg/reactivestreams/Publisher;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveContainerRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveJson { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/Object;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Lorg/reactivestreams/Publisher;)V @@ -78,14 +93,20 @@ public final class com/caplin/integration/datasourcex/reactive/reactivestreams/B public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveJson;Ljava/lang/String;Ljava/lang/Object;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveJson;Ljava/lang/String;Lorg/reactivestreams/Publisher;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveJson;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveMapping { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveMapping;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveMapping;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/String;)V public final fun path (Ljava/lang/String;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Lorg/reactivestreams/Publisher;)V @@ -93,14 +114,20 @@ public final class com/caplin/integration/datasourcex/reactive/reactivestreams/B public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveMapping;Ljava/lang/String;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveMapping;Ljava/lang/String;Lorg/reactivestreams/Publisher;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveMapping;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveMapping;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveRecord { public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/util/Map;)V public final fun path (Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;)V public final fun path (Ljava/lang/String;Lorg/reactivestreams/Publisher;)V @@ -108,8 +135,11 @@ public final class com/caplin/integration/datasourcex/reactive/reactivestreams/B public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveRecord;Ljava/lang/String;Ljava/util/Map;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveRecord;Ljava/lang/String;Lorg/reactivestreams/Publisher;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;ILjava/lang/Object;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesSupplier;ILjava/lang/Object;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindActiveRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/RequestSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/reactivestreams/BindBroadcast { @@ -157,20 +187,28 @@ public final class com/caplin/integration/datasourcex/reactive/reactivestreams/B } public final class com/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelJson { + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelJson;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelJson;Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;ILjava/lang/Object;)V + public final fun pattern (Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun pattern (Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelJson;Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelJson;Ljava/lang/String;Ljava/lang/Class;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V } public final class com/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelRecord { + public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun namespace (Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun namespace$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelRecord;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V public final fun path (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;)V public static synthetic fun path$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelSupplier;ILjava/lang/Object;)V + public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;)V public final fun pattern (Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;)V + public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/ChannelRequestSupplier;ILjava/lang/Object;)V public static synthetic fun pattern$default (Lcom/caplin/integration/datasourcex/reactive/reactivestreams/BindChannelRecord;Ljava/lang/String;Lcom/caplin/integration/datasourcex/reactive/api/ConfigBlock;Lcom/caplin/integration/datasourcex/reactive/api/PathVariablesChannelSupplier;ILjava/lang/Object;)V } diff --git a/reactive/reactivestreams/src/samples/kotlin/samples/Samples.kt b/reactive/reactivestreams/src/samples/kotlin/samples/Samples.kt index 03ce120..0832fb0 100644 --- a/reactive/reactivestreams/src/samples/kotlin/samples/Samples.kt +++ b/reactive/reactivestreams/src/samples/kotlin/samples/Samples.kt @@ -27,9 +27,9 @@ class Samples { pattern( pattern = "/example/{username}/subjectPattern/{myKey}", configure = { objectMappings = mapOf("username" to "%u") }, - supplier = { _, parameters -> - val username = parameters["username"] - val myKey = parameters["myKey"] + supplier = { + val username = pathVariables["username"] + val myKey = pathVariables["myKey"] Flux.interval(Duration.ofSeconds(1)).map { count: Long -> JsonObject("$username $myKey $count") } diff --git a/spring/src/main/kotlin/com/caplin/integration/datasourcex/spring/internal/DataSourceServerBootstrap.kt b/spring/src/main/kotlin/com/caplin/integration/datasourcex/spring/internal/DataSourceServerBootstrap.kt index 7628742..d3df4f8 100644 --- a/spring/src/main/kotlin/com/caplin/integration/datasourcex/spring/internal/DataSourceServerBootstrap.kt +++ b/spring/src/main/kotlin/com/caplin/integration/datasourcex/spring/internal/DataSourceServerBootstrap.kt @@ -11,7 +11,6 @@ import com.caplin.integration.datasourcex.spring.internal.DataSourceRequestTypeM import com.caplin.integration.datasourcex.util.AntPatternNamespace import com.caplin.integration.datasourcex.util.AntPatternNamespace.Companion.addIncludeNamespace import com.caplin.integration.datasourcex.util.getLogger -import java.nio.charset.Charset import java.time.Duration import java.util.concurrent.atomic.AtomicReference import kotlinx.coroutines.awaitCancellation @@ -48,7 +47,7 @@ internal class DataSourceServerBootstrap( private val logger = getLogger() private val emptyPayload = emptyFlow().asPublisher() - internal val bootstrapCharset = Charset.forName("UTF-8") + internal val bootstrapCharset = AntPatternNamespace.CHARSET private val fireAndForgetOkResponse = mapOf("Result" to "ok") } @@ -193,8 +192,8 @@ internal class DataSourceServerBootstrap( pattern, dataSourceRequestType.payloadType!!, { channelType = dataSourceRequestType.channelType }, - ) { subject, _, receiveFlow -> - createFlow(subject, receiveFlow) + ) { + createFlow(path, receive) } } } @@ -217,8 +216,8 @@ internal class DataSourceServerBootstrap( else -> error("Unreachable") } }, - ) { subject, _, receiveFlow -> - createFlow(subject, receiveFlow) + ) { + createFlow(path, receive) } } } @@ -255,15 +254,13 @@ internal class DataSourceServerBootstrap( when (val type = dataSourceRequestType.type) { RequestType.Stream.ObjectType.MAPPING -> - active { mapping { pattern(pattern) { subject, _ -> createFlow(subject) } } } + active { mapping { pattern(pattern) { createFlow(path) } } } RequestType.Stream.ObjectType.JSON -> - active { json { pattern(pattern) { subject, _ -> createFlow(subject) } } } + active { json { pattern(pattern) { createFlow(path) } } } RequestType.Stream.ObjectType.CONTAINER_JSON -> - activeContainer { - json { pattern(pattern) { subject, _ -> createFlow(subject) } } - } + activeContainer { json { pattern(pattern) { createFlow(path) } } } RequestType.Stream.ObjectType.TYPE1, RequestType.Stream.ObjectType.GENERIC -> @@ -281,8 +278,8 @@ internal class DataSourceServerBootstrap( else -> error("Unreachable") } }, - ) { subject, _ -> - createFlow(subject) + ) { + createFlow(path) } } } @@ -305,8 +302,8 @@ internal class DataSourceServerBootstrap( else -> error("Unreachable") } }, - ) { subject, _ -> - createFlow(subject) + ) { + createFlow(path) } } } diff --git a/util/api/datasourcex-util.api b/util/api/datasourcex-util.api index 14874b8..260b4eb 100644 --- a/util/api/datasourcex-util.api +++ b/util/api/datasourcex-util.api @@ -1,9 +1,11 @@ public final class com/caplin/integration/datasourcex/util/AntPatternNamespace : com/caplin/datasource/namespace/Namespace { + public static final field CHARSET Ljava/nio/charset/Charset; public static final field Companion Lcom/caplin/integration/datasourcex/util/AntPatternNamespace$Companion; public fun (Ljava/lang/String;)V public static final fun addExcludeNamespace (Lcom/caplin/datasource/Service;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;)V public static final fun addIncludeNamespace (Lcom/caplin/datasource/Service;Lcom/caplin/integration/datasourcex/util/AntPatternNamespace;)V public final fun extractPathVariables (Ljava/lang/String;)Ljava/util/Map; + public final fun extractQueryParameters (Ljava/lang/String;)Ljava/util/Map; public final fun getObjectMap (Ljava/util/Map;)Lcom/caplin/integration/datasourcex/util/AntPatternNamespace$ObjectMap; public final fun getPathVariables ()Ljava/util/Set; public final fun getPattern ()Ljava/lang/String; diff --git a/util/src/main/kotlin/com/caplin/integration/datasourcex/util/AntPatternNamespace.kt b/util/src/main/kotlin/com/caplin/integration/datasourcex/util/AntPatternNamespace.kt index 569dfa9..8cdc904 100644 --- a/util/src/main/kotlin/com/caplin/integration/datasourcex/util/AntPatternNamespace.kt +++ b/util/src/main/kotlin/com/caplin/integration/datasourcex/util/AntPatternNamespace.kt @@ -2,6 +2,9 @@ package com.caplin.integration.datasourcex.util import com.caplin.datasource.Service import com.caplin.datasource.namespace.Namespace +import java.net.URLDecoder +import java.nio.charset.Charset +import java.nio.charset.StandardCharsets /** * An implementation of [Namespace] that matches subjects based on Ant style path patterns. @@ -20,6 +23,23 @@ class AntPatternNamespace(pattern: String) : Namespace { private const val MAX_WILDCARDS = 10 + /** The [Charset] used to URL-decode path variables and query parameters. */ + @JvmField val CHARSET: Charset = StandardCharsets.UTF_8 + + /** + * Parses the query portion of a subject (the part after the first `?`, without the `?` itself) + * into a map of decoded parameter names to values. + * + * Names and values are URL-decoded. A parameter with no `=` (e.g. `flag`) or an empty value + * (e.g. `empty=`) maps to an empty string. When a key repeats, the last value wins. + */ + private fun parseQueryString(query: String): Map = + query.split("&").filter(String::isNotEmpty).associate { parameter -> + urlDecode(parameter.substringBefore('=')) to urlDecode(parameter.substringAfter('=', "")) + } + + private fun urlDecode(value: String): String = URLDecoder.decode(value, CHARSET) + @JvmStatic fun Service.addIncludeNamespace(antPatternNamespace: AntPatternNamespace) { addIncludePattern(antPatternNamespace.posixExtendedPattern) @@ -71,27 +91,45 @@ class AntPatternNamespace(pattern: String) : Namespace { private val matcher = AntRegexPathMatcher(pattern) - override fun match(subject: String): Boolean = matcher.regex.matchEntire(subject) != null + override fun match(subject: String): Boolean = + matcher.regex.matchEntire(subject.pathPortion) != null /** - * Extracts path variables from a matching subject. + * Extracts path variables from a matching subject. Values are URL-decoded. Any trailing `?query` + * is ignored, so a subject that carries query parameters yields the same path variables as the + * query-less subject. * - * @param subject The subject to extract variables from. Must match the [pattern]. + * @param subject The subject to extract variables from. Its path portion must match the + * [pattern]. * @return A map of path variable names to their extracted values. * @throws IllegalStateException If the subject does not match the pattern. */ fun extractPathVariables(subject: String): Map { val groups = - checkNotNull(matcher.regex.matchEntire(subject)) { + checkNotNull(matcher.regex.matchEntire(subject.pathPortion)) { "Subject $subject does not match pattern $pattern" } .groups return matcher.pathVariables - .mapNotNull { name -> groups[name]?.value?.let { value -> name to value } } + .mapNotNull { name -> groups[name]?.value?.let { value -> name to urlDecode(value) } } .toMap() } + /** + * Extracts the query parameters from the optional trailing `?a=b&c=d` portion of a subject. + * + * @param subject The subject to extract query parameters from. + * @return A map of query parameter names to values, or an empty map when the subject has no + * query. + */ + fun extractQueryParameters(subject: String): Map = + parseQueryString(subject.substringAfter('?', "")) + + /** The subject with any trailing `?query` removed. */ + private val String.pathPortion: String + get() = substringBefore('?') + /** * Indicates whether this pattern only matches one exact path (i.e. no use of `?`, `*`, `**` or * path variables). diff --git a/util/src/test/kotlin/com/caplin/integration/datasourcex/util/AntPatternNamespaceTest.kt b/util/src/test/kotlin/com/caplin/integration/datasourcex/util/AntPatternNamespaceTest.kt index bd96830..d7b3fc6 100644 --- a/util/src/test/kotlin/com/caplin/integration/datasourcex/util/AntPatternNamespaceTest.kt +++ b/util/src/test/kotlin/com/caplin/integration/datasourcex/util/AntPatternNamespaceTest.kt @@ -2,9 +2,73 @@ package com.caplin.integration.datasourcex.util import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.equals.shouldBeEqual +import io.kotest.matchers.shouldBe class AntPatternNamespaceTest : FunSpec({ + test("subject with trailing query matches iff its path portion matches") { + val namespace = AntPatternNamespace("/CALENDAR/TENORDATES/{productPair}") + + namespace.match("/CALENDAR/TENORDATES/EURUSD?locationType=ONSHORE") shouldBe true + namespace.match("/CALENDAR/TENORDATES/EURUSD") shouldBe true + namespace.match("/CALENDAR/OTHER/EURUSD?locationType=ONSHORE") shouldBe false + } + + test("path variables are not polluted by a trailing query") { + val namespace = AntPatternNamespace("/CALENDAR/TENORDATES/{productPair}") + + namespace.extractPathVariables("/CALENDAR/TENORDATES/EURUSD?locationType=ONSHORE") shouldBe + mapOf("productPair" to "EURUSD") + namespace.extractPathVariables("/CALENDAR/TENORDATES/EURUSD") shouldBe + mapOf("productPair" to "EURUSD") + } + + test("extractPathVariables URL-decodes values") { + AntPatternNamespace("/CALENDAR/TENORDATES/{productPair}") + .extractPathVariables("/CALENDAR/TENORDATES/EUR%2FUSD?locationType=ONSHORE") shouldBe + mapOf("productPair" to "EUR/USD") + } + + test("extractQueryParameters returns an empty map when there is no query") { + AntPatternNamespace("/CALENDAR/TENORDATES/{productPair}") + .extractQueryParameters("/CALENDAR/TENORDATES/EURUSD") shouldBe emptyMap() + } + + test("extractQueryParameters parses a single parameter") { + AntPatternNamespace("/CALENDAR/TENORDATES/{productPair}") + .extractQueryParameters("/CALENDAR/TENORDATES/EURUSD?locationType=ONSHORE") shouldBe + mapOf("locationType" to "ONSHORE") + } + + test("extractQueryParameters parses multiple parameters") { + AntPatternNamespace("/CALENDAR/TENORDATES/{productPair}") + .extractQueryParameters( + "/CALENDAR/TENORDATES/EURUSD?locationType=ONSHORE&tenor=SPOT" + ) shouldBe mapOf("locationType" to "ONSHORE", "tenor" to "SPOT") + } + + test("extractQueryParameters parses a query on an exact pattern with no path variables") { + AntPatternNamespace("/CALENDAR/HOLIDAYS") + .extractQueryParameters("/CALENDAR/HOLIDAYS?year=2026") shouldBe mapOf("year" to "2026") + } + + test("extractQueryParameters URL-decodes keys and values") { + AntPatternNamespace("/CALENDAR/{id}") + .extractQueryParameters("/CALENDAR/x?a%20b=c%2Bd&e=%3D") shouldBe + mapOf("a b" to "c+d", "e" to "=") + } + + test("extractQueryParameters yields empty values for keys without a value") { + AntPatternNamespace("/CALENDAR/{id}") + .extractQueryParameters("/CALENDAR/x?flag&empty=") shouldBe + mapOf("flag" to "", "empty" to "") + } + + test("extractQueryParameters keeps the last value for a repeated key") { + AntPatternNamespace("/CALENDAR/{id}").extractQueryParameters("/CALENDAR/x?a=1&a=2") shouldBe + mapOf("a" to "2") + } + test("object maps are created as expected") { AntPatternNamespace("/PRIVATE/{mapping1}/FX/{baseCurrency}/{termCurrency}/*/{mapping2}/**") .getObjectMap(mapOf("mapping1" to "%u", "mapping2" to "%g"))