From 6772c5eeb5557a1e494852713cc55ec722b75145 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Sep 2025 02:37:42 +0000 Subject: [PATCH 1/9] fix(client): incorrect `getPackageVersion` impl --- .../src/main/kotlin/com/cas_parser/api/core/Properties.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/Properties.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/Properties.kt index c715f1a..dc9a375 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/Properties.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/Properties.kt @@ -2,7 +2,7 @@ package com.cas_parser.api.core -import java.util.Properties +import com.cas_parser.api.client.CasParserClient fun getOsArch(): String { val osArch = System.getProperty("os.arch") @@ -16,7 +16,7 @@ fun getOsArch(): String { "x86_64" -> "x64" "arm" -> "arm" "aarch64" -> "arm64" - else -> "other:${osArch}" + else -> "other:$osArch" } } @@ -30,13 +30,13 @@ fun getOsName(): String { osName.startsWith("Linux") -> "Linux" osName.startsWith("Mac OS") -> "MacOS" osName.startsWith("Windows") -> "Windows" - else -> "Other:${osName}" + else -> "Other:$osName" } } fun getOsVersion(): String = System.getProperty("os.version", "unknown") fun getPackageVersion(): String = - Properties::class.java.`package`.implementationVersion ?: "unknown" + CasParserClient::class.java.`package`.implementationVersion ?: "unknown" fun getJavaVersion(): String = System.getProperty("java.version", "unknown") From 482319f0e19023df4e3ba5414e38914f6ad037fa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 02:32:51 +0000 Subject: [PATCH 2/9] feat(client): expose sleeper option fix(client): ensure single timer is created per client --- .../client/okhttp/CasParserOkHttpClient.kt | 12 ++++++ .../okhttp/CasParserOkHttpClientAsync.kt | 12 ++++++ .../com/cas_parser/api/core/ClientOptions.kt | 27 ++++++++++++ .../com/cas_parser/api/core/DefaultSleeper.kt | 28 +++++++++++++ .../api/core/PhantomReachableSleeper.kt | 23 +++++++++++ .../kotlin/com/cas_parser/api/core/Sleeper.kt | 21 ++++++++++ .../api/core/http/RetryingHttpClient.kt | 41 ++++--------------- .../api/core/http/RetryingHttpClientTest.kt | 9 +++- 8 files changed, 139 insertions(+), 34 deletions(-) create mode 100644 cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/DefaultSleeper.kt create mode 100644 cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/PhantomReachableSleeper.kt create mode 100644 cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/Sleeper.kt diff --git a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClient.kt b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClient.kt index 687527a..f75536a 100644 --- a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClient.kt +++ b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClient.kt @@ -5,6 +5,7 @@ package com.cas_parser.api.client.okhttp import com.cas_parser.api.client.CasParserClient import com.cas_parser.api.client.CasParserClientImpl import com.cas_parser.api.core.ClientOptions +import com.cas_parser.api.core.Sleeper import com.cas_parser.api.core.Timeout import com.cas_parser.api.core.http.Headers import com.cas_parser.api.core.http.HttpClient @@ -120,6 +121,17 @@ class CasParserOkHttpClient private constructor() { */ fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) } + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) } + /** * The clock to use for operations that require timing, like retries. * diff --git a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClientAsync.kt b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClientAsync.kt index 186bbe4..4142acc 100644 --- a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClientAsync.kt +++ b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClientAsync.kt @@ -5,6 +5,7 @@ package com.cas_parser.api.client.okhttp import com.cas_parser.api.client.CasParserClientAsync import com.cas_parser.api.client.CasParserClientAsyncImpl import com.cas_parser.api.core.ClientOptions +import com.cas_parser.api.core.Sleeper import com.cas_parser.api.core.Timeout import com.cas_parser.api.core.http.Headers import com.cas_parser.api.core.http.HttpClient @@ -120,6 +121,17 @@ class CasParserOkHttpClientAsync private constructor() { */ fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) } + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) } + /** * The clock to use for operations that require timing, like retries. * diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt index d330bc7..f5195cd 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt @@ -40,6 +40,16 @@ private constructor( * rarely needs to be overridden. */ @get:JvmName("jsonMapper") val jsonMapper: JsonMapper, + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + @get:JvmName("sleeper") val sleeper: Sleeper, /** * The clock to use for operations that require timing, like retries. * @@ -131,6 +141,7 @@ private constructor( private var httpClient: HttpClient? = null private var checkJacksonVersionCompatibility: Boolean = true private var jsonMapper: JsonMapper = jsonMapper() + private var sleeper: Sleeper? = null private var clock: Clock = Clock.systemUTC() private var baseUrl: String? = null private var headers: Headers.Builder = Headers.builder() @@ -145,6 +156,7 @@ private constructor( httpClient = clientOptions.originalHttpClient checkJacksonVersionCompatibility = clientOptions.checkJacksonVersionCompatibility jsonMapper = clientOptions.jsonMapper + sleeper = clientOptions.sleeper clock = clientOptions.clock baseUrl = clientOptions.baseUrl headers = clientOptions.headers.toBuilder() @@ -185,6 +197,17 @@ private constructor( */ fun jsonMapper(jsonMapper: JsonMapper) = apply { this.jsonMapper = jsonMapper } + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + fun sleeper(sleeper: Sleeper) = apply { this.sleeper = PhantomReachableSleeper(sleeper) } + /** * The clock to use for operations that require timing, like retries. * @@ -369,6 +392,7 @@ private constructor( */ fun build(): ClientOptions { val httpClient = checkRequired("httpClient", httpClient) + val sleeper = sleeper ?: PhantomReachableSleeper(DefaultSleeper()) val apiKey = checkRequired("apiKey", apiKey) val headers = Headers.builder() @@ -392,11 +416,13 @@ private constructor( httpClient, RetryingHttpClient.builder() .httpClient(httpClient) + .sleeper(sleeper) .clock(clock) .maxRetries(maxRetries) .build(), checkJacksonVersionCompatibility, jsonMapper, + sleeper, clock, baseUrl, headers.build(), @@ -421,5 +447,6 @@ private constructor( */ fun close() { httpClient.close() + sleeper.close() } } diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/DefaultSleeper.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/DefaultSleeper.kt new file mode 100644 index 0000000..5e092e2 --- /dev/null +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/DefaultSleeper.kt @@ -0,0 +1,28 @@ +package com.cas_parser.api.core + +import java.time.Duration +import java.util.Timer +import java.util.TimerTask +import java.util.concurrent.CompletableFuture + +class DefaultSleeper : Sleeper { + + private val timer = Timer("DefaultSleeper", true) + + override fun sleep(duration: Duration) = Thread.sleep(duration.toMillis()) + + override fun sleepAsync(duration: Duration): CompletableFuture { + val future = CompletableFuture() + timer.schedule( + object : TimerTask() { + override fun run() { + future.complete(null) + } + }, + duration.toMillis(), + ) + return future + } + + override fun close() = timer.cancel() +} diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/PhantomReachableSleeper.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/PhantomReachableSleeper.kt new file mode 100644 index 0000000..2b3afd5 --- /dev/null +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/PhantomReachableSleeper.kt @@ -0,0 +1,23 @@ +package com.cas_parser.api.core + +import java.time.Duration +import java.util.concurrent.CompletableFuture + +/** + * A delegating wrapper around a [Sleeper] that closes it once it's only phantom reachable. + * + * This class ensures the [Sleeper] is closed even if the user forgets to do it. + */ +internal class PhantomReachableSleeper(private val sleeper: Sleeper) : Sleeper { + + init { + closeWhenPhantomReachable(this, sleeper) + } + + override fun sleep(duration: Duration) = sleeper.sleep(duration) + + override fun sleepAsync(duration: Duration): CompletableFuture = + sleeper.sleepAsync(duration) + + override fun close() = sleeper.close() +} diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/Sleeper.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/Sleeper.kt new file mode 100644 index 0000000..5a93d9a --- /dev/null +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/Sleeper.kt @@ -0,0 +1,21 @@ +package com.cas_parser.api.core + +import java.time.Duration +import java.util.concurrent.CompletableFuture + +/** + * An interface for delaying execution for a specified amount of time. + * + * Useful for testing and cleaning up resources. + */ +interface Sleeper : AutoCloseable { + + /** Synchronously pauses execution for the given [duration]. */ + fun sleep(duration: Duration) + + /** Asynchronously pauses execution for the given [duration]. */ + fun sleepAsync(duration: Duration): CompletableFuture + + /** Overridden from [AutoCloseable] to not have a checked exception in its signature. */ + override fun close() +} diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/RetryingHttpClient.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/RetryingHttpClient.kt index 569b1aa..2bf9815 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/RetryingHttpClient.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/RetryingHttpClient.kt @@ -1,6 +1,8 @@ package com.cas_parser.api.core.http +import com.cas_parser.api.core.DefaultSleeper import com.cas_parser.api.core.RequestOptions +import com.cas_parser.api.core.Sleeper import com.cas_parser.api.core.checkRequired import com.cas_parser.api.errors.CasParserIoException import com.cas_parser.api.errors.CasParserRetryableException @@ -11,8 +13,6 @@ import java.time.OffsetDateTime import java.time.format.DateTimeFormatter import java.time.format.DateTimeParseException import java.time.temporal.ChronoUnit -import java.util.Timer -import java.util.TimerTask import java.util.UUID import java.util.concurrent.CompletableFuture import java.util.concurrent.ThreadLocalRandom @@ -130,7 +130,10 @@ private constructor( return executeWithRetries(modifiedRequest, requestOptions) } - override fun close() = httpClient.close() + override fun close() { + httpClient.close() + sleeper.close() + } private fun isRetryable(request: HttpRequest): Boolean = // Some requests, such as when a request body is being streamed, cannot be retried because @@ -235,33 +238,14 @@ private constructor( class Builder internal constructor() { private var httpClient: HttpClient? = null - private var sleeper: Sleeper = - object : Sleeper { - - private val timer = Timer("RetryingHttpClient", true) - - override fun sleep(duration: Duration) = Thread.sleep(duration.toMillis()) - - override fun sleepAsync(duration: Duration): CompletableFuture { - val future = CompletableFuture() - timer.schedule( - object : TimerTask() { - override fun run() { - future.complete(null) - } - }, - duration.toMillis(), - ) - return future - } - } + private var sleeper: Sleeper? = null private var clock: Clock = Clock.systemUTC() private var maxRetries: Int = 2 private var idempotencyHeader: String? = null fun httpClient(httpClient: HttpClient) = apply { this.httpClient = httpClient } - @JvmSynthetic internal fun sleeper(sleeper: Sleeper) = apply { this.sleeper = sleeper } + fun sleeper(sleeper: Sleeper) = apply { this.sleeper = sleeper } fun clock(clock: Clock) = apply { this.clock = clock } @@ -272,17 +256,10 @@ private constructor( fun build(): HttpClient = RetryingHttpClient( checkRequired("httpClient", httpClient), - sleeper, + sleeper ?: DefaultSleeper(), clock, maxRetries, idempotencyHeader, ) } - - internal interface Sleeper { - - fun sleep(duration: Duration) - - fun sleepAsync(duration: Duration): CompletableFuture - } } diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/http/RetryingHttpClientTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/http/RetryingHttpClientTest.kt index d740df3..90db8ea 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/http/RetryingHttpClientTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/http/RetryingHttpClientTest.kt @@ -2,6 +2,7 @@ package com.cas_parser.api.core.http import com.cas_parser.api.client.okhttp.OkHttpClient import com.cas_parser.api.core.RequestOptions +import com.cas_parser.api.core.Sleeper import com.cas_parser.api.errors.CasParserRetryableException import com.github.tomakehurst.wiremock.client.WireMock.* import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo @@ -294,12 +295,14 @@ internal class RetryingHttpClientTest { .httpClient(failingHttpClient) .maxRetries(2) .sleeper( - object : RetryingHttpClient.Sleeper { + object : Sleeper { override fun sleep(duration: Duration) {} override fun sleepAsync(duration: Duration): CompletableFuture = CompletableFuture.completedFuture(null) + + override fun close() {} } ) .build() @@ -333,12 +336,14 @@ internal class RetryingHttpClientTest { .httpClient(httpClient) // Use a no-op `Sleeper` to make the test fast. .sleeper( - object : RetryingHttpClient.Sleeper { + object : Sleeper { override fun sleep(duration: Duration) {} override fun sleepAsync(duration: Duration): CompletableFuture = CompletableFuture.completedFuture(null) + + override fun close() {} } ) From 692db64a36ef927e9c0ea23bd57192af99aaaf02 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 03:22:45 +0000 Subject: [PATCH 3/9] chore: improve formatter performance --- scripts/fast-format | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/fast-format b/scripts/fast-format index e16bfc5..1b3bc47 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -2,7 +2,12 @@ set -euo pipefail +echo "Script started with $# arguments" +echo "Arguments: $*" +echo "Script location: $(dirname "$0")" + cd "$(dirname "$0")/.." +echo "Changed to directory: $(pwd)" if [ $# -eq 0 ]; then echo "Usage: $0 [additional-formatter-args...]" @@ -12,6 +17,8 @@ fi FILE_LIST="$1" +echo "Looking for file: $FILE_LIST" + if [ ! -f "$FILE_LIST" ]; then echo "Error: File '$FILE_LIST' not found" exit 1 @@ -23,9 +30,9 @@ if ! command -v ktfmt-fast-format &> /dev/null; then fi # Process Kotlin files -kt_files=$(grep -E '\.kt$' "$FILE_LIST" | grep -v './buildSrc/build/') -kt_files=$(grep -E '\.kt$' "$FILE_LIST" | grep -v './buildSrc/build/') -echo "==> Found $(echo "$kt_files" | wc -l) Kotlin files:" +echo "==> Looking for Kotlin files" +kt_files=$(grep -E '\.kt$' "$FILE_LIST" | grep -v './buildSrc/build/' || true) +echo "==> Done looking for Kotlin files" if [[ -n "$kt_files" ]]; then echo "==> will format Kotlin files" From 557721f0775228db057005e912d8f820f512fcca Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 00:19:42 +0000 Subject: [PATCH 4/9] feat(api): api update --- .stats.yml | 4 +- .../api/models/casparser/UnifiedResponse.kt | 2058 ++++++++++++++++- .../models/casparser/UnifiedResponseTest.kt | 139 ++ .../api/proguard/ProGuardCompatibilityTest.kt | 47 + 4 files changed, 2185 insertions(+), 63 deletions(-) diff --git a/.stats.yml b/.stats.yml index 92721c7..06e7614 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 5 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-b7fdba3d3f97c7debc22c7ca30b828bce81bcd64648df8c94029b27a3321ebb9.yml -openapi_spec_hash: 03f1315f1d32ada42445ca920f047dff +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-9eaed98ce5934f11e901cef376a28257d2c196bd3dba7c690babc6741a730ded.yml +openapi_spec_hash: b76e4e830c4d03ba4cf9429bb9fb9c8a config_hash: cb5d75abef6264b5d86448caf7295afa diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt index 2c18576..67cc09d 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt @@ -28,6 +28,7 @@ private constructor( private val investor: JsonField, private val meta: JsonField, private val mutualFunds: JsonField>, + private val nps: JsonField>, private val summary: JsonField, private val additionalProperties: MutableMap, ) { @@ -45,8 +46,9 @@ private constructor( @JsonProperty("mutual_funds") @ExcludeMissing mutualFunds: JsonField> = JsonMissing.of(), + @JsonProperty("nps") @ExcludeMissing nps: JsonField> = JsonMissing.of(), @JsonProperty("summary") @ExcludeMissing summary: JsonField = JsonMissing.of(), - ) : this(dematAccounts, insurance, investor, meta, mutualFunds, summary, mutableMapOf()) + ) : this(dematAccounts, insurance, investor, meta, mutualFunds, nps, summary, mutableMapOf()) /** * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the @@ -78,6 +80,14 @@ private constructor( */ fun mutualFunds(): Optional> = mutualFunds.getOptional("mutual_funds") + /** + * List of NPS accounts + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun nps(): Optional> = nps.getOptional("nps") + /** * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -123,6 +133,13 @@ private constructor( @ExcludeMissing fun _mutualFunds(): JsonField> = mutualFunds + /** + * Returns the raw JSON value of [nps]. + * + * Unlike [nps], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("nps") @ExcludeMissing fun _nps(): JsonField> = nps + /** * Returns the raw JSON value of [summary]. * @@ -156,6 +173,7 @@ private constructor( private var investor: JsonField = JsonMissing.of() private var meta: JsonField = JsonMissing.of() private var mutualFunds: JsonField>? = null + private var nps: JsonField>? = null private var summary: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -166,6 +184,7 @@ private constructor( investor = unifiedResponse.investor meta = unifiedResponse.meta mutualFunds = unifiedResponse.mutualFunds.map { it.toMutableList() } + nps = unifiedResponse.nps.map { it.toMutableList() } summary = unifiedResponse.summary additionalProperties = unifiedResponse.additionalProperties.toMutableMap() } @@ -253,6 +272,26 @@ private constructor( } } + /** List of NPS accounts */ + fun nps(nps: List) = nps(JsonField.of(nps)) + + /** + * Sets [Builder.nps] to an arbitrary JSON value. + * + * You should usually call [Builder.nps] with a well-typed `List` value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun nps(nps: JsonField>) = apply { this.nps = nps.map { it.toMutableList() } } + + /** + * Adds a single [Np] to [nps]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addNp(np: Np) = apply { + nps = (nps ?: JsonField.of(mutableListOf())).also { checkKnown("nps", it).add(np) } + } + fun summary(summary: Summary) = summary(JsonField.of(summary)) /** @@ -294,6 +333,7 @@ private constructor( investor, meta, (mutualFunds ?: JsonMissing.of()).map { it.toImmutable() }, + (nps ?: JsonMissing.of()).map { it.toImmutable() }, summary, additionalProperties.toMutableMap(), ) @@ -311,6 +351,7 @@ private constructor( investor().ifPresent { it.validate() } meta().ifPresent { it.validate() } mutualFunds().ifPresent { it.forEach { it.validate() } } + nps().ifPresent { it.forEach { it.validate() } } summary().ifPresent { it.validate() } validated = true } @@ -335,6 +376,7 @@ private constructor( (investor.asKnown().getOrNull()?.validity() ?: 0) + (meta.asKnown().getOrNull()?.validity() ?: 0) + (mutualFunds.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (nps.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (summary.asKnown().getOrNull()?.validity() ?: 0) class DematAccount @@ -346,6 +388,7 @@ private constructor( private val dpId: JsonField, private val dpName: JsonField, private val holdings: JsonField, + private val linkedHolders: JsonField>, private val value: JsonField, private val additionalProperties: MutableMap, ) { @@ -367,6 +410,9 @@ private constructor( @JsonProperty("holdings") @ExcludeMissing holdings: JsonField = JsonMissing.of(), + @JsonProperty("linked_holders") + @ExcludeMissing + linkedHolders: JsonField> = JsonMissing.of(), @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), ) : this( additionalInfo, @@ -376,6 +422,7 @@ private constructor( dpId, dpName, holdings, + linkedHolders, value, mutableMapOf(), ) @@ -435,6 +482,15 @@ private constructor( */ fun holdings(): Optional = holdings.getOptional("holdings") + /** + * List of account holders linked to this demat account + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun linkedHolders(): Optional> = + linkedHolders.getOptional("linked_holders") + /** * Total value of the demat account * @@ -497,6 +553,16 @@ private constructor( */ @JsonProperty("holdings") @ExcludeMissing fun _holdings(): JsonField = holdings + /** + * Returns the raw JSON value of [linkedHolders]. + * + * Unlike [linkedHolders], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("linked_holders") + @ExcludeMissing + fun _linkedHolders(): JsonField> = linkedHolders + /** * Returns the raw JSON value of [value]. * @@ -532,6 +598,7 @@ private constructor( private var dpId: JsonField = JsonMissing.of() private var dpName: JsonField = JsonMissing.of() private var holdings: JsonField = JsonMissing.of() + private var linkedHolders: JsonField>? = null private var value: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -544,6 +611,7 @@ private constructor( dpId = dematAccount.dpId dpName = dematAccount.dpName holdings = dematAccount.holdings + linkedHolders = dematAccount.linkedHolders.map { it.toMutableList() } value = dematAccount.value additionalProperties = dematAccount.additionalProperties.toMutableMap() } @@ -634,6 +702,33 @@ private constructor( */ fun holdings(holdings: JsonField) = apply { this.holdings = holdings } + /** List of account holders linked to this demat account */ + fun linkedHolders(linkedHolders: List) = + linkedHolders(JsonField.of(linkedHolders)) + + /** + * Sets [Builder.linkedHolders] to an arbitrary JSON value. + * + * You should usually call [Builder.linkedHolders] with a well-typed + * `List` value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun linkedHolders(linkedHolders: JsonField>) = apply { + this.linkedHolders = linkedHolders.map { it.toMutableList() } + } + + /** + * Adds a single [LinkedHolder] to [linkedHolders]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addLinkedHolder(linkedHolder: LinkedHolder) = apply { + linkedHolders = + (linkedHolders ?: JsonField.of(mutableListOf())).also { + checkKnown("linkedHolders", it).add(linkedHolder) + } + } + /** Total value of the demat account */ fun value(value: Float) = value(JsonField.of(value)) @@ -679,6 +774,7 @@ private constructor( dpId, dpName, holdings, + (linkedHolders ?: JsonMissing.of()).map { it.toImmutable() }, value, additionalProperties.toMutableMap(), ) @@ -698,6 +794,7 @@ private constructor( dpId() dpName() holdings().ifPresent { it.validate() } + linkedHolders().ifPresent { it.forEach { it.validate() } } value() validated = true } @@ -725,6 +822,7 @@ private constructor( (if (dpId.asKnown().isPresent) 1 else 0) + (if (dpName.asKnown().isPresent) 1 else 0) + (holdings.asKnown().getOrNull()?.validity() ?: 0) + + (linkedHolders.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (value.asKnown().isPresent) 1 else 0) /** Additional information specific to the demat account type */ @@ -3136,6 +3234,185 @@ private constructor( "Holdings{aifs=$aifs, corporateBonds=$corporateBonds, dematMutualFunds=$dematMutualFunds, equities=$equities, governmentSecurities=$governmentSecurities, additionalProperties=$additionalProperties}" } + class LinkedHolder + private constructor( + private val name: JsonField, + private val pan: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), + ) : this(name, pan, mutableMapOf()) + + /** + * Name of the account holder + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * PAN of the account holder + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun pan(): Optional = pan.getOptional("pan") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [pan]. + * + * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [LinkedHolder]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LinkedHolder]. */ + class Builder internal constructor() { + + private var name: JsonField = JsonMissing.of() + private var pan: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(linkedHolder: LinkedHolder) = apply { + name = linkedHolder.name + pan = linkedHolder.pan + additionalProperties = linkedHolder.additionalProperties.toMutableMap() + } + + /** Name of the account holder */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** PAN of the account holder */ + fun pan(pan: String) = pan(JsonField.of(pan)) + + /** + * Sets [Builder.pan] to an arbitrary JSON value. + * + * You should usually call [Builder.pan] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun pan(pan: JsonField) = apply { this.pan = pan } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [LinkedHolder]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): LinkedHolder = + LinkedHolder(name, pan, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): LinkedHolder = apply { + if (validated) { + return@apply + } + + name() + pan() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (name.asKnown().isPresent) 1 else 0) + (if (pan.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is LinkedHolder && + name == other.name && + pan == other.pan && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(name, pan, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "LinkedHolder{name=$name, pan=$pan, additionalProperties=$additionalProperties}" + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -3149,6 +3426,7 @@ private constructor( dpId == other.dpId && dpName == other.dpName && holdings == other.holdings && + linkedHolders == other.linkedHolders && value == other.value && additionalProperties == other.additionalProperties } @@ -3162,6 +3440,7 @@ private constructor( dpId, dpName, holdings, + linkedHolders, value, additionalProperties, ) @@ -3170,7 +3449,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "DematAccount{additionalInfo=$additionalInfo, boId=$boId, clientId=$clientId, dematType=$dematType, dpId=$dpId, dpName=$dpName, holdings=$holdings, value=$value, additionalProperties=$additionalProperties}" + "DematAccount{additionalInfo=$additionalInfo, boId=$boId, clientId=$clientId, dematType=$dematType, dpId=$dpId, dpName=$dpName, holdings=$holdings, linkedHolders=$linkedHolders, value=$value, additionalProperties=$additionalProperties}" } class Insurance @@ -4733,6 +5012,7 @@ private constructor( private val additionalInfo: JsonField, private val amc: JsonField, private val folioNumber: JsonField, + private val linkedHolders: JsonField>, private val registrar: JsonField, private val schemes: JsonField>, private val value: JsonField, @@ -4748,6 +5028,9 @@ private constructor( @JsonProperty("folio_number") @ExcludeMissing folioNumber: JsonField = JsonMissing.of(), + @JsonProperty("linked_holders") + @ExcludeMissing + linkedHolders: JsonField> = JsonMissing.of(), @JsonProperty("registrar") @ExcludeMissing registrar: JsonField = JsonMissing.of(), @@ -4755,7 +5038,16 @@ private constructor( @ExcludeMissing schemes: JsonField> = JsonMissing.of(), @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), - ) : this(additionalInfo, amc, folioNumber, registrar, schemes, value, mutableMapOf()) + ) : this( + additionalInfo, + amc, + folioNumber, + linkedHolders, + registrar, + schemes, + value, + mutableMapOf(), + ) /** * Additional folio information @@ -4782,6 +5074,15 @@ private constructor( */ fun folioNumber(): Optional = folioNumber.getOptional("folio_number") + /** + * List of account holders linked to this mutual fund folio + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun linkedHolders(): Optional> = + linkedHolders.getOptional("linked_holders") + /** * Registrar and Transfer Agent name * @@ -4830,6 +5131,16 @@ private constructor( @ExcludeMissing fun _folioNumber(): JsonField = folioNumber + /** + * Returns the raw JSON value of [linkedHolders]. + * + * Unlike [linkedHolders], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("linked_holders") + @ExcludeMissing + fun _linkedHolders(): JsonField> = linkedHolders + /** * Returns the raw JSON value of [registrar]. * @@ -4875,6 +5186,7 @@ private constructor( private var additionalInfo: JsonField = JsonMissing.of() private var amc: JsonField = JsonMissing.of() private var folioNumber: JsonField = JsonMissing.of() + private var linkedHolders: JsonField>? = null private var registrar: JsonField = JsonMissing.of() private var schemes: JsonField>? = null private var value: JsonField = JsonMissing.of() @@ -4885,6 +5197,7 @@ private constructor( additionalInfo = mutualFund.additionalInfo amc = mutualFund.amc folioNumber = mutualFund.folioNumber + linkedHolders = mutualFund.linkedHolders.map { it.toMutableList() } registrar = mutualFund.registrar schemes = mutualFund.schemes.map { it.toMutableList() } value = mutualFund.value @@ -4932,6 +5245,33 @@ private constructor( this.folioNumber = folioNumber } + /** List of account holders linked to this mutual fund folio */ + fun linkedHolders(linkedHolders: List) = + linkedHolders(JsonField.of(linkedHolders)) + + /** + * Sets [Builder.linkedHolders] to an arbitrary JSON value. + * + * You should usually call [Builder.linkedHolders] with a well-typed + * `List` value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun linkedHolders(linkedHolders: JsonField>) = apply { + this.linkedHolders = linkedHolders.map { it.toMutableList() } + } + + /** + * Adds a single [LinkedHolder] to [linkedHolders]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addLinkedHolder(linkedHolder: LinkedHolder) = apply { + linkedHolders = + (linkedHolders ?: JsonField.of(mutableListOf())).also { + checkKnown("linkedHolders", it).add(linkedHolder) + } + } + /** Registrar and Transfer Agent name */ fun registrar(registrar: String) = registrar(JsonField.of(registrar)) @@ -5010,6 +5350,7 @@ private constructor( additionalInfo, amc, folioNumber, + (linkedHolders ?: JsonMissing.of()).map { it.toImmutable() }, registrar, (schemes ?: JsonMissing.of()).map { it.toImmutable() }, value, @@ -5027,6 +5368,7 @@ private constructor( additionalInfo().ifPresent { it.validate() } amc() folioNumber() + linkedHolders().ifPresent { it.forEach { it.validate() } } registrar() schemes().ifPresent { it.forEach { it.validate() } } value() @@ -5052,6 +5394,7 @@ private constructor( (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + (if (amc.asKnown().isPresent) 1 else 0) + (if (folioNumber.asKnown().isPresent) 1 else 0) + + (linkedHolders.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (registrar.asKnown().isPresent) 1 else 0) + (schemes.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (value.asKnown().isPresent) 1 else 0) @@ -5273,30 +5616,209 @@ private constructor( "AdditionalInfo{kyc=$kyc, pan=$pan, pankyc=$pankyc, additionalProperties=$additionalProperties}" } - class Scheme + class LinkedHolder private constructor( - private val additionalInfo: JsonField, - private val cost: JsonField, - private val gain: JsonField, - private val isin: JsonField, private val name: JsonField, - private val nav: JsonField, - private val nominees: JsonField>, - private val transactions: JsonField>, - private val type: JsonField, - private val units: JsonField, - private val value: JsonField, + private val pan: JsonField, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( - @JsonProperty("additional_info") - @ExcludeMissing - additionalInfo: JsonField = JsonMissing.of(), - @JsonProperty("cost") @ExcludeMissing cost: JsonField = JsonMissing.of(), - @JsonProperty("gain") @ExcludeMissing gain: JsonField = JsonMissing.of(), - @JsonProperty("isin") @ExcludeMissing isin: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), + ) : this(name, pan, mutableMapOf()) + + /** + * Name of the account holder + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * PAN of the account holder + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun pan(): Optional = pan.getOptional("pan") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [pan]. + * + * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [LinkedHolder]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LinkedHolder]. */ + class Builder internal constructor() { + + private var name: JsonField = JsonMissing.of() + private var pan: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(linkedHolder: LinkedHolder) = apply { + name = linkedHolder.name + pan = linkedHolder.pan + additionalProperties = linkedHolder.additionalProperties.toMutableMap() + } + + /** Name of the account holder */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** PAN of the account holder */ + fun pan(pan: String) = pan(JsonField.of(pan)) + + /** + * Sets [Builder.pan] to an arbitrary JSON value. + * + * You should usually call [Builder.pan] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun pan(pan: JsonField) = apply { this.pan = pan } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [LinkedHolder]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): LinkedHolder = + LinkedHolder(name, pan, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): LinkedHolder = apply { + if (validated) { + return@apply + } + + name() + pan() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (name.asKnown().isPresent) 1 else 0) + (if (pan.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is LinkedHolder && + name == other.name && + pan == other.pan && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(name, pan, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "LinkedHolder{name=$name, pan=$pan, additionalProperties=$additionalProperties}" + } + + class Scheme + private constructor( + private val additionalInfo: JsonField, + private val cost: JsonField, + private val gain: JsonField, + private val isin: JsonField, + private val name: JsonField, + private val nav: JsonField, + private val nominees: JsonField>, + private val transactions: JsonField>, + private val type: JsonField, + private val units: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("cost") @ExcludeMissing cost: JsonField = JsonMissing.of(), + @JsonProperty("gain") @ExcludeMissing gain: JsonField = JsonMissing.of(), + @JsonProperty("isin") @ExcludeMissing isin: JsonField = JsonMissing.of(), @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), @JsonProperty("nav") @ExcludeMissing nav: JsonField = JsonMissing.of(), @JsonProperty("nominees") @@ -6968,6 +7490,7 @@ private constructor( additionalInfo == other.additionalInfo && amc == other.amc && folioNumber == other.folioNumber && + linkedHolders == other.linkedHolders && registrar == other.registrar && schemes == other.schemes && value == other.value && @@ -6979,6 +7502,7 @@ private constructor( additionalInfo, amc, folioNumber, + linkedHolders, registrar, schemes, value, @@ -6989,55 +7513,115 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "MutualFund{additionalInfo=$additionalInfo, amc=$amc, folioNumber=$folioNumber, registrar=$registrar, schemes=$schemes, value=$value, additionalProperties=$additionalProperties}" + "MutualFund{additionalInfo=$additionalInfo, amc=$amc, folioNumber=$folioNumber, linkedHolders=$linkedHolders, registrar=$registrar, schemes=$schemes, value=$value, additionalProperties=$additionalProperties}" } - class Summary + class Np private constructor( - private val accounts: JsonField, - private val totalValue: JsonField, + private val additionalInfo: JsonValue, + private val cra: JsonField, + private val funds: JsonField>, + private val linkedHolders: JsonField>, + private val pran: JsonField, + private val value: JsonField, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( - @JsonProperty("accounts") + @JsonProperty("additional_info") @ExcludeMissing - accounts: JsonField = JsonMissing.of(), - @JsonProperty("total_value") + additionalInfo: JsonValue = JsonMissing.of(), + @JsonProperty("cra") @ExcludeMissing cra: JsonField = JsonMissing.of(), + @JsonProperty("funds") @ExcludeMissing funds: JsonField> = JsonMissing.of(), + @JsonProperty("linked_holders") @ExcludeMissing - totalValue: JsonField = JsonMissing.of(), - ) : this(accounts, totalValue, mutableMapOf()) + linkedHolders: JsonField> = JsonMissing.of(), + @JsonProperty("pran") @ExcludeMissing pran: JsonField = JsonMissing.of(), + @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), + ) : this(additionalInfo, cra, funds, linkedHolders, pran, value, mutableMapOf()) + + /** Additional information specific to the NPS account */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonValue = additionalInfo /** + * Central Record Keeping Agency name + * * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ - fun accounts(): Optional = accounts.getOptional("accounts") + fun cra(): Optional = cra.getOptional("cra") /** - * Total portfolio value across all accounts + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun funds(): Optional> = funds.getOptional("funds") + + /** + * List of account holders linked to this NPS account * * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). */ - fun totalValue(): Optional = totalValue.getOptional("total_value") + fun linkedHolders(): Optional> = + linkedHolders.getOptional("linked_holders") /** - * Returns the raw JSON value of [accounts]. + * Permanent Retirement Account Number (PRAN) * - * Unlike [accounts], this method doesn't throw if the JSON field has an unexpected type. + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). */ - @JsonProperty("accounts") @ExcludeMissing fun _accounts(): JsonField = accounts + fun pran(): Optional = pran.getOptional("pran") /** - * Returns the raw JSON value of [totalValue]. + * Total value of the NPS account * - * Unlike [totalValue], this method doesn't throw if the JSON field has an unexpected type. + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). */ - @JsonProperty("total_value") + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [cra]. + * + * Unlike [cra], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("cra") @ExcludeMissing fun _cra(): JsonField = cra + + /** + * Returns the raw JSON value of [funds]. + * + * Unlike [funds], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("funds") @ExcludeMissing fun _funds(): JsonField> = funds + + /** + * Returns the raw JSON value of [linkedHolders]. + * + * Unlike [linkedHolders], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("linked_holders") @ExcludeMissing - fun _totalValue(): JsonField = totalValue + fun _linkedHolders(): JsonField> = linkedHolders + + /** + * Returns the raw JSON value of [pran]. + * + * Unlike [pran], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pran") @ExcludeMissing fun _pran(): JsonField = pran + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -7053,37 +7637,1159 @@ private constructor( companion object { - /** Returns a mutable builder for constructing an instance of [Summary]. */ + /** Returns a mutable builder for constructing an instance of [Np]. */ @JvmStatic fun builder() = Builder() } - /** A builder for [Summary]. */ + /** A builder for [Np]. */ class Builder internal constructor() { - private var accounts: JsonField = JsonMissing.of() - private var totalValue: JsonField = JsonMissing.of() + private var additionalInfo: JsonValue = JsonMissing.of() + private var cra: JsonField = JsonMissing.of() + private var funds: JsonField>? = null + private var linkedHolders: JsonField>? = null + private var pran: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(summary: Summary) = apply { - accounts = summary.accounts - totalValue = summary.totalValue - additionalProperties = summary.additionalProperties.toMutableMap() + internal fun from(np: Np) = apply { + additionalInfo = np.additionalInfo + cra = np.cra + funds = np.funds.map { it.toMutableList() } + linkedHolders = np.linkedHolders.map { it.toMutableList() } + pran = np.pran + value = np.value + additionalProperties = np.additionalProperties.toMutableMap() } - fun accounts(accounts: Accounts) = accounts(JsonField.of(accounts)) + /** Additional information specific to the NPS account */ + fun additionalInfo(additionalInfo: JsonValue) = apply { + this.additionalInfo = additionalInfo + } + + /** Central Record Keeping Agency name */ + fun cra(cra: String) = cra(JsonField.of(cra)) /** - * Sets [Builder.accounts] to an arbitrary JSON value. + * Sets [Builder.cra] to an arbitrary JSON value. * - * You should usually call [Builder.accounts] with a well-typed [Accounts] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. + * You should usually call [Builder.cra] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. */ - fun accounts(accounts: JsonField) = apply { this.accounts = accounts } + fun cra(cra: JsonField) = apply { this.cra = cra } - /** Total portfolio value across all accounts */ - fun totalValue(totalValue: Float) = totalValue(JsonField.of(totalValue)) + fun funds(funds: List) = funds(JsonField.of(funds)) + + /** + * Sets [Builder.funds] to an arbitrary JSON value. + * + * You should usually call [Builder.funds] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun funds(funds: JsonField>) = apply { + this.funds = funds.map { it.toMutableList() } + } + + /** + * Adds a single [Fund] to [funds]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addFund(fund: Fund) = apply { + funds = + (funds ?: JsonField.of(mutableListOf())).also { + checkKnown("funds", it).add(fund) + } + } + + /** List of account holders linked to this NPS account */ + fun linkedHolders(linkedHolders: List) = + linkedHolders(JsonField.of(linkedHolders)) + + /** + * Sets [Builder.linkedHolders] to an arbitrary JSON value. + * + * You should usually call [Builder.linkedHolders] with a well-typed + * `List` value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun linkedHolders(linkedHolders: JsonField>) = apply { + this.linkedHolders = linkedHolders.map { it.toMutableList() } + } + + /** + * Adds a single [LinkedHolder] to [linkedHolders]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addLinkedHolder(linkedHolder: LinkedHolder) = apply { + linkedHolders = + (linkedHolders ?: JsonField.of(mutableListOf())).also { + checkKnown("linkedHolders", it).add(linkedHolder) + } + } + + /** Permanent Retirement Account Number (PRAN) */ + fun pran(pran: String) = pran(JsonField.of(pran)) + + /** + * Sets [Builder.pran] to an arbitrary JSON value. + * + * You should usually call [Builder.pran] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun pran(pran: JsonField) = apply { this.pran = pran } + + /** Total value of the NPS account */ + fun value(value: Float) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Float] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun value(value: JsonField) = apply { this.value = value } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Np]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Np = + Np( + additionalInfo, + cra, + (funds ?: JsonMissing.of()).map { it.toImmutable() }, + (linkedHolders ?: JsonMissing.of()).map { it.toImmutable() }, + pran, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Np = apply { + if (validated) { + return@apply + } + + cra() + funds().ifPresent { it.forEach { it.validate() } } + linkedHolders().ifPresent { it.forEach { it.validate() } } + pran() + value() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (cra.asKnown().isPresent) 1 else 0) + + (funds.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (linkedHolders.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (pran.asKnown().isPresent) 1 else 0) + + (if (value.asKnown().isPresent) 1 else 0) + + class Fund + private constructor( + private val additionalInfo: JsonField, + private val cost: JsonField, + private val name: JsonField, + private val nav: JsonField, + private val units: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("cost") @ExcludeMissing cost: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("nav") @ExcludeMissing nav: JsonField = JsonMissing.of(), + @JsonProperty("units") @ExcludeMissing units: JsonField = JsonMissing.of(), + @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), + ) : this(additionalInfo, cost, name, nav, units, value, mutableMapOf()) + + /** + * Additional information specific to the NPS fund + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") + + /** + * Cost of investment + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun cost(): Optional = cost.getOptional("cost") + + /** + * Name of the NPS fund + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * Net Asset Value per unit + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun nav(): Optional = nav.getOptional("nav") + + /** + * Number of units held + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun units(): Optional = units.getOptional("units") + + /** + * Current market value of the holding + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo + + /** + * Returns the raw JSON value of [cost]. + * + * Unlike [cost], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("cost") @ExcludeMissing fun _cost(): JsonField = cost + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [nav]. + * + * Unlike [nav], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("nav") @ExcludeMissing fun _nav(): JsonField = nav + + /** + * Returns the raw JSON value of [units]. + * + * Unlike [units], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Fund]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Fund]. */ + class Builder internal constructor() { + + private var additionalInfo: JsonField = JsonMissing.of() + private var cost: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var nav: JsonField = JsonMissing.of() + private var units: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(fund: Fund) = apply { + additionalInfo = fund.additionalInfo + cost = fund.cost + name = fund.name + nav = fund.nav + units = fund.units + value = fund.value + additionalProperties = fund.additionalProperties.toMutableMap() + } + + /** Additional information specific to the NPS fund */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) + + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } + + /** Cost of investment */ + fun cost(cost: Float) = cost(JsonField.of(cost)) + + /** + * Sets [Builder.cost] to an arbitrary JSON value. + * + * You should usually call [Builder.cost] with a well-typed [Float] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun cost(cost: JsonField) = apply { this.cost = cost } + + /** Name of the NPS fund */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** Net Asset Value per unit */ + fun nav(nav: Float) = nav(JsonField.of(nav)) + + /** + * Sets [Builder.nav] to an arbitrary JSON value. + * + * You should usually call [Builder.nav] with a well-typed [Float] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun nav(nav: JsonField) = apply { this.nav = nav } + + /** Number of units held */ + fun units(units: Float) = units(JsonField.of(units)) + + /** + * Sets [Builder.units] to an arbitrary JSON value. + * + * You should usually call [Builder.units] with a well-typed [Float] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun units(units: JsonField) = apply { this.units = units } + + /** Current market value of the holding */ + fun value(value: Float) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Float] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Fund]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Fund = + Fund( + additionalInfo, + cost, + name, + nav, + units, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Fund = apply { + if (validated) { + return@apply + } + + additionalInfo().ifPresent { it.validate() } + cost() + name() + nav() + units() + value() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (cost.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (if (nav.asKnown().isPresent) 1 else 0) + + (if (units.asKnown().isPresent) 1 else 0) + + (if (value.asKnown().isPresent) 1 else 0) + + /** Additional information specific to the NPS fund */ + class AdditionalInfo + private constructor( + private val manager: JsonField, + private val tier: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("manager") + @ExcludeMissing + manager: JsonField = JsonMissing.of(), + @JsonProperty("tier") @ExcludeMissing tier: JsonField = JsonMissing.of(), + ) : this(manager, tier, mutableMapOf()) + + /** + * Fund manager name + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun manager(): Optional = manager.getOptional("manager") + + /** + * NPS tier (Tier I or Tier II) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun tier(): Optional = tier.getOptional("tier") + + /** + * Returns the raw JSON value of [manager]. + * + * Unlike [manager], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("manager") @ExcludeMissing fun _manager(): JsonField = manager + + /** + * Returns the raw JSON value of [tier]. + * + * Unlike [tier], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("tier") @ExcludeMissing fun _tier(): JsonField = tier + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { + + private var manager: JsonField = JsonMissing.of() + private var tier: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + manager = additionalInfo.manager + tier = additionalInfo.tier + additionalProperties = additionalInfo.additionalProperties.toMutableMap() + } + + /** Fund manager name */ + fun manager(manager: String) = manager(JsonField.of(manager)) + + /** + * Sets [Builder.manager] to an arbitrary JSON value. + * + * You should usually call [Builder.manager] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun manager(manager: JsonField) = apply { this.manager = manager } + + /** NPS tier (Tier I or Tier II) */ + fun tier(tier: Tier?) = tier(JsonField.ofNullable(tier)) + + /** Alias for calling [Builder.tier] with `tier.orElse(null)`. */ + fun tier(tier: Optional) = tier(tier.getOrNull()) + + /** + * Sets [Builder.tier] to an arbitrary JSON value. + * + * You should usually call [Builder.tier] with a well-typed [Tier] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun tier(tier: JsonField) = apply { this.tier = tier } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo(manager, tier, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } + + manager() + tier().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (manager.asKnown().isPresent) 1 else 0) + + (tier.asKnown().getOrNull()?.validity() ?: 0) + + /** NPS tier (Tier I or Tier II) */ + class Tier @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value + + companion object { + + @JvmField val _1 = of(1.0) + + @JvmField val _2 = of(2.0) + + @JvmStatic fun of(value: Double) = Tier(JsonField.of(value)) + } + + /** An enum containing [Tier]'s known values. */ + enum class Known { + _1, + _2, + } + + /** + * An enum containing [Tier]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Tier] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _1, + _2, + /** + * An enum member indicating that [Tier] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or + * if you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _1 -> Value._1 + _2 -> Value._2 + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known + * and don't want to throw for the unknown case. + * + * @throws CasParserInvalidDataException if this class instance's value is a not + * a known member. + */ + fun known(): Known = + when (this) { + _1 -> Known._1 + _2 -> Known._2 + else -> throw CasParserInvalidDataException("Unknown Tier: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * @throws CasParserInvalidDataException if this class instance's value does not + * have the expected primitive type. + */ + fun asDouble(): Double = + _value().asNumber().getOrNull()?.toDouble() + ?: throw CasParserInvalidDataException("Value is not a Double") + + private var validated: Boolean = false + + fun validate(): Tier = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Tier && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AdditionalInfo && + manager == other.manager && + tier == other.tier && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(manager, tier, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{manager=$manager, tier=$tier, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Fund && + additionalInfo == other.additionalInfo && + cost == other.cost && + name == other.name && + nav == other.nav && + units == other.units && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(additionalInfo, cost, name, nav, units, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Fund{additionalInfo=$additionalInfo, cost=$cost, name=$name, nav=$nav, units=$units, value=$value, additionalProperties=$additionalProperties}" + } + + class LinkedHolder + private constructor( + private val name: JsonField, + private val pan: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), + ) : this(name, pan, mutableMapOf()) + + /** + * Name of the account holder + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * PAN of the account holder + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun pan(): Optional = pan.getOptional("pan") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [pan]. + * + * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [LinkedHolder]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LinkedHolder]. */ + class Builder internal constructor() { + + private var name: JsonField = JsonMissing.of() + private var pan: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(linkedHolder: LinkedHolder) = apply { + name = linkedHolder.name + pan = linkedHolder.pan + additionalProperties = linkedHolder.additionalProperties.toMutableMap() + } + + /** Name of the account holder */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** PAN of the account holder */ + fun pan(pan: String) = pan(JsonField.of(pan)) + + /** + * Sets [Builder.pan] to an arbitrary JSON value. + * + * You should usually call [Builder.pan] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun pan(pan: JsonField) = apply { this.pan = pan } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [LinkedHolder]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): LinkedHolder = + LinkedHolder(name, pan, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): LinkedHolder = apply { + if (validated) { + return@apply + } + + name() + pan() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (name.asKnown().isPresent) 1 else 0) + (if (pan.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is LinkedHolder && + name == other.name && + pan == other.pan && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(name, pan, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "LinkedHolder{name=$name, pan=$pan, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Np && + additionalInfo == other.additionalInfo && + cra == other.cra && + funds == other.funds && + linkedHolders == other.linkedHolders && + pran == other.pran && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + cra, + funds, + linkedHolders, + pran, + value, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Np{additionalInfo=$additionalInfo, cra=$cra, funds=$funds, linkedHolders=$linkedHolders, pran=$pran, value=$value, additionalProperties=$additionalProperties}" + } + + class Summary + private constructor( + private val accounts: JsonField, + private val totalValue: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("accounts") + @ExcludeMissing + accounts: JsonField = JsonMissing.of(), + @JsonProperty("total_value") + @ExcludeMissing + totalValue: JsonField = JsonMissing.of(), + ) : this(accounts, totalValue, mutableMapOf()) + + /** + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun accounts(): Optional = accounts.getOptional("accounts") + + /** + * Total portfolio value across all accounts + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun totalValue(): Optional = totalValue.getOptional("total_value") + + /** + * Returns the raw JSON value of [accounts]. + * + * Unlike [accounts], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("accounts") @ExcludeMissing fun _accounts(): JsonField = accounts + + /** + * Returns the raw JSON value of [totalValue]. + * + * Unlike [totalValue], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("total_value") + @ExcludeMissing + fun _totalValue(): JsonField = totalValue + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Summary]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Summary]. */ + class Builder internal constructor() { + + private var accounts: JsonField = JsonMissing.of() + private var totalValue: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(summary: Summary) = apply { + accounts = summary.accounts + totalValue = summary.totalValue + additionalProperties = summary.additionalProperties.toMutableMap() + } + + fun accounts(accounts: Accounts) = accounts(JsonField.of(accounts)) + + /** + * Sets [Builder.accounts] to an arbitrary JSON value. + * + * You should usually call [Builder.accounts] with a well-typed [Accounts] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun accounts(accounts: JsonField) = apply { this.accounts = accounts } + + /** Total portfolio value across all accounts */ + fun totalValue(totalValue: Float) = totalValue(JsonField.of(totalValue)) /** * Sets [Builder.totalValue] to an arbitrary JSON value. @@ -7158,6 +8864,7 @@ private constructor( private val demat: JsonField, private val insurance: JsonField, private val mutualFunds: JsonField, + private val nps: JsonField, private val additionalProperties: MutableMap, ) { @@ -7170,7 +8877,8 @@ private constructor( @JsonProperty("mutual_funds") @ExcludeMissing mutualFunds: JsonField = JsonMissing.of(), - ) : this(demat, insurance, mutualFunds, mutableMapOf()) + @JsonProperty("nps") @ExcludeMissing nps: JsonField = JsonMissing.of(), + ) : this(demat, insurance, mutualFunds, nps, mutableMapOf()) /** * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. @@ -7190,6 +8898,12 @@ private constructor( */ fun mutualFunds(): Optional = mutualFunds.getOptional("mutual_funds") + /** + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun nps(): Optional = nps.getOptional("nps") + /** * Returns the raw JSON value of [demat]. * @@ -7217,6 +8931,13 @@ private constructor( @ExcludeMissing fun _mutualFunds(): JsonField = mutualFunds + /** + * Returns the raw JSON value of [nps]. + * + * Unlike [nps], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("nps") @ExcludeMissing fun _nps(): JsonField = nps + @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -7241,6 +8962,7 @@ private constructor( private var demat: JsonField = JsonMissing.of() private var insurance: JsonField = JsonMissing.of() private var mutualFunds: JsonField = JsonMissing.of() + private var nps: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -7248,6 +8970,7 @@ private constructor( demat = accounts.demat insurance = accounts.insurance mutualFunds = accounts.mutualFunds + nps = accounts.nps additionalProperties = accounts.additionalProperties.toMutableMap() } @@ -7288,6 +9011,17 @@ private constructor( this.mutualFunds = mutualFunds } + fun nps(nps: Nps) = nps(JsonField.of(nps)) + + /** + * Sets [Builder.nps] to an arbitrary JSON value. + * + * You should usually call [Builder.nps] with a well-typed [Nps] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun nps(nps: JsonField) = apply { this.nps = nps } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -7316,7 +9050,13 @@ private constructor( * Further updates to this [Builder] will not mutate the returned instance. */ fun build(): Accounts = - Accounts(demat, insurance, mutualFunds, additionalProperties.toMutableMap()) + Accounts( + demat, + insurance, + mutualFunds, + nps, + additionalProperties.toMutableMap(), + ) } private var validated: Boolean = false @@ -7329,6 +9069,7 @@ private constructor( demat().ifPresent { it.validate() } insurance().ifPresent { it.validate() } mutualFunds().ifPresent { it.validate() } + nps().ifPresent { it.validate() } validated = true } @@ -7350,7 +9091,8 @@ private constructor( internal fun validity(): Int = (demat.asKnown().getOrNull()?.validity() ?: 0) + (insurance.asKnown().getOrNull()?.validity() ?: 0) + - (mutualFunds.asKnown().getOrNull()?.validity() ?: 0) + (mutualFunds.asKnown().getOrNull()?.validity() ?: 0) + + (nps.asKnown().getOrNull()?.validity() ?: 0) class Demat private constructor( @@ -7928,6 +9670,197 @@ private constructor( "MutualFunds{count=$count, totalValue=$totalValue, additionalProperties=$additionalProperties}" } + class Nps + private constructor( + private val count: JsonField, + private val totalValue: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("count") + @ExcludeMissing + count: JsonField = JsonMissing.of(), + @JsonProperty("total_value") + @ExcludeMissing + totalValue: JsonField = JsonMissing.of(), + ) : this(count, totalValue, mutableMapOf()) + + /** + * Number of NPS accounts + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun count(): Optional = count.getOptional("count") + + /** + * Total value of NPS accounts + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun totalValue(): Optional = totalValue.getOptional("total_value") + + /** + * Returns the raw JSON value of [count]. + * + * Unlike [count], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("count") @ExcludeMissing fun _count(): JsonField = count + + /** + * Returns the raw JSON value of [totalValue]. + * + * Unlike [totalValue], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("total_value") + @ExcludeMissing + fun _totalValue(): JsonField = totalValue + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Nps]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Nps]. */ + class Builder internal constructor() { + + private var count: JsonField = JsonMissing.of() + private var totalValue: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(nps: Nps) = apply { + count = nps.count + totalValue = nps.totalValue + additionalProperties = nps.additionalProperties.toMutableMap() + } + + /** Number of NPS accounts */ + fun count(count: Long) = count(JsonField.of(count)) + + /** + * Sets [Builder.count] to an arbitrary JSON value. + * + * You should usually call [Builder.count] with a well-typed [Long] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun count(count: JsonField) = apply { this.count = count } + + /** Total value of NPS accounts */ + fun totalValue(totalValue: Float) = totalValue(JsonField.of(totalValue)) + + /** + * Sets [Builder.totalValue] to an arbitrary JSON value. + * + * You should usually call [Builder.totalValue] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun totalValue(totalValue: JsonField) = apply { + this.totalValue = totalValue + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Nps]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Nps = Nps(count, totalValue, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Nps = apply { + if (validated) { + return@apply + } + + count() + totalValue() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (count.asKnown().isPresent) 1 else 0) + + (if (totalValue.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Nps && + count == other.count && + totalValue == other.totalValue && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(count, totalValue, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Nps{count=$count, totalValue=$totalValue, additionalProperties=$additionalProperties}" + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -7937,17 +9870,18 @@ private constructor( demat == other.demat && insurance == other.insurance && mutualFunds == other.mutualFunds && + nps == other.nps && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(demat, insurance, mutualFunds, additionalProperties) + Objects.hash(demat, insurance, mutualFunds, nps, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "Accounts{demat=$demat, insurance=$insurance, mutualFunds=$mutualFunds, additionalProperties=$additionalProperties}" + "Accounts{demat=$demat, insurance=$insurance, mutualFunds=$mutualFunds, nps=$nps, additionalProperties=$additionalProperties}" } override fun equals(other: Any?): Boolean { @@ -7982,6 +9916,7 @@ private constructor( investor == other.investor && meta == other.meta && mutualFunds == other.mutualFunds && + nps == other.nps && summary == other.summary && additionalProperties == other.additionalProperties } @@ -7993,6 +9928,7 @@ private constructor( investor, meta, mutualFunds, + nps, summary, additionalProperties, ) @@ -8001,5 +9937,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnifiedResponse{dematAccounts=$dematAccounts, insurance=$insurance, investor=$investor, meta=$meta, mutualFunds=$mutualFunds, summary=$summary, additionalProperties=$additionalProperties}" + "UnifiedResponse{dematAccounts=$dematAccounts, insurance=$insurance, investor=$investor, meta=$meta, mutualFunds=$mutualFunds, nps=$nps, summary=$summary, additionalProperties=$additionalProperties}" } diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/UnifiedResponseTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/UnifiedResponseTest.kt index 1a5cffc..86f7a31 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/UnifiedResponseTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/UnifiedResponseTest.kt @@ -86,6 +86,12 @@ internal class UnifiedResponseTest { ) .build() ) + .addLinkedHolder( + UnifiedResponse.DematAccount.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) .value(0.0f) .build() ) @@ -140,6 +146,12 @@ internal class UnifiedResponseTest { ) .amc("amc") .folioNumber("folio_number") + .addLinkedHolder( + UnifiedResponse.MutualFund.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) .registrar("registrar") .addScheme( UnifiedResponse.MutualFund.Scheme.builder() @@ -183,6 +195,35 @@ internal class UnifiedResponseTest { .value(0.0f) .build() ) + .addNp( + UnifiedResponse.Np.builder() + .additionalInfo(JsonValue.from(mapOf())) + .cra("cra") + .addFund( + UnifiedResponse.Np.Fund.builder() + .additionalInfo( + UnifiedResponse.Np.Fund.AdditionalInfo.builder() + .manager("manager") + .tier(UnifiedResponse.Np.Fund.AdditionalInfo.Tier._1) + .build() + ) + .cost(0.0f) + .name("name") + .nav(0.0f) + .units(0.0f) + .value(0.0f) + .build() + ) + .addLinkedHolder( + UnifiedResponse.Np.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) + .pran("pran") + .value(0.0f) + .build() + ) .summary( UnifiedResponse.Summary.builder() .accounts( @@ -205,6 +246,12 @@ internal class UnifiedResponseTest { .totalValue(0.0f) .build() ) + .nps( + UnifiedResponse.Summary.Accounts.Nps.builder() + .count(0L) + .totalValue(0.0f) + .build() + ) .build() ) .totalValue(0.0f) @@ -281,6 +328,12 @@ internal class UnifiedResponseTest { ) .build() ) + .addLinkedHolder( + UnifiedResponse.DematAccount.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) .value(0.0f) .build() ) @@ -339,6 +392,12 @@ internal class UnifiedResponseTest { ) .amc("amc") .folioNumber("folio_number") + .addLinkedHolder( + UnifiedResponse.MutualFund.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) .registrar("registrar") .addScheme( UnifiedResponse.MutualFund.Scheme.builder() @@ -382,6 +441,33 @@ internal class UnifiedResponseTest { .value(0.0f) .build() ) + assertThat(unifiedResponse.nps().getOrNull()) + .containsExactly( + UnifiedResponse.Np.builder() + .additionalInfo(JsonValue.from(mapOf())) + .cra("cra") + .addFund( + UnifiedResponse.Np.Fund.builder() + .additionalInfo( + UnifiedResponse.Np.Fund.AdditionalInfo.builder() + .manager("manager") + .tier(UnifiedResponse.Np.Fund.AdditionalInfo.Tier._1) + .build() + ) + .cost(0.0f) + .name("name") + .nav(0.0f) + .units(0.0f) + .value(0.0f) + .build() + ) + .addLinkedHolder( + UnifiedResponse.Np.LinkedHolder.builder().name("name").pan("pan").build() + ) + .pran("pran") + .value(0.0f) + .build() + ) assertThat(unifiedResponse.summary()) .contains( UnifiedResponse.Summary.builder() @@ -405,6 +491,12 @@ internal class UnifiedResponseTest { .totalValue(0.0f) .build() ) + .nps( + UnifiedResponse.Summary.Accounts.Nps.builder() + .count(0L) + .totalValue(0.0f) + .build() + ) .build() ) .totalValue(0.0f) @@ -486,6 +578,12 @@ internal class UnifiedResponseTest { ) .build() ) + .addLinkedHolder( + UnifiedResponse.DematAccount.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) .value(0.0f) .build() ) @@ -540,6 +638,12 @@ internal class UnifiedResponseTest { ) .amc("amc") .folioNumber("folio_number") + .addLinkedHolder( + UnifiedResponse.MutualFund.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) .registrar("registrar") .addScheme( UnifiedResponse.MutualFund.Scheme.builder() @@ -583,6 +687,35 @@ internal class UnifiedResponseTest { .value(0.0f) .build() ) + .addNp( + UnifiedResponse.Np.builder() + .additionalInfo(JsonValue.from(mapOf())) + .cra("cra") + .addFund( + UnifiedResponse.Np.Fund.builder() + .additionalInfo( + UnifiedResponse.Np.Fund.AdditionalInfo.builder() + .manager("manager") + .tier(UnifiedResponse.Np.Fund.AdditionalInfo.Tier._1) + .build() + ) + .cost(0.0f) + .name("name") + .nav(0.0f) + .units(0.0f) + .value(0.0f) + .build() + ) + .addLinkedHolder( + UnifiedResponse.Np.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) + .pran("pran") + .value(0.0f) + .build() + ) .summary( UnifiedResponse.Summary.builder() .accounts( @@ -605,6 +738,12 @@ internal class UnifiedResponseTest { .totalValue(0.0f) .build() ) + .nps( + UnifiedResponse.Summary.Accounts.Nps.builder() + .count(0L) + .totalValue(0.0f) + .build() + ) .build() ) .totalValue(0.0f) diff --git a/cas-parser-java-proguard-test/src/test/kotlin/com/cas_parser/api/proguard/ProGuardCompatibilityTest.kt b/cas-parser-java-proguard-test/src/test/kotlin/com/cas_parser/api/proguard/ProGuardCompatibilityTest.kt index f132d1f..e2b76ff 100644 --- a/cas-parser-java-proguard-test/src/test/kotlin/com/cas_parser/api/proguard/ProGuardCompatibilityTest.kt +++ b/cas-parser-java-proguard-test/src/test/kotlin/com/cas_parser/api/proguard/ProGuardCompatibilityTest.kt @@ -128,6 +128,12 @@ internal class ProGuardCompatibilityTest { ) .build() ) + .addLinkedHolder( + UnifiedResponse.DematAccount.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) .value(0.0f) .build() ) @@ -182,6 +188,12 @@ internal class ProGuardCompatibilityTest { ) .amc("amc") .folioNumber("folio_number") + .addLinkedHolder( + UnifiedResponse.MutualFund.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) .registrar("registrar") .addScheme( UnifiedResponse.MutualFund.Scheme.builder() @@ -225,6 +237,35 @@ internal class ProGuardCompatibilityTest { .value(0.0f) .build() ) + .addNp( + UnifiedResponse.Np.builder() + .additionalInfo(JsonValue.from(mapOf())) + .cra("cra") + .addFund( + UnifiedResponse.Np.Fund.builder() + .additionalInfo( + UnifiedResponse.Np.Fund.AdditionalInfo.builder() + .manager("manager") + .tier(UnifiedResponse.Np.Fund.AdditionalInfo.Tier._1) + .build() + ) + .cost(0.0f) + .name("name") + .nav(0.0f) + .units(0.0f) + .value(0.0f) + .build() + ) + .addLinkedHolder( + UnifiedResponse.Np.LinkedHolder.builder() + .name("name") + .pan("pan") + .build() + ) + .pran("pran") + .value(0.0f) + .build() + ) .summary( UnifiedResponse.Summary.builder() .accounts( @@ -247,6 +288,12 @@ internal class ProGuardCompatibilityTest { .totalValue(0.0f) .build() ) + .nps( + UnifiedResponse.Summary.Accounts.Nps.builder() + .count(0L) + .totalValue(0.0f) + .build() + ) .build() ) .totalValue(0.0f) From ce29632f7f03c172ad042bbaa68e431ab2fd7fa7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 02:22:21 +0000 Subject: [PATCH 5/9] fix(client): deserialization of empty objects --- .../CasGeneratorGenerateCasParams.kt | 1 + .../CasGeneratorGenerateCasResponse.kt | 1 + .../api/models/casparser/UnifiedResponse.kt | 32 +++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParams.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParams.kt index eb7213c..598c6a2 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParams.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParams.kt @@ -394,6 +394,7 @@ private constructor( override fun _queryParams(): QueryParams = additionalQueryParams class Body + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val email: JsonField, private val fromDate: JsonField, diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponse.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponse.kt index 09df4cd..ad4901d 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponse.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponse.kt @@ -16,6 +16,7 @@ import java.util.Objects import java.util.Optional class CasGeneratorGenerateCasResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val msg: JsonField, private val status: JsonField, diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt index 67cc09d..98a9131 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt @@ -22,6 +22,7 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull class UnifiedResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val dematAccounts: JsonField>, private val insurance: JsonField, @@ -380,6 +381,7 @@ private constructor( (summary.asKnown().getOrNull()?.validity() ?: 0) class DematAccount + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonField, private val boId: JsonField, @@ -827,6 +829,7 @@ private constructor( /** Additional information specific to the demat account type */ class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val boStatus: JsonField, private val boSubStatus: JsonField, @@ -1408,6 +1411,7 @@ private constructor( } class Holdings + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val aifs: JsonField>, private val corporateBonds: JsonField>, @@ -1766,6 +1770,7 @@ private constructor( ?: 0) class Aif + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonValue, private val isin: JsonField, @@ -2052,6 +2057,7 @@ private constructor( } class CorporateBond + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonValue, private val isin: JsonField, @@ -2340,6 +2346,7 @@ private constructor( } class DematMutualFund + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonValue, private val isin: JsonField, @@ -2628,6 +2635,7 @@ private constructor( } class Equity + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonValue, private val isin: JsonField, @@ -2914,6 +2922,7 @@ private constructor( } class GovernmentSecurity + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonValue, private val isin: JsonField, @@ -3235,6 +3244,7 @@ private constructor( } class LinkedHolder + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val name: JsonField, private val pan: JsonField, @@ -3453,6 +3463,7 @@ private constructor( } class Insurance + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val lifeInsurancePolicies: JsonField>, private val additionalProperties: MutableMap, @@ -3600,6 +3611,7 @@ private constructor( (lifeInsurancePolicies.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) class LifeInsurancePolicy + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonValue, private val lifeAssured: JsonField, @@ -4107,6 +4119,7 @@ private constructor( } class Investor + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val address: JsonField, private val casId: JsonField, @@ -4465,6 +4478,7 @@ private constructor( } class Meta + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val casType: JsonField, private val generatedAt: JsonField, @@ -4807,6 +4821,7 @@ private constructor( } class StatementPeriod + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val from: JsonField, private val to: JsonField, @@ -5008,6 +5023,7 @@ private constructor( } class MutualFund + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonField, private val amc: JsonField, @@ -5401,6 +5417,7 @@ private constructor( /** Additional folio information */ class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val kyc: JsonField, private val pan: JsonField, @@ -5617,6 +5634,7 @@ private constructor( } class LinkedHolder + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val name: JsonField, private val pan: JsonField, @@ -5796,6 +5814,7 @@ private constructor( } class Scheme + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonField, private val cost: JsonField, @@ -6324,6 +6343,7 @@ private constructor( /** Additional information specific to the scheme */ class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val advisor: JsonField, private val amfi: JsonField, @@ -6649,6 +6669,7 @@ private constructor( } class Gain + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val absolute: JsonField, private val percentage: JsonField, @@ -6843,6 +6864,7 @@ private constructor( } class Transaction + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val amount: JsonField, private val balance: JsonField, @@ -7517,6 +7539,7 @@ private constructor( } class Np + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonValue, private val cra: JsonField, @@ -7830,6 +7853,7 @@ private constructor( (if (value.asKnown().isPresent) 1 else 0) class Fund + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val additionalInfo: JsonField, private val cost: JsonField, @@ -8141,6 +8165,7 @@ private constructor( /** Additional information specific to the NPS fund */ class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val manager: JsonField, private val tier: JsonField, @@ -8487,6 +8512,7 @@ private constructor( } class LinkedHolder + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val name: JsonField, private val pan: JsonField, @@ -8699,6 +8725,7 @@ private constructor( } class Summary + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val accounts: JsonField, private val totalValue: JsonField, @@ -8860,6 +8887,7 @@ private constructor( (if (totalValue.asKnown().isPresent) 1 else 0) class Accounts + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val demat: JsonField, private val insurance: JsonField, @@ -9095,6 +9123,7 @@ private constructor( (nps.asKnown().getOrNull()?.validity() ?: 0) class Demat + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val count: JsonField, private val totalValue: JsonField, @@ -9287,6 +9316,7 @@ private constructor( } class Insurance + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val count: JsonField, private val totalValue: JsonField, @@ -9479,6 +9509,7 @@ private constructor( } class MutualFunds + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val count: JsonField, private val totalValue: JsonField, @@ -9671,6 +9702,7 @@ private constructor( } class Nps + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val count: JsonField, private val totalValue: JsonField, From 91a54b7acbf164ad459293fe697a4b0c9a795758 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 1 Jan 2026 23:19:39 +0000 Subject: [PATCH 6/9] feat(api): api update --- .stats.yml | 4 +- LICENSE | 2 +- README.md | 4 +- .../build.gradle.kts | 1 + .../api/client/okhttp/OkHttpClient.kt | 40 +- .../api/client/okhttp/OkHttpClientTest.kt | 44 + .../api/models/casparser/UnifiedResponse.kt | 16489 ++++++++++++---- .../models/casparser/UnifiedResponseTest.kt | 688 +- .../api/proguard/ProGuardCompatibilityTest.kt | 231 +- 9 files changed, 13410 insertions(+), 4093 deletions(-) create mode 100644 cas-parser-java-client-okhttp/src/test/kotlin/com/cas_parser/api/client/okhttp/OkHttpClientTest.kt diff --git a/.stats.yml b/.stats.yml index 06e7614..48b33b3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 5 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-9eaed98ce5934f11e901cef376a28257d2c196bd3dba7c690babc6741a730ded.yml -openapi_spec_hash: b76e4e830c4d03ba4cf9429bb9fb9c8a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-38618cc5c938e87eeacf4893d6a6ba4e6ef7da390e6283dc7b50b484a7b97165.yml +openapi_spec_hash: b9e439ecee904ded01aa34efdee88856 config_hash: cb5d75abef6264b5d86448caf7295afa diff --git a/LICENSE b/LICENSE index f1756ce..6bbb512 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 Cas Parser + Copyright 2026 Cas Parser Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index eb1c0bb..15ce0f4 100644 --- a/README.md +++ b/README.md @@ -248,13 +248,13 @@ The SDK uses the standard [OkHttp logging interceptor](https://github.com/square Enable logging by setting the `CAS_PARSER_LOG` environment variable to `info`: ```sh -$ export CAS_PARSER_LOG=info +export CAS_PARSER_LOG=info ``` Or to `debug` for more verbose logging: ```sh -$ export CAS_PARSER_LOG=debug +export CAS_PARSER_LOG=debug ``` ## ProGuard and R8 diff --git a/cas-parser-java-client-okhttp/build.gradle.kts b/cas-parser-java-client-okhttp/build.gradle.kts index 115d28c..91df2a9 100644 --- a/cas-parser-java-client-okhttp/build.gradle.kts +++ b/cas-parser-java-client-okhttp/build.gradle.kts @@ -11,4 +11,5 @@ dependencies { testImplementation(kotlin("test")) testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2") } diff --git a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/OkHttpClient.kt b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/OkHttpClient.kt index 281e1c4..eee1317 100644 --- a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/OkHttpClient.kt +++ b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/OkHttpClient.kt @@ -13,6 +13,7 @@ import java.io.IOException import java.io.InputStream import java.net.Proxy import java.time.Duration +import java.util.concurrent.CancellationException import java.util.concurrent.CompletableFuture import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory @@ -29,8 +30,8 @@ import okhttp3.Response import okhttp3.logging.HttpLoggingInterceptor import okio.BufferedSink -class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpClient) : - HttpClient { +class OkHttpClient +private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) : HttpClient { override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { val call = newCall(request, requestOptions) @@ -50,20 +51,25 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC ): CompletableFuture { val future = CompletableFuture() - request.body?.run { future.whenComplete { _, _ -> close() } } - - newCall(request, requestOptions) - .enqueue( - object : Callback { - override fun onResponse(call: Call, response: Response) { - future.complete(response.toResponse()) - } + val call = newCall(request, requestOptions) + call.enqueue( + object : Callback { + override fun onResponse(call: Call, response: Response) { + future.complete(response.toResponse()) + } - override fun onFailure(call: Call, e: IOException) { - future.completeExceptionally(CasParserIoException("Request failed", e)) - } + override fun onFailure(call: Call, e: IOException) { + future.completeExceptionally(CasParserIoException("Request failed", e)) } - ) + } + ) + + future.whenComplete { _, e -> + if (e is CancellationException) { + call.cancel() + } + request.body?.close() + } return future } @@ -109,19 +115,19 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC val builder = Request.Builder().url(toUrl()).method(method.name, body) headers.names().forEach { name -> - headers.values(name).forEach { builder.header(name, it) } + headers.values(name).forEach { builder.addHeader(name, it) } } if ( !headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0 ) { - builder.header( + builder.addHeader( "X-Stainless-Read-Timeout", Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString(), ) } if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) { - builder.header( + builder.addHeader( "X-Stainless-Timeout", Duration.ofMillis(client.callTimeoutMillis.toLong()).seconds.toString(), ) diff --git a/cas-parser-java-client-okhttp/src/test/kotlin/com/cas_parser/api/client/okhttp/OkHttpClientTest.kt b/cas-parser-java-client-okhttp/src/test/kotlin/com/cas_parser/api/client/okhttp/OkHttpClientTest.kt new file mode 100644 index 0000000..457b40c --- /dev/null +++ b/cas-parser-java-client-okhttp/src/test/kotlin/com/cas_parser/api/client/okhttp/OkHttpClientTest.kt @@ -0,0 +1,44 @@ +package com.cas_parser.api.client.okhttp + +import com.cas_parser.api.core.http.HttpMethod +import com.cas_parser.api.core.http.HttpRequest +import com.github.tomakehurst.wiremock.client.WireMock.* +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo +import com.github.tomakehurst.wiremock.junit5.WireMockTest +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.parallel.ResourceLock + +@WireMockTest +@ResourceLock("https://github.com/wiremock/wiremock/issues/169") +internal class OkHttpClientTest { + + private lateinit var baseUrl: String + private lateinit var httpClient: OkHttpClient + + @BeforeEach + fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) { + baseUrl = wmRuntimeInfo.httpBaseUrl + httpClient = OkHttpClient.builder().build() + } + + @Test + fun executeAsync_whenFutureCancelled_cancelsUnderlyingCall() { + stubFor(post(urlPathEqualTo("/something")).willReturn(ok())) + val responseFuture = + httpClient.executeAsync( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build() + ) + val call = httpClient.okHttpClient.dispatcher.runningCalls().single() + + responseFuture.cancel(false) + + // Should have cancelled the underlying call + assertThat(call.isCanceled()).isTrue() + } +} diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt index 98a9131..e64ebfb 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casparser/UnifiedResponse.kt @@ -1772,9 +1772,10 @@ private constructor( class Aif @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val additionalInfo: JsonValue, + private val additionalInfo: JsonField, private val isin: JsonField, private val name: JsonField, + private val transactions: JsonField>, private val units: JsonField, private val value: JsonField, private val additionalProperties: MutableMap, @@ -1784,25 +1785,32 @@ private constructor( private constructor( @JsonProperty("additional_info") @ExcludeMissing - additionalInfo: JsonValue = JsonMissing.of(), + additionalInfo: JsonField = JsonMissing.of(), @JsonProperty("isin") @ExcludeMissing isin: JsonField = JsonMissing.of(), @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("transactions") + @ExcludeMissing + transactions: JsonField> = JsonMissing.of(), @JsonProperty("units") @ExcludeMissing units: JsonField = JsonMissing.of(), @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), - ) : this(additionalInfo, isin, name, units, value, mutableMapOf()) + ) : this(additionalInfo, isin, name, transactions, units, value, mutableMapOf()) - /** Additional information specific to the AIF */ - @JsonProperty("additional_info") - @ExcludeMissing - fun _additionalInfo(): JsonValue = additionalInfo + /** + * Additional information specific to the AIF + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") /** * ISIN code of the AIF @@ -1820,6 +1828,15 @@ private constructor( */ fun name(): Optional = name.getOptional("name") + /** + * List of transactions for this holding (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun transactions(): Optional> = + transactions.getOptional("transactions") + /** * Number of units held * @@ -1836,6 +1853,16 @@ private constructor( */ fun value(): Optional = value.getOptional("value") + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo + /** * Returns the raw JSON value of [isin]. * @@ -1852,6 +1879,16 @@ private constructor( */ @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + /** + * Returns the raw JSON value of [transactions]. + * + * Unlike [transactions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("transactions") + @ExcludeMissing + fun _transactions(): JsonField> = transactions + /** * Returns the raw JSON value of [units]. * @@ -1889,9 +1926,10 @@ private constructor( /** A builder for [Aif]. */ class Builder internal constructor() { - private var additionalInfo: JsonValue = JsonMissing.of() + private var additionalInfo: JsonField = JsonMissing.of() private var isin: JsonField = JsonMissing.of() private var name: JsonField = JsonMissing.of() + private var transactions: JsonField>? = null private var units: JsonField = JsonMissing.of() private var value: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -1901,13 +1939,24 @@ private constructor( additionalInfo = aif.additionalInfo isin = aif.isin name = aif.name + transactions = aif.transactions.map { it.toMutableList() } units = aif.units value = aif.value additionalProperties = aif.additionalProperties.toMutableMap() } /** Additional information specific to the AIF */ - fun additionalInfo(additionalInfo: JsonValue) = apply { + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) + + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { this.additionalInfo = additionalInfo } @@ -1935,6 +1984,33 @@ private constructor( */ fun name(name: JsonField) = apply { this.name = name } + /** List of transactions for this holding (beta) */ + fun transactions(transactions: List) = + transactions(JsonField.of(transactions)) + + /** + * Sets [Builder.transactions] to an arbitrary JSON value. + * + * You should usually call [Builder.transactions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun transactions(transactions: JsonField>) = apply { + this.transactions = transactions.map { it.toMutableList() } + } + + /** + * Adds a single [Transaction] to [transactions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTransaction(transaction: Transaction) = apply { + transactions = + (transactions ?: JsonField.of(mutableListOf())).also { + checkKnown("transactions", it).add(transaction) + } + } + /** Number of units held */ fun units(units: Float) = units(JsonField.of(units)) @@ -1991,6 +2067,7 @@ private constructor( additionalInfo, isin, name, + (transactions ?: JsonMissing.of()).map { it.toImmutable() }, units, value, additionalProperties.toMutableMap(), @@ -2004,8 +2081,10 @@ private constructor( return@apply } + additionalInfo().ifPresent { it.validate() } isin() name() + transactions().ifPresent { it.forEach { it.validate() } } units() value() validated = true @@ -2027,650 +2106,1530 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (if (isin.asKnown().isPresent) 1 else 0) + + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (isin.asKnown().isPresent) 1 else 0) + (if (name.asKnown().isPresent) 1 else 0) + + (transactions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (units.asKnown().isPresent) 1 else 0) + (if (value.asKnown().isPresent) 1 else 0) - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** Additional information specific to the AIF */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val closeUnits: JsonField, + private val openUnits: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("close_units") + @ExcludeMissing + closeUnits: JsonField = JsonMissing.of(), + @JsonProperty("open_units") + @ExcludeMissing + openUnits: JsonField = JsonMissing.of(), + ) : this(closeUnits, openUnits, mutableMapOf()) - return other is Aif && - additionalInfo == other.additionalInfo && - isin == other.isin && - name == other.name && - units == other.units && - value == other.value && - additionalProperties == other.additionalProperties - } + /** + * Closing balance units for the statement period (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun closeUnits(): Optional = closeUnits.getOptional("close_units") - private val hashCode: Int by lazy { - Objects.hash(additionalInfo, isin, name, units, value, additionalProperties) - } + /** + * Opening balance units for the statement period (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun openUnits(): Optional = openUnits.getOptional("open_units") - override fun hashCode(): Int = hashCode + /** + * Returns the raw JSON value of [closeUnits]. + * + * Unlike [closeUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("close_units") + @ExcludeMissing + fun _closeUnits(): JsonField = closeUnits - override fun toString() = - "Aif{additionalInfo=$additionalInfo, isin=$isin, name=$name, units=$units, value=$value, additionalProperties=$additionalProperties}" - } + /** + * Returns the raw JSON value of [openUnits]. + * + * Unlike [openUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("open_units") + @ExcludeMissing + fun _openUnits(): JsonField = openUnits - class CorporateBond - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val additionalInfo: JsonValue, - private val isin: JsonField, - private val name: JsonField, - private val units: JsonField, - private val value: JsonField, - private val additionalProperties: MutableMap, - ) { + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - @JsonCreator - private constructor( - @JsonProperty("additional_info") - @ExcludeMissing - additionalInfo: JsonValue = JsonMissing.of(), - @JsonProperty("isin") + @JsonAnyGetter @ExcludeMissing - isin: JsonField = JsonMissing.of(), - @JsonProperty("name") - @ExcludeMissing - name: JsonField = JsonMissing.of(), - @JsonProperty("units") - @ExcludeMissing - units: JsonField = JsonMissing.of(), - @JsonProperty("value") - @ExcludeMissing - value: JsonField = JsonMissing.of(), - ) : this(additionalInfo, isin, name, units, value, mutableMapOf()) + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - /** Additional information specific to the corporate bond */ - @JsonProperty("additional_info") - @ExcludeMissing - fun _additionalInfo(): JsonValue = additionalInfo + fun toBuilder() = Builder().from(this) - /** - * ISIN code of the corporate bond - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun isin(): Optional = isin.getOptional("isin") + companion object { - /** - * Name of the corporate bond - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun name(): Optional = name.getOptional("name") + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } - /** - * Number of units held - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun units(): Optional = units.getOptional("units") + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { - /** - * Current market value of the holding - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun value(): Optional = value.getOptional("value") + private var closeUnits: JsonField = JsonMissing.of() + private var openUnits: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() - /** - * Returns the raw JSON value of [isin]. - * - * Unlike [isin], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("isin") @ExcludeMissing fun _isin(): JsonField = isin + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + closeUnits = additionalInfo.closeUnits + openUnits = additionalInfo.openUnits + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() + } - /** - * Returns the raw JSON value of [name]. - * - * Unlike [name], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + /** Closing balance units for the statement period (beta) */ + fun closeUnits(closeUnits: Float?) = + closeUnits(JsonField.ofNullable(closeUnits)) - /** - * Returns the raw JSON value of [units]. - * - * Unlike [units], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units + /** + * Alias for [Builder.closeUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun closeUnits(closeUnits: Float) = closeUnits(closeUnits as Float?) - /** - * Returns the raw JSON value of [value]. - * - * Unlike [value], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + /** + * Alias for calling [Builder.closeUnits] with `closeUnits.orElse(null)`. + */ + fun closeUnits(closeUnits: Optional) = + closeUnits(closeUnits.getOrNull()) - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** + * Sets [Builder.closeUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.closeUnits] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun closeUnits(closeUnits: JsonField) = apply { + this.closeUnits = closeUnits + } - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + /** Opening balance units for the statement period (beta) */ + fun openUnits(openUnits: Float?) = + openUnits(JsonField.ofNullable(openUnits)) - fun toBuilder() = Builder().from(this) + /** + * Alias for [Builder.openUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun openUnits(openUnits: Float) = openUnits(openUnits as Float?) - companion object { + /** Alias for calling [Builder.openUnits] with `openUnits.orElse(null)`. */ + fun openUnits(openUnits: Optional) = openUnits(openUnits.getOrNull()) - /** - * Returns a mutable builder for constructing an instance of [CorporateBond]. - */ - @JvmStatic fun builder() = Builder() - } + /** + * Sets [Builder.openUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.openUnits] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun openUnits(openUnits: JsonField) = apply { + this.openUnits = openUnits + } - /** A builder for [CorporateBond]. */ - class Builder internal constructor() { + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - private var additionalInfo: JsonValue = JsonMissing.of() - private var isin: JsonField = JsonMissing.of() - private var name: JsonField = JsonMissing.of() - private var units: JsonField = JsonMissing.of() - private var value: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - @JvmSynthetic - internal fun from(corporateBond: CorporateBond) = apply { - additionalInfo = corporateBond.additionalInfo - isin = corporateBond.isin - name = corporateBond.name - units = corporateBond.units - value = corporateBond.value - additionalProperties = corporateBond.additionalProperties.toMutableMap() + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + closeUnits, + openUnits, + additionalProperties.toMutableMap(), + ) } - /** Additional information specific to the corporate bond */ - fun additionalInfo(additionalInfo: JsonValue) = apply { - this.additionalInfo = additionalInfo + private var validated: Boolean = false + + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } + + closeUnits() + openUnits() + validated = true } - /** ISIN code of the corporate bond */ - fun isin(isin: String) = isin(JsonField.of(isin)) + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } /** - * Sets [Builder.isin] to an arbitrary JSON value. + * Returns a score indicating how many valid values are contained in this object + * recursively. * - * You should usually call [Builder.isin] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * Used for best match union deserialization. */ - fun isin(isin: JsonField) = apply { this.isin = isin } + @JvmSynthetic + internal fun validity(): Int = + (if (closeUnits.asKnown().isPresent) 1 else 0) + + (if (openUnits.asKnown().isPresent) 1 else 0) - /** Name of the corporate bond */ - fun name(name: String) = name(JsonField.of(name)) + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - /** - * Sets [Builder.name] to an arbitrary JSON value. + return other is AdditionalInfo && + closeUnits == other.closeUnits && + openUnits == other.openUnits && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(closeUnits, openUnits, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{closeUnits=$closeUnits, openUnits=$openUnits, additionalProperties=$additionalProperties}" + } + + /** + * Unified transaction schema for all holding types (MF folios, equities, bonds, + * etc.) + */ + class Transaction + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val amount: JsonField, + private val balance: JsonField, + private val date: JsonField, + private val description: JsonField, + private val dividendRate: JsonField, + private val nav: JsonField, + private val type: JsonField, + private val units: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("amount") + @ExcludeMissing + amount: JsonField = JsonMissing.of(), + @JsonProperty("balance") + @ExcludeMissing + balance: JsonField = JsonMissing.of(), + @JsonProperty("date") + @ExcludeMissing + date: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("dividend_rate") + @ExcludeMissing + dividendRate: JsonField = JsonMissing.of(), + @JsonProperty("nav") + @ExcludeMissing + nav: JsonField = JsonMissing.of(), + @JsonProperty("type") + @ExcludeMissing + type: JsonField = JsonMissing.of(), + @JsonProperty("units") + @ExcludeMissing + units: JsonField = JsonMissing.of(), + ) : this( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + mutableMapOf(), + ) + + /** + * Additional transaction-specific fields that vary by source * - * You should usually call [Builder.name] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). */ - fun name(name: JsonField) = apply { this.name = name } + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") - /** Number of units held */ - fun units(units: Float) = units(JsonField.of(units)) + /** + * Transaction amount in currency (computed from units × price/NAV) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") /** - * Sets [Builder.units] to an arbitrary JSON value. + * Balance units after transaction * - * You should usually call [Builder.units] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). */ - fun units(units: JsonField) = apply { this.units = units } + fun balance(): Optional = balance.getOptional("balance") - /** Current market value of the holding */ - fun value(value: Float) = value(JsonField.of(value)) + /** + * Transaction date (YYYY-MM-DD) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun date(): Optional = date.getOptional("date") /** - * Sets [Builder.value] to an arbitrary JSON value. + * Transaction description/particulars * - * You should usually call [Builder.value] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). */ - fun value(value: JsonField) = apply { this.value = value } + fun description(): Optional = description.getOptional("description") - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * Dividend rate (for DIVIDEND_PAYOUT transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun dividendRate(): Optional = dividendRate.getOptional("dividend_rate") - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + /** + * NAV/price per unit on transaction date + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun nav(): Optional = nav.getOptional("nav") - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) - } + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun type(): Optional = type.getOptional("type") - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } + /** + * Number of units involved in transaction + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun units(): Optional = units.getOptional("units") - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo /** - * Returns an immutable instance of [CorporateBond]. + * Returns the raw JSON value of [amount]. * - * Further updates to this [Builder] will not mutate the returned instance. + * Unlike [amount], this method doesn't throw if the JSON field has an + * unexpected type. */ - fun build(): CorporateBond = - CorporateBond( - additionalInfo, - isin, - name, - units, - value, - additionalProperties.toMutableMap(), - ) - } + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount - private var validated: Boolean = false + /** + * Returns the raw JSON value of [balance]. + * + * Unlike [balance], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("balance") + @ExcludeMissing + fun _balance(): JsonField = balance - fun validate(): CorporateBond = apply { - if (validated) { - return@apply - } + /** + * Returns the raw JSON value of [date]. + * + * Unlike [date], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date - isin() - name() - units() - value() - validated = true - } + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + /** + * Returns the raw JSON value of [dividendRate]. + * + * Unlike [dividendRate], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("dividend_rate") + @ExcludeMissing + fun _dividendRate(): JsonField = dividendRate - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (isin.asKnown().isPresent) 1 else 0) + - (if (name.asKnown().isPresent) 1 else 0) + - (if (units.asKnown().isPresent) 1 else 0) + - (if (value.asKnown().isPresent) 1 else 0) + /** + * Returns the raw JSON value of [nav]. + * + * Unlike [nav], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("nav") @ExcludeMissing fun _nav(): JsonField = nav - override fun equals(other: Any?): Boolean { - if (this === other) { - return true + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [units]. + * + * Unlike [units], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) } - return other is CorporateBond && - additionalInfo == other.additionalInfo && - isin == other.isin && - name == other.name && - units == other.units && - value == other.value && - additionalProperties == other.additionalProperties - } + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - private val hashCode: Int by lazy { - Objects.hash(additionalInfo, isin, name, units, value, additionalProperties) - } + fun toBuilder() = Builder().from(this) - override fun hashCode(): Int = hashCode + companion object { - override fun toString() = - "CorporateBond{additionalInfo=$additionalInfo, isin=$isin, name=$name, units=$units, value=$value, additionalProperties=$additionalProperties}" - } + /** + * Returns a mutable builder for constructing an instance of [Transaction]. + */ + @JvmStatic fun builder() = Builder() + } - class DematMutualFund - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val additionalInfo: JsonValue, - private val isin: JsonField, - private val name: JsonField, - private val units: JsonField, - private val value: JsonField, - private val additionalProperties: MutableMap, - ) { + /** A builder for [Transaction]. */ + class Builder internal constructor() { + + private var additionalInfo: JsonField = JsonMissing.of() + private var amount: JsonField = JsonMissing.of() + private var balance: JsonField = JsonMissing.of() + private var date: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var dividendRate: JsonField = JsonMissing.of() + private var nav: JsonField = JsonMissing.of() + private var type: JsonField = JsonMissing.of() + private var units: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(transaction: Transaction) = apply { + additionalInfo = transaction.additionalInfo + amount = transaction.amount + balance = transaction.balance + date = transaction.date + description = transaction.description + dividendRate = transaction.dividendRate + nav = transaction.nav + type = transaction.type + units = transaction.units + additionalProperties = transaction.additionalProperties.toMutableMap() + } - @JsonCreator - private constructor( - @JsonProperty("additional_info") - @ExcludeMissing - additionalInfo: JsonValue = JsonMissing.of(), - @JsonProperty("isin") - @ExcludeMissing - isin: JsonField = JsonMissing.of(), - @JsonProperty("name") - @ExcludeMissing - name: JsonField = JsonMissing.of(), - @JsonProperty("units") - @ExcludeMissing - units: JsonField = JsonMissing.of(), - @JsonProperty("value") - @ExcludeMissing - value: JsonField = JsonMissing.of(), - ) : this(additionalInfo, isin, name, units, value, mutableMapOf()) + /** Additional transaction-specific fields that vary by source */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) - /** Additional information specific to the mutual fund */ - @JsonProperty("additional_info") - @ExcludeMissing - fun _additionalInfo(): JsonValue = additionalInfo + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } - /** - * ISIN code of the mutual fund - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun isin(): Optional = isin.getOptional("isin") + /** Transaction amount in currency (computed from units × price/NAV) */ + fun amount(amount: Float?) = amount(JsonField.ofNullable(amount)) - /** - * Name of the mutual fund - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun name(): Optional = name.getOptional("name") + /** + * Alias for [Builder.amount]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun amount(amount: Float) = amount(amount as Float?) - /** - * Number of units held - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun units(): Optional = units.getOptional("units") + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) - /** - * Current market value of the holding - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun value(): Optional = value.getOptional("value") + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } - /** - * Returns the raw JSON value of [isin]. - * - * Unlike [isin], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("isin") @ExcludeMissing fun _isin(): JsonField = isin + /** Balance units after transaction */ + fun balance(balance: Float) = balance(JsonField.of(balance)) - /** - * Returns the raw JSON value of [name]. - * - * Unlike [name], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + /** + * Sets [Builder.balance] to an arbitrary JSON value. + * + * You should usually call [Builder.balance] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun balance(balance: JsonField) = apply { this.balance = balance } - /** - * Returns the raw JSON value of [units]. - * - * Unlike [units], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units + /** Transaction date (YYYY-MM-DD) */ + fun date(date: LocalDate) = date(JsonField.of(date)) - /** - * Returns the raw JSON value of [value]. - * - * Unlike [value], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + /** + * Sets [Builder.date] to an arbitrary JSON value. + * + * You should usually call [Builder.date] with a well-typed [LocalDate] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun date(date: JsonField) = apply { this.date = date } - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** Transaction description/particulars */ + fun description(description: String) = + description(JsonField.of(description)) - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } - fun toBuilder() = Builder().from(this) + /** Dividend rate (for DIVIDEND_PAYOUT transactions) */ + fun dividendRate(dividendRate: Float?) = + dividendRate(JsonField.ofNullable(dividendRate)) - companion object { + /** + * Alias for [Builder.dividendRate]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun dividendRate(dividendRate: Float) = dividendRate(dividendRate as Float?) - /** - * Returns a mutable builder for constructing an instance of [DematMutualFund]. - */ - @JvmStatic fun builder() = Builder() - } + /** + * Alias for calling [Builder.dividendRate] with + * `dividendRate.orElse(null)`. + */ + fun dividendRate(dividendRate: Optional) = + dividendRate(dividendRate.getOrNull()) - /** A builder for [DematMutualFund]. */ - class Builder internal constructor() { + /** + * Sets [Builder.dividendRate] to an arbitrary JSON value. + * + * You should usually call [Builder.dividendRate] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun dividendRate(dividendRate: JsonField) = apply { + this.dividendRate = dividendRate + } - private var additionalInfo: JsonValue = JsonMissing.of() - private var isin: JsonField = JsonMissing.of() - private var name: JsonField = JsonMissing.of() - private var units: JsonField = JsonMissing.of() - private var value: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + /** NAV/price per unit on transaction date */ + fun nav(nav: Float?) = nav(JsonField.ofNullable(nav)) - @JvmSynthetic - internal fun from(dematMutualFund: DematMutualFund) = apply { - additionalInfo = dematMutualFund.additionalInfo - isin = dematMutualFund.isin - name = dematMutualFund.name - units = dematMutualFund.units - value = dematMutualFund.value - additionalProperties = dematMutualFund.additionalProperties.toMutableMap() - } + /** + * Alias for [Builder.nav]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun nav(nav: Float) = nav(nav as Float?) - /** Additional information specific to the mutual fund */ - fun additionalInfo(additionalInfo: JsonValue) = apply { - this.additionalInfo = additionalInfo - } + /** Alias for calling [Builder.nav] with `nav.orElse(null)`. */ + fun nav(nav: Optional) = nav(nav.getOrNull()) - /** ISIN code of the mutual fund */ - fun isin(isin: String) = isin(JsonField.of(isin)) + /** + * Sets [Builder.nav] to an arbitrary JSON value. + * + * You should usually call [Builder.nav] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun nav(nav: JsonField) = apply { this.nav = nav } - /** - * Sets [Builder.isin] to an arbitrary JSON value. - * - * You should usually call [Builder.isin] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun isin(isin: JsonField) = apply { this.isin = isin } + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, + * DIVIDEND_PAYOUT, DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, + * STT_TAX, MISC, REVERSAL, UNKNOWN. + */ + fun type(type: Type) = type(JsonField.of(type)) - /** Name of the mutual fund */ - fun name(name: String) = name(JsonField.of(name)) + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } - /** - * Sets [Builder.name] to an arbitrary JSON value. - * - * You should usually call [Builder.name] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun name(name: JsonField) = apply { this.name = name } + /** Number of units involved in transaction */ + fun units(units: Float) = units(JsonField.of(units)) - /** Number of units held */ - fun units(units: Float) = units(JsonField.of(units)) + /** + * Sets [Builder.units] to an arbitrary JSON value. + * + * You should usually call [Builder.units] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun units(units: JsonField) = apply { this.units = units } - /** - * Sets [Builder.units] to an arbitrary JSON value. - * - * You should usually call [Builder.units] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun units(units: JsonField) = apply { this.units = units } + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - /** Current market value of the holding */ - fun value(value: Float) = value(JsonField.of(value)) + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - /** - * Sets [Builder.value] to an arbitrary JSON value. - * - * You should usually call [Builder.value] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun value(value: JsonField) = apply { this.value = value } + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Transaction]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Transaction = + Transaction( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + additionalProperties.toMutableMap(), + ) } - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) + private var validated: Boolean = false + + fun validate(): Transaction = apply { + if (validated) { + return@apply } - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) + additionalInfo().ifPresent { it.validate() } + amount() + balance() + date() + description() + dividendRate() + nav() + type().ifPresent { it.validate() } + units() + validated = true } - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } /** - * Returns an immutable instance of [DematMutualFund]. + * Returns a score indicating how many valid values are contained in this object + * recursively. * - * Further updates to this [Builder] will not mutate the returned instance. + * Used for best match union deserialization. */ - fun build(): DematMutualFund = - DematMutualFund( - additionalInfo, - isin, - name, - units, - value, - additionalProperties.toMutableMap(), + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (amount.asKnown().isPresent) 1 else 0) + + (if (balance.asKnown().isPresent) 1 else 0) + + (if (date.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (if (dividendRate.asKnown().isPresent) 1 else 0) + + (if (nav.asKnown().isPresent) 1 else 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (units.asKnown().isPresent) 1 else 0) + + /** Additional transaction-specific fields that vary by source */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val capitalWithdrawal: JsonField, + private val credit: JsonField, + private val debit: JsonField, + private val incomeDistribution: JsonField, + private val orderNo: JsonField, + private val price: JsonField, + private val stampDuty: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("capital_withdrawal") + @ExcludeMissing + capitalWithdrawal: JsonField = JsonMissing.of(), + @JsonProperty("credit") + @ExcludeMissing + credit: JsonField = JsonMissing.of(), + @JsonProperty("debit") + @ExcludeMissing + debit: JsonField = JsonMissing.of(), + @JsonProperty("income_distribution") + @ExcludeMissing + incomeDistribution: JsonField = JsonMissing.of(), + @JsonProperty("order_no") + @ExcludeMissing + orderNo: JsonField = JsonMissing.of(), + @JsonProperty("price") + @ExcludeMissing + price: JsonField = JsonMissing.of(), + @JsonProperty("stamp_duty") + @ExcludeMissing + stampDuty: JsonField = JsonMissing.of(), + ) : this( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + mutableMapOf(), ) - } - private var validated: Boolean = false + /** + * Capital withdrawal amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun capitalWithdrawal(): Optional = + capitalWithdrawal.getOptional("capital_withdrawal") - fun validate(): DematMutualFund = apply { - if (validated) { - return@apply - } + /** + * Units credited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun credit(): Optional = credit.getOptional("credit") - isin() - name() - units() - value() - validated = true - } + /** + * Units debited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun debit(): Optional = debit.getOptional("debit") - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + /** + * Income distribution amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun incomeDistribution(): Optional = + incomeDistribution.getOptional("income_distribution") - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (isin.asKnown().isPresent) 1 else 0) + - (if (name.asKnown().isPresent) 1 else 0) + - (if (units.asKnown().isPresent) 1 else 0) + - (if (value.asKnown().isPresent) 1 else 0) + /** + * Order/transaction reference number (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun orderNo(): Optional = orderNo.getOptional("order_no") - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** + * Price per unit (NSDL/CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun price(): Optional = price.getOptional("price") - return other is DematMutualFund && - additionalInfo == other.additionalInfo && - isin == other.isin && - name == other.name && - units == other.units && - value == other.value && - additionalProperties == other.additionalProperties - } + /** + * Stamp duty charged + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun stampDuty(): Optional = stampDuty.getOptional("stamp_duty") - private val hashCode: Int by lazy { - Objects.hash(additionalInfo, isin, name, units, value, additionalProperties) - } + /** + * Returns the raw JSON value of [capitalWithdrawal]. + * + * Unlike [capitalWithdrawal], this method doesn't throw if the JSON field + * has an unexpected type. + */ + @JsonProperty("capital_withdrawal") + @ExcludeMissing + fun _capitalWithdrawal(): JsonField = capitalWithdrawal - override fun hashCode(): Int = hashCode + /** + * Returns the raw JSON value of [credit]. + * + * Unlike [credit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("credit") + @ExcludeMissing + fun _credit(): JsonField = credit - override fun toString() = - "DematMutualFund{additionalInfo=$additionalInfo, isin=$isin, name=$name, units=$units, value=$value, additionalProperties=$additionalProperties}" - } + /** + * Returns the raw JSON value of [debit]. + * + * Unlike [debit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("debit") + @ExcludeMissing + fun _debit(): JsonField = debit - class Equity - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val additionalInfo: JsonValue, - private val isin: JsonField, - private val name: JsonField, - private val units: JsonField, - private val value: JsonField, - private val additionalProperties: MutableMap, - ) { + /** + * Returns the raw JSON value of [incomeDistribution]. + * + * Unlike [incomeDistribution], this method doesn't throw if the JSON field + * has an unexpected type. + */ + @JsonProperty("income_distribution") + @ExcludeMissing + fun _incomeDistribution(): JsonField = incomeDistribution - @JsonCreator - private constructor( - @JsonProperty("additional_info") - @ExcludeMissing - additionalInfo: JsonValue = JsonMissing.of(), - @JsonProperty("isin") - @ExcludeMissing - isin: JsonField = JsonMissing.of(), - @JsonProperty("name") - @ExcludeMissing - name: JsonField = JsonMissing.of(), - @JsonProperty("units") - @ExcludeMissing - units: JsonField = JsonMissing.of(), - @JsonProperty("value") - @ExcludeMissing - value: JsonField = JsonMissing.of(), - ) : this(additionalInfo, isin, name, units, value, mutableMapOf()) + /** + * Returns the raw JSON value of [orderNo]. + * + * Unlike [orderNo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("order_no") + @ExcludeMissing + fun _orderNo(): JsonField = orderNo - /** Additional information specific to the equity */ - @JsonProperty("additional_info") - @ExcludeMissing - fun _additionalInfo(): JsonValue = additionalInfo + /** + * Returns the raw JSON value of [price]. + * + * Unlike [price], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("price") + @ExcludeMissing + fun _price(): JsonField = price - /** - * ISIN code of the equity + /** + * Returns the raw JSON value of [stampDuty]. + * + * Unlike [stampDuty], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("stamp_duty") + @ExcludeMissing + fun _stampDuty(): JsonField = stampDuty + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { + + private var capitalWithdrawal: JsonField = JsonMissing.of() + private var credit: JsonField = JsonMissing.of() + private var debit: JsonField = JsonMissing.of() + private var incomeDistribution: JsonField = JsonMissing.of() + private var orderNo: JsonField = JsonMissing.of() + private var price: JsonField = JsonMissing.of() + private var stampDuty: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + capitalWithdrawal = additionalInfo.capitalWithdrawal + credit = additionalInfo.credit + debit = additionalInfo.debit + incomeDistribution = additionalInfo.incomeDistribution + orderNo = additionalInfo.orderNo + price = additionalInfo.price + stampDuty = additionalInfo.stampDuty + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() + } + + /** Capital withdrawal amount (CDSL MF transactions) */ + fun capitalWithdrawal(capitalWithdrawal: Float) = + capitalWithdrawal(JsonField.of(capitalWithdrawal)) + + /** + * Sets [Builder.capitalWithdrawal] to an arbitrary JSON value. + * + * You should usually call [Builder.capitalWithdrawal] with a well-typed + * [Float] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun capitalWithdrawal(capitalWithdrawal: JsonField) = apply { + this.capitalWithdrawal = capitalWithdrawal + } + + /** Units credited (demat transactions) */ + fun credit(credit: Float) = credit(JsonField.of(credit)) + + /** + * Sets [Builder.credit] to an arbitrary JSON value. + * + * You should usually call [Builder.credit] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun credit(credit: JsonField) = apply { this.credit = credit } + + /** Units debited (demat transactions) */ + fun debit(debit: Float) = debit(JsonField.of(debit)) + + /** + * Sets [Builder.debit] to an arbitrary JSON value. + * + * You should usually call [Builder.debit] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun debit(debit: JsonField) = apply { this.debit = debit } + + /** Income distribution amount (CDSL MF transactions) */ + fun incomeDistribution(incomeDistribution: Float) = + incomeDistribution(JsonField.of(incomeDistribution)) + + /** + * Sets [Builder.incomeDistribution] to an arbitrary JSON value. + * + * You should usually call [Builder.incomeDistribution] with a + * well-typed [Float] value instead. This method is primarily for + * setting the field to an undocumented or not yet supported value. + */ + fun incomeDistribution(incomeDistribution: JsonField) = apply { + this.incomeDistribution = incomeDistribution + } + + /** Order/transaction reference number (demat transactions) */ + fun orderNo(orderNo: String) = orderNo(JsonField.of(orderNo)) + + /** + * Sets [Builder.orderNo] to an arbitrary JSON value. + * + * You should usually call [Builder.orderNo] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun orderNo(orderNo: JsonField) = apply { + this.orderNo = orderNo + } + + /** Price per unit (NSDL/CDSL MF transactions) */ + fun price(price: Float) = price(JsonField.of(price)) + + /** + * Sets [Builder.price] to an arbitrary JSON value. + * + * You should usually call [Builder.price] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun price(price: JsonField) = apply { this.price = price } + + /** Stamp duty charged */ + fun stampDuty(stampDuty: Float) = stampDuty(JsonField.of(stampDuty)) + + /** + * Sets [Builder.stampDuty] to an arbitrary JSON value. + * + * You should usually call [Builder.stampDuty] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun stampDuty(stampDuty: JsonField) = apply { + this.stampDuty = stampDuty + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } + + capitalWithdrawal() + credit() + debit() + incomeDistribution() + orderNo() + price() + stampDuty() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (capitalWithdrawal.asKnown().isPresent) 1 else 0) + + (if (credit.asKnown().isPresent) 1 else 0) + + (if (debit.asKnown().isPresent) 1 else 0) + + (if (incomeDistribution.asKnown().isPresent) 1 else 0) + + (if (orderNo.asKnown().isPresent) 1 else 0) + + (if (price.asKnown().isPresent) 1 else 0) + + (if (stampDuty.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AdditionalInfo && + capitalWithdrawal == other.capitalWithdrawal && + credit == other.credit && + debit == other.debit && + incomeDistribution == other.incomeDistribution && + orderNo == other.orderNo && + price == other.price && + stampDuty == other.stampDuty && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{capitalWithdrawal=$capitalWithdrawal, credit=$credit, debit=$debit, incomeDistribution=$incomeDistribution, orderNo=$orderNo, price=$price, stampDuty=$stampDuty, additionalProperties=$additionalProperties}" + } + + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + */ + class Type + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data + * that doesn't match any known member, and you want to know that value. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value + + companion object { + + @JvmField val PURCHASE = of("PURCHASE") + + @JvmField val PURCHASE_SIP = of("PURCHASE_SIP") + + @JvmField val REDEMPTION = of("REDEMPTION") + + @JvmField val SWITCH_IN = of("SWITCH_IN") + + @JvmField val SWITCH_IN_MERGER = of("SWITCH_IN_MERGER") + + @JvmField val SWITCH_OUT = of("SWITCH_OUT") + + @JvmField val SWITCH_OUT_MERGER = of("SWITCH_OUT_MERGER") + + @JvmField val DIVIDEND_PAYOUT = of("DIVIDEND_PAYOUT") + + @JvmField val DIVIDEND_REINVEST = of("DIVIDEND_REINVEST") + + @JvmField val SEGREGATION = of("SEGREGATION") + + @JvmField val STAMP_DUTY_TAX = of("STAMP_DUTY_TAX") + + @JvmField val TDS_TAX = of("TDS_TAX") + + @JvmField val STT_TAX = of("STT_TAX") + + @JvmField val MISC = of("MISC") + + @JvmField val REVERSAL = of("REVERSAL") + + @JvmField val UNKNOWN = of("UNKNOWN") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API + * may respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + /** + * An enum member indicating that [Type] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always + * known or if you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PURCHASE -> Value.PURCHASE + PURCHASE_SIP -> Value.PURCHASE_SIP + REDEMPTION -> Value.REDEMPTION + SWITCH_IN -> Value.SWITCH_IN + SWITCH_IN_MERGER -> Value.SWITCH_IN_MERGER + SWITCH_OUT -> Value.SWITCH_OUT + SWITCH_OUT_MERGER -> Value.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Value.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Value.DIVIDEND_REINVEST + SEGREGATION -> Value.SEGREGATION + STAMP_DUTY_TAX -> Value.STAMP_DUTY_TAX + TDS_TAX -> Value.TDS_TAX + STT_TAX -> Value.STT_TAX + MISC -> Value.MISC + REVERSAL -> Value.REVERSAL + UNKNOWN -> Value.UNKNOWN + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always + * known and don't want to throw for the unknown case. + * + * @throws CasParserInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + PURCHASE -> Known.PURCHASE + PURCHASE_SIP -> Known.PURCHASE_SIP + REDEMPTION -> Known.REDEMPTION + SWITCH_IN -> Known.SWITCH_IN + SWITCH_IN_MERGER -> Known.SWITCH_IN_MERGER + SWITCH_OUT -> Known.SWITCH_OUT + SWITCH_OUT_MERGER -> Known.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Known.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Known.DIVIDEND_REINVEST + SEGREGATION -> Known.SEGREGATION + STAMP_DUTY_TAX -> Known.STAMP_DUTY_TAX + TDS_TAX -> Known.TDS_TAX + STT_TAX -> Known.STT_TAX + MISC -> Known.MISC + REVERSAL -> Known.REVERSAL + UNKNOWN -> Known.UNKNOWN + else -> throw CasParserInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily + * for debugging and generally doesn't throw. + * + * @throws CasParserInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CasParserInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Transaction && + additionalInfo == other.additionalInfo && + amount == other.amount && + balance == other.balance && + date == other.date && + description == other.description && + dividendRate == other.dividendRate && + nav == other.nav && + type == other.type && + units == other.units && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Transaction{additionalInfo=$additionalInfo, amount=$amount, balance=$balance, date=$date, description=$description, dividendRate=$dividendRate, nav=$nav, type=$type, units=$units, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Aif && + additionalInfo == other.additionalInfo && + isin == other.isin && + name == other.name && + transactions == other.transactions && + units == other.units && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + isin, + name, + transactions, + units, + value, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Aif{additionalInfo=$additionalInfo, isin=$isin, name=$name, transactions=$transactions, units=$units, value=$value, additionalProperties=$additionalProperties}" + } + + class CorporateBond + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val isin: JsonField, + private val name: JsonField, + private val transactions: JsonField>, + private val units: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("isin") + @ExcludeMissing + isin: JsonField = JsonMissing.of(), + @JsonProperty("name") + @ExcludeMissing + name: JsonField = JsonMissing.of(), + @JsonProperty("transactions") + @ExcludeMissing + transactions: JsonField> = JsonMissing.of(), + @JsonProperty("units") + @ExcludeMissing + units: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(additionalInfo, isin, name, transactions, units, value, mutableMapOf()) + + /** + * Additional information specific to the corporate bond + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") + + /** + * ISIN code of the corporate bond * * @throws CasParserInvalidDataException if the JSON field has an unexpected type * (e.g. if the server responded with an unexpected value). @@ -2678,13 +3637,22 @@ private constructor( fun isin(): Optional = isin.getOptional("isin") /** - * Name of the equity + * Name of the corporate bond * * @throws CasParserInvalidDataException if the JSON field has an unexpected type * (e.g. if the server responded with an unexpected value). */ fun name(): Optional = name.getOptional("name") + /** + * List of transactions for this holding (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun transactions(): Optional> = + transactions.getOptional("transactions") + /** * Number of units held * @@ -2701,6 +3669,16 @@ private constructor( */ fun value(): Optional = value.getOptional("value") + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo + /** * Returns the raw JSON value of [isin]. * @@ -2717,6 +3695,16 @@ private constructor( */ @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + /** + * Returns the raw JSON value of [transactions]. + * + * Unlike [transactions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("transactions") + @ExcludeMissing + fun _transactions(): JsonField> = transactions + /** * Returns the raw JSON value of [units]. * @@ -2747,36 +3735,50 @@ private constructor( companion object { - /** Returns a mutable builder for constructing an instance of [Equity]. */ + /** + * Returns a mutable builder for constructing an instance of [CorporateBond]. + */ @JvmStatic fun builder() = Builder() } - /** A builder for [Equity]. */ + /** A builder for [CorporateBond]. */ class Builder internal constructor() { - private var additionalInfo: JsonValue = JsonMissing.of() + private var additionalInfo: JsonField = JsonMissing.of() private var isin: JsonField = JsonMissing.of() private var name: JsonField = JsonMissing.of() + private var transactions: JsonField>? = null private var units: JsonField = JsonMissing.of() private var value: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(equity: Equity) = apply { - additionalInfo = equity.additionalInfo - isin = equity.isin - name = equity.name - units = equity.units - value = equity.value - additionalProperties = equity.additionalProperties.toMutableMap() + internal fun from(corporateBond: CorporateBond) = apply { + additionalInfo = corporateBond.additionalInfo + isin = corporateBond.isin + name = corporateBond.name + transactions = corporateBond.transactions.map { it.toMutableList() } + units = corporateBond.units + value = corporateBond.value + additionalProperties = corporateBond.additionalProperties.toMutableMap() } - /** Additional information specific to the equity */ - fun additionalInfo(additionalInfo: JsonValue) = apply { + /** Additional information specific to the corporate bond */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) + + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { this.additionalInfo = additionalInfo } - /** ISIN code of the equity */ + /** ISIN code of the corporate bond */ fun isin(isin: String) = isin(JsonField.of(isin)) /** @@ -2788,7 +3790,7 @@ private constructor( */ fun isin(isin: JsonField) = apply { this.isin = isin } - /** Name of the equity */ + /** Name of the corporate bond */ fun name(name: String) = name(JsonField.of(name)) /** @@ -2800,6 +3802,33 @@ private constructor( */ fun name(name: JsonField) = apply { this.name = name } + /** List of transactions for this holding (beta) */ + fun transactions(transactions: List) = + transactions(JsonField.of(transactions)) + + /** + * Sets [Builder.transactions] to an arbitrary JSON value. + * + * You should usually call [Builder.transactions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun transactions(transactions: JsonField>) = apply { + this.transactions = transactions.map { it.toMutableList() } + } + + /** + * Adds a single [Transaction] to [transactions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTransaction(transaction: Transaction) = apply { + transactions = + (transactions ?: JsonField.of(mutableListOf())).also { + checkKnown("transactions", it).add(transaction) + } + } + /** Number of units held */ fun units(units: Float) = units(JsonField.of(units)) @@ -2847,15 +3876,16 @@ private constructor( } /** - * Returns an immutable instance of [Equity]. + * Returns an immutable instance of [CorporateBond]. * * Further updates to this [Builder] will not mutate the returned instance. */ - fun build(): Equity = - Equity( + fun build(): CorporateBond = + CorporateBond( additionalInfo, isin, name, + (transactions ?: JsonMissing.of()).map { it.toImmutable() }, units, value, additionalProperties.toMutableMap(), @@ -2864,13 +3894,15 @@ private constructor( private var validated: Boolean = false - fun validate(): Equity = apply { + fun validate(): CorporateBond = apply { if (validated) { return@apply } + additionalInfo().ifPresent { it.validate() } isin() name() + transactions().ifPresent { it.forEach { it.validate() } } units() value() validated = true @@ -2892,3571 +3924,10819 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (if (isin.asKnown().isPresent) 1 else 0) + + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (isin.asKnown().isPresent) 1 else 0) + (if (name.asKnown().isPresent) 1 else 0) + + (transactions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + (if (units.asKnown().isPresent) 1 else 0) + (if (value.asKnown().isPresent) 1 else 0) - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** Additional information specific to the corporate bond */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val closeUnits: JsonField, + private val openUnits: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("close_units") + @ExcludeMissing + closeUnits: JsonField = JsonMissing.of(), + @JsonProperty("open_units") + @ExcludeMissing + openUnits: JsonField = JsonMissing.of(), + ) : this(closeUnits, openUnits, mutableMapOf()) - return other is Equity && - additionalInfo == other.additionalInfo && - isin == other.isin && - name == other.name && - units == other.units && - value == other.value && - additionalProperties == other.additionalProperties - } + /** + * Closing balance units for the statement period (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun closeUnits(): Optional = closeUnits.getOptional("close_units") - private val hashCode: Int by lazy { - Objects.hash(additionalInfo, isin, name, units, value, additionalProperties) - } + /** + * Opening balance units for the statement period (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun openUnits(): Optional = openUnits.getOptional("open_units") - override fun hashCode(): Int = hashCode + /** + * Returns the raw JSON value of [closeUnits]. + * + * Unlike [closeUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("close_units") + @ExcludeMissing + fun _closeUnits(): JsonField = closeUnits - override fun toString() = - "Equity{additionalInfo=$additionalInfo, isin=$isin, name=$name, units=$units, value=$value, additionalProperties=$additionalProperties}" - } + /** + * Returns the raw JSON value of [openUnits]. + * + * Unlike [openUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("open_units") + @ExcludeMissing + fun _openUnits(): JsonField = openUnits - class GovernmentSecurity - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val additionalInfo: JsonValue, - private val isin: JsonField, - private val name: JsonField, - private val units: JsonField, - private val value: JsonField, - private val additionalProperties: MutableMap, - ) { + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - @JsonCreator - private constructor( - @JsonProperty("additional_info") + @JsonAnyGetter @ExcludeMissing - additionalInfo: JsonValue = JsonMissing.of(), - @JsonProperty("isin") - @ExcludeMissing - isin: JsonField = JsonMissing.of(), - @JsonProperty("name") - @ExcludeMissing - name: JsonField = JsonMissing.of(), - @JsonProperty("units") - @ExcludeMissing - units: JsonField = JsonMissing.of(), - @JsonProperty("value") - @ExcludeMissing - value: JsonField = JsonMissing.of(), - ) : this(additionalInfo, isin, name, units, value, mutableMapOf()) + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - /** Additional information specific to the government security */ - @JsonProperty("additional_info") - @ExcludeMissing - fun _additionalInfo(): JsonValue = additionalInfo + fun toBuilder() = Builder().from(this) - /** - * ISIN code of the government security - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun isin(): Optional = isin.getOptional("isin") + companion object { - /** - * Name of the government security - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun name(): Optional = name.getOptional("name") + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } - /** - * Number of units held - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun units(): Optional = units.getOptional("units") + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { - /** - * Current market value of the holding - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun value(): Optional = value.getOptional("value") + private var closeUnits: JsonField = JsonMissing.of() + private var openUnits: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() - /** - * Returns the raw JSON value of [isin]. - * - * Unlike [isin], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("isin") @ExcludeMissing fun _isin(): JsonField = isin + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + closeUnits = additionalInfo.closeUnits + openUnits = additionalInfo.openUnits + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() + } - /** - * Returns the raw JSON value of [name]. - * - * Unlike [name], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + /** Closing balance units for the statement period (beta) */ + fun closeUnits(closeUnits: Float?) = + closeUnits(JsonField.ofNullable(closeUnits)) - /** - * Returns the raw JSON value of [units]. - * - * Unlike [units], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units + /** + * Alias for [Builder.closeUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun closeUnits(closeUnits: Float) = closeUnits(closeUnits as Float?) - /** - * Returns the raw JSON value of [value]. - * - * Unlike [value], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + /** + * Alias for calling [Builder.closeUnits] with `closeUnits.orElse(null)`. + */ + fun closeUnits(closeUnits: Optional) = + closeUnits(closeUnits.getOrNull()) - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** + * Sets [Builder.closeUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.closeUnits] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun closeUnits(closeUnits: JsonField) = apply { + this.closeUnits = closeUnits + } - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + /** Opening balance units for the statement period (beta) */ + fun openUnits(openUnits: Float?) = + openUnits(JsonField.ofNullable(openUnits)) - fun toBuilder() = Builder().from(this) + /** + * Alias for [Builder.openUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun openUnits(openUnits: Float) = openUnits(openUnits as Float?) - companion object { + /** Alias for calling [Builder.openUnits] with `openUnits.orElse(null)`. */ + fun openUnits(openUnits: Optional) = openUnits(openUnits.getOrNull()) - /** - * Returns a mutable builder for constructing an instance of - * [GovernmentSecurity]. - */ - @JvmStatic fun builder() = Builder() - } + /** + * Sets [Builder.openUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.openUnits] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun openUnits(openUnits: JsonField) = apply { + this.openUnits = openUnits + } - /** A builder for [GovernmentSecurity]. */ - class Builder internal constructor() { + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - private var additionalInfo: JsonValue = JsonMissing.of() - private var isin: JsonField = JsonMissing.of() - private var name: JsonField = JsonMissing.of() - private var units: JsonField = JsonMissing.of() - private var value: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - @JvmSynthetic - internal fun from(governmentSecurity: GovernmentSecurity) = apply { - additionalInfo = governmentSecurity.additionalInfo - isin = governmentSecurity.isin - name = governmentSecurity.name - units = governmentSecurity.units - value = governmentSecurity.value - additionalProperties = - governmentSecurity.additionalProperties.toMutableMap() + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + closeUnits, + openUnits, + additionalProperties.toMutableMap(), + ) } - /** Additional information specific to the government security */ - fun additionalInfo(additionalInfo: JsonValue) = apply { - this.additionalInfo = additionalInfo + private var validated: Boolean = false + + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } + + closeUnits() + openUnits() + validated = true } - /** ISIN code of the government security */ - fun isin(isin: String) = isin(JsonField.of(isin)) + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } /** - * Sets [Builder.isin] to an arbitrary JSON value. + * Returns a score indicating how many valid values are contained in this object + * recursively. * - * You should usually call [Builder.isin] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * Used for best match union deserialization. */ - fun isin(isin: JsonField) = apply { this.isin = isin } + @JvmSynthetic + internal fun validity(): Int = + (if (closeUnits.asKnown().isPresent) 1 else 0) + + (if (openUnits.asKnown().isPresent) 1 else 0) - /** Name of the government security */ - fun name(name: String) = name(JsonField.of(name)) + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AdditionalInfo && + closeUnits == other.closeUnits && + openUnits == other.openUnits && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(closeUnits, openUnits, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{closeUnits=$closeUnits, openUnits=$openUnits, additionalProperties=$additionalProperties}" + } + + /** + * Unified transaction schema for all holding types (MF folios, equities, bonds, + * etc.) + */ + class Transaction + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val amount: JsonField, + private val balance: JsonField, + private val date: JsonField, + private val description: JsonField, + private val dividendRate: JsonField, + private val nav: JsonField, + private val type: JsonField, + private val units: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("amount") + @ExcludeMissing + amount: JsonField = JsonMissing.of(), + @JsonProperty("balance") + @ExcludeMissing + balance: JsonField = JsonMissing.of(), + @JsonProperty("date") + @ExcludeMissing + date: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("dividend_rate") + @ExcludeMissing + dividendRate: JsonField = JsonMissing.of(), + @JsonProperty("nav") + @ExcludeMissing + nav: JsonField = JsonMissing.of(), + @JsonProperty("type") + @ExcludeMissing + type: JsonField = JsonMissing.of(), + @JsonProperty("units") + @ExcludeMissing + units: JsonField = JsonMissing.of(), + ) : this( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + mutableMapOf(), + ) /** - * Sets [Builder.name] to an arbitrary JSON value. + * Additional transaction-specific fields that vary by source * - * You should usually call [Builder.name] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). */ - fun name(name: JsonField) = apply { this.name = name } + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") - /** Number of units held */ - fun units(units: Float) = units(JsonField.of(units)) + /** + * Transaction amount in currency (computed from units × price/NAV) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") /** - * Sets [Builder.units] to an arbitrary JSON value. + * Balance units after transaction * - * You should usually call [Builder.units] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). */ - fun units(units: JsonField) = apply { this.units = units } + fun balance(): Optional = balance.getOptional("balance") - /** Current market value of the holding */ - fun value(value: Float) = value(JsonField.of(value)) + /** + * Transaction date (YYYY-MM-DD) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun date(): Optional = date.getOptional("date") /** - * Sets [Builder.value] to an arbitrary JSON value. + * Transaction description/particulars * - * You should usually call [Builder.value] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). */ - fun value(value: JsonField) = apply { this.value = value } + fun description(): Optional = description.getOptional("description") - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * Dividend rate (for DIVIDEND_PAYOUT transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun dividendRate(): Optional = dividendRate.getOptional("dividend_rate") - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + /** + * NAV/price per unit on transaction date + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun nav(): Optional = nav.getOptional("nav") - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) - } + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun type(): Optional = type.getOptional("type") - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } + /** + * Number of units involved in transaction + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun units(): Optional = units.getOptional("units") - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo /** - * Returns an immutable instance of [GovernmentSecurity]. + * Returns the raw JSON value of [amount]. * - * Further updates to this [Builder] will not mutate the returned instance. + * Unlike [amount], this method doesn't throw if the JSON field has an + * unexpected type. */ - fun build(): GovernmentSecurity = - GovernmentSecurity( - additionalInfo, - isin, - name, - units, - value, - additionalProperties.toMutableMap(), - ) - } + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount - private var validated: Boolean = false + /** + * Returns the raw JSON value of [balance]. + * + * Unlike [balance], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("balance") + @ExcludeMissing + fun _balance(): JsonField = balance - fun validate(): GovernmentSecurity = apply { - if (validated) { - return@apply - } + /** + * Returns the raw JSON value of [date]. + * + * Unlike [date], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date - isin() - name() - units() - value() - validated = true - } + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + /** + * Returns the raw JSON value of [dividendRate]. + * + * Unlike [dividendRate], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("dividend_rate") + @ExcludeMissing + fun _dividendRate(): JsonField = dividendRate - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (isin.asKnown().isPresent) 1 else 0) + - (if (name.asKnown().isPresent) 1 else 0) + - (if (units.asKnown().isPresent) 1 else 0) + - (if (value.asKnown().isPresent) 1 else 0) + /** + * Returns the raw JSON value of [nav]. + * + * Unlike [nav], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("nav") @ExcludeMissing fun _nav(): JsonField = nav - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type - return other is GovernmentSecurity && - additionalInfo == other.additionalInfo && - isin == other.isin && - name == other.name && - units == other.units && - value == other.value && - additionalProperties == other.additionalProperties - } + /** + * Returns the raw JSON value of [units]. + * + * Unlike [units], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units - private val hashCode: Int by lazy { - Objects.hash(additionalInfo, isin, name, units, value, additionalProperties) - } + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - override fun hashCode(): Int = hashCode + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - override fun toString() = - "GovernmentSecurity{additionalInfo=$additionalInfo, isin=$isin, name=$name, units=$units, value=$value, additionalProperties=$additionalProperties}" - } + fun toBuilder() = Builder().from(this) - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + companion object { - return other is Holdings && - aifs == other.aifs && - corporateBonds == other.corporateBonds && - dematMutualFunds == other.dematMutualFunds && - equities == other.equities && - governmentSecurities == other.governmentSecurities && - additionalProperties == other.additionalProperties - } + /** + * Returns a mutable builder for constructing an instance of [Transaction]. + */ + @JvmStatic fun builder() = Builder() + } - private val hashCode: Int by lazy { - Objects.hash( - aifs, - corporateBonds, - dematMutualFunds, - equities, - governmentSecurities, - additionalProperties, - ) - } + /** A builder for [Transaction]. */ + class Builder internal constructor() { + + private var additionalInfo: JsonField = JsonMissing.of() + private var amount: JsonField = JsonMissing.of() + private var balance: JsonField = JsonMissing.of() + private var date: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var dividendRate: JsonField = JsonMissing.of() + private var nav: JsonField = JsonMissing.of() + private var type: JsonField = JsonMissing.of() + private var units: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(transaction: Transaction) = apply { + additionalInfo = transaction.additionalInfo + amount = transaction.amount + balance = transaction.balance + date = transaction.date + description = transaction.description + dividendRate = transaction.dividendRate + nav = transaction.nav + type = transaction.type + units = transaction.units + additionalProperties = transaction.additionalProperties.toMutableMap() + } - override fun hashCode(): Int = hashCode + /** Additional transaction-specific fields that vary by source */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) - override fun toString() = - "Holdings{aifs=$aifs, corporateBonds=$corporateBonds, dematMutualFunds=$dematMutualFunds, equities=$equities, governmentSecurities=$governmentSecurities, additionalProperties=$additionalProperties}" - } + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } - class LinkedHolder - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val name: JsonField, - private val pan: JsonField, - private val additionalProperties: MutableMap, - ) { + /** Transaction amount in currency (computed from units × price/NAV) */ + fun amount(amount: Float?) = amount(JsonField.ofNullable(amount)) - @JsonCreator - private constructor( - @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), - @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), - ) : this(name, pan, mutableMapOf()) + /** + * Alias for [Builder.amount]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun amount(amount: Float) = amount(amount as Float?) - /** - * Name of the account holder - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun name(): Optional = name.getOptional("name") + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) - /** - * PAN of the account holder - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun pan(): Optional = pan.getOptional("pan") + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } - /** - * Returns the raw JSON value of [name]. - * - * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + /** Balance units after transaction */ + fun balance(balance: Float) = balance(JsonField.of(balance)) - /** - * Returns the raw JSON value of [pan]. - * - * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + /** + * Sets [Builder.balance] to an arbitrary JSON value. + * + * You should usually call [Builder.balance] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun balance(balance: JsonField) = apply { this.balance = balance } - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** Transaction date (YYYY-MM-DD) */ + fun date(date: LocalDate) = date(JsonField.of(date)) - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + /** + * Sets [Builder.date] to an arbitrary JSON value. + * + * You should usually call [Builder.date] with a well-typed [LocalDate] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun date(date: JsonField) = apply { this.date = date } - fun toBuilder() = Builder().from(this) + /** Transaction description/particulars */ + fun description(description: String) = + description(JsonField.of(description)) - companion object { + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } - /** Returns a mutable builder for constructing an instance of [LinkedHolder]. */ - @JvmStatic fun builder() = Builder() - } + /** Dividend rate (for DIVIDEND_PAYOUT transactions) */ + fun dividendRate(dividendRate: Float?) = + dividendRate(JsonField.ofNullable(dividendRate)) - /** A builder for [LinkedHolder]. */ - class Builder internal constructor() { + /** + * Alias for [Builder.dividendRate]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun dividendRate(dividendRate: Float) = dividendRate(dividendRate as Float?) - private var name: JsonField = JsonMissing.of() - private var pan: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + /** + * Alias for calling [Builder.dividendRate] with + * `dividendRate.orElse(null)`. + */ + fun dividendRate(dividendRate: Optional) = + dividendRate(dividendRate.getOrNull()) - @JvmSynthetic - internal fun from(linkedHolder: LinkedHolder) = apply { - name = linkedHolder.name - pan = linkedHolder.pan - additionalProperties = linkedHolder.additionalProperties.toMutableMap() - } + /** + * Sets [Builder.dividendRate] to an arbitrary JSON value. + * + * You should usually call [Builder.dividendRate] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun dividendRate(dividendRate: JsonField) = apply { + this.dividendRate = dividendRate + } - /** Name of the account holder */ - fun name(name: String) = name(JsonField.of(name)) + /** NAV/price per unit on transaction date */ + fun nav(nav: Float?) = nav(JsonField.ofNullable(nav)) - /** - * Sets [Builder.name] to an arbitrary JSON value. - * - * You should usually call [Builder.name] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun name(name: JsonField) = apply { this.name = name } + /** + * Alias for [Builder.nav]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun nav(nav: Float) = nav(nav as Float?) - /** PAN of the account holder */ - fun pan(pan: String) = pan(JsonField.of(pan)) + /** Alias for calling [Builder.nav] with `nav.orElse(null)`. */ + fun nav(nav: Optional) = nav(nav.getOrNull()) - /** - * Sets [Builder.pan] to an arbitrary JSON value. - * - * You should usually call [Builder.pan] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun pan(pan: JsonField) = apply { this.pan = pan } + /** + * Sets [Builder.nav] to an arbitrary JSON value. + * + * You should usually call [Builder.nav] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun nav(nav: JsonField) = apply { this.nav = nav } - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, + * DIVIDEND_PAYOUT, DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, + * STT_TAX, MISC, REVERSAL, UNKNOWN. + */ + fun type(type: Type) = type(JsonField.of(type)) - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) - } + /** Number of units involved in transaction */ + fun units(units: Float) = units(JsonField.of(units)) - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } + /** + * Sets [Builder.units] to an arbitrary JSON value. + * + * You should usually call [Builder.units] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun units(units: JsonField) = apply { this.units = units } - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - /** - * Returns an immutable instance of [LinkedHolder]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): LinkedHolder = - LinkedHolder(name, pan, additionalProperties.toMutableMap()) - } + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - private var validated: Boolean = false + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } - fun validate(): LinkedHolder = apply { - if (validated) { - return@apply - } + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } - name() - pan() - validated = true - } + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + /** + * Returns an immutable instance of [Transaction]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Transaction = + Transaction( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + additionalProperties.toMutableMap(), + ) + } - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (name.asKnown().isPresent) 1 else 0) + (if (pan.asKnown().isPresent) 1 else 0) + private var validated: Boolean = false - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + fun validate(): Transaction = apply { + if (validated) { + return@apply + } - return other is LinkedHolder && - name == other.name && - pan == other.pan && - additionalProperties == other.additionalProperties - } + additionalInfo().ifPresent { it.validate() } + amount() + balance() + date() + description() + dividendRate() + nav() + type().ifPresent { it.validate() } + units() + validated = true + } - private val hashCode: Int by lazy { Objects.hash(name, pan, additionalProperties) } + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } - override fun hashCode(): Int = hashCode + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (amount.asKnown().isPresent) 1 else 0) + + (if (balance.asKnown().isPresent) 1 else 0) + + (if (date.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (if (dividendRate.asKnown().isPresent) 1 else 0) + + (if (nav.asKnown().isPresent) 1 else 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (units.asKnown().isPresent) 1 else 0) + + /** Additional transaction-specific fields that vary by source */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val capitalWithdrawal: JsonField, + private val credit: JsonField, + private val debit: JsonField, + private val incomeDistribution: JsonField, + private val orderNo: JsonField, + private val price: JsonField, + private val stampDuty: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("capital_withdrawal") + @ExcludeMissing + capitalWithdrawal: JsonField = JsonMissing.of(), + @JsonProperty("credit") + @ExcludeMissing + credit: JsonField = JsonMissing.of(), + @JsonProperty("debit") + @ExcludeMissing + debit: JsonField = JsonMissing.of(), + @JsonProperty("income_distribution") + @ExcludeMissing + incomeDistribution: JsonField = JsonMissing.of(), + @JsonProperty("order_no") + @ExcludeMissing + orderNo: JsonField = JsonMissing.of(), + @JsonProperty("price") + @ExcludeMissing + price: JsonField = JsonMissing.of(), + @JsonProperty("stamp_duty") + @ExcludeMissing + stampDuty: JsonField = JsonMissing.of(), + ) : this( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + mutableMapOf(), + ) - override fun toString() = - "LinkedHolder{name=$name, pan=$pan, additionalProperties=$additionalProperties}" - } + /** + * Capital withdrawal amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun capitalWithdrawal(): Optional = + capitalWithdrawal.getOptional("capital_withdrawal") - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** + * Units credited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun credit(): Optional = credit.getOptional("credit") - return other is DematAccount && - additionalInfo == other.additionalInfo && - boId == other.boId && - clientId == other.clientId && - dematType == other.dematType && - dpId == other.dpId && - dpName == other.dpName && - holdings == other.holdings && - linkedHolders == other.linkedHolders && - value == other.value && - additionalProperties == other.additionalProperties - } + /** + * Units debited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun debit(): Optional = debit.getOptional("debit") - private val hashCode: Int by lazy { - Objects.hash( - additionalInfo, - boId, - clientId, - dematType, - dpId, - dpName, - holdings, - linkedHolders, - value, - additionalProperties, - ) - } + /** + * Income distribution amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun incomeDistribution(): Optional = + incomeDistribution.getOptional("income_distribution") - override fun hashCode(): Int = hashCode + /** + * Order/transaction reference number (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun orderNo(): Optional = orderNo.getOptional("order_no") - override fun toString() = - "DematAccount{additionalInfo=$additionalInfo, boId=$boId, clientId=$clientId, dematType=$dematType, dpId=$dpId, dpName=$dpName, holdings=$holdings, linkedHolders=$linkedHolders, value=$value, additionalProperties=$additionalProperties}" - } + /** + * Price per unit (NSDL/CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun price(): Optional = price.getOptional("price") - class Insurance - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val lifeInsurancePolicies: JsonField>, - private val additionalProperties: MutableMap, - ) { + /** + * Stamp duty charged + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun stampDuty(): Optional = stampDuty.getOptional("stamp_duty") - @JsonCreator - private constructor( - @JsonProperty("life_insurance_policies") - @ExcludeMissing - lifeInsurancePolicies: JsonField> = JsonMissing.of() - ) : this(lifeInsurancePolicies, mutableMapOf()) + /** + * Returns the raw JSON value of [capitalWithdrawal]. + * + * Unlike [capitalWithdrawal], this method doesn't throw if the JSON field + * has an unexpected type. + */ + @JsonProperty("capital_withdrawal") + @ExcludeMissing + fun _capitalWithdrawal(): JsonField = capitalWithdrawal - /** - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun lifeInsurancePolicies(): Optional> = - lifeInsurancePolicies.getOptional("life_insurance_policies") + /** + * Returns the raw JSON value of [credit]. + * + * Unlike [credit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("credit") + @ExcludeMissing + fun _credit(): JsonField = credit - /** - * Returns the raw JSON value of [lifeInsurancePolicies]. - * - * Unlike [lifeInsurancePolicies], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("life_insurance_policies") - @ExcludeMissing - fun _lifeInsurancePolicies(): JsonField> = lifeInsurancePolicies + /** + * Returns the raw JSON value of [debit]. + * + * Unlike [debit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("debit") + @ExcludeMissing + fun _debit(): JsonField = debit - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** + * Returns the raw JSON value of [incomeDistribution]. + * + * Unlike [incomeDistribution], this method doesn't throw if the JSON field + * has an unexpected type. + */ + @JsonProperty("income_distribution") + @ExcludeMissing + fun _incomeDistribution(): JsonField = incomeDistribution - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + /** + * Returns the raw JSON value of [orderNo]. + * + * Unlike [orderNo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("order_no") + @ExcludeMissing + fun _orderNo(): JsonField = orderNo - fun toBuilder() = Builder().from(this) + /** + * Returns the raw JSON value of [price]. + * + * Unlike [price], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("price") + @ExcludeMissing + fun _price(): JsonField = price - companion object { + /** + * Returns the raw JSON value of [stampDuty]. + * + * Unlike [stampDuty], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("stamp_duty") + @ExcludeMissing + fun _stampDuty(): JsonField = stampDuty - /** Returns a mutable builder for constructing an instance of [Insurance]. */ - @JvmStatic fun builder() = Builder() - } + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - /** A builder for [Insurance]. */ - class Builder internal constructor() { + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - private var lifeInsurancePolicies: JsonField>? = null - private var additionalProperties: MutableMap = mutableMapOf() + fun toBuilder() = Builder().from(this) - @JvmSynthetic - internal fun from(insurance: Insurance) = apply { - lifeInsurancePolicies = insurance.lifeInsurancePolicies.map { it.toMutableList() } - additionalProperties = insurance.additionalProperties.toMutableMap() - } + companion object { - fun lifeInsurancePolicies(lifeInsurancePolicies: List) = - lifeInsurancePolicies(JsonField.of(lifeInsurancePolicies)) + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } - /** - * Sets [Builder.lifeInsurancePolicies] to an arbitrary JSON value. - * - * You should usually call [Builder.lifeInsurancePolicies] with a well-typed - * `List` value instead. This method is primarily for setting the - * field to an undocumented or not yet supported value. - */ - fun lifeInsurancePolicies(lifeInsurancePolicies: JsonField>) = - apply { - this.lifeInsurancePolicies = lifeInsurancePolicies.map { it.toMutableList() } - } + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { + + private var capitalWithdrawal: JsonField = JsonMissing.of() + private var credit: JsonField = JsonMissing.of() + private var debit: JsonField = JsonMissing.of() + private var incomeDistribution: JsonField = JsonMissing.of() + private var orderNo: JsonField = JsonMissing.of() + private var price: JsonField = JsonMissing.of() + private var stampDuty: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + capitalWithdrawal = additionalInfo.capitalWithdrawal + credit = additionalInfo.credit + debit = additionalInfo.debit + incomeDistribution = additionalInfo.incomeDistribution + orderNo = additionalInfo.orderNo + price = additionalInfo.price + stampDuty = additionalInfo.stampDuty + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() + } + + /** Capital withdrawal amount (CDSL MF transactions) */ + fun capitalWithdrawal(capitalWithdrawal: Float) = + capitalWithdrawal(JsonField.of(capitalWithdrawal)) + + /** + * Sets [Builder.capitalWithdrawal] to an arbitrary JSON value. + * + * You should usually call [Builder.capitalWithdrawal] with a well-typed + * [Float] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun capitalWithdrawal(capitalWithdrawal: JsonField) = apply { + this.capitalWithdrawal = capitalWithdrawal + } + + /** Units credited (demat transactions) */ + fun credit(credit: Float) = credit(JsonField.of(credit)) + + /** + * Sets [Builder.credit] to an arbitrary JSON value. + * + * You should usually call [Builder.credit] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun credit(credit: JsonField) = apply { this.credit = credit } + + /** Units debited (demat transactions) */ + fun debit(debit: Float) = debit(JsonField.of(debit)) + + /** + * Sets [Builder.debit] to an arbitrary JSON value. + * + * You should usually call [Builder.debit] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun debit(debit: JsonField) = apply { this.debit = debit } + + /** Income distribution amount (CDSL MF transactions) */ + fun incomeDistribution(incomeDistribution: Float) = + incomeDistribution(JsonField.of(incomeDistribution)) + + /** + * Sets [Builder.incomeDistribution] to an arbitrary JSON value. + * + * You should usually call [Builder.incomeDistribution] with a + * well-typed [Float] value instead. This method is primarily for + * setting the field to an undocumented or not yet supported value. + */ + fun incomeDistribution(incomeDistribution: JsonField) = apply { + this.incomeDistribution = incomeDistribution + } + + /** Order/transaction reference number (demat transactions) */ + fun orderNo(orderNo: String) = orderNo(JsonField.of(orderNo)) + + /** + * Sets [Builder.orderNo] to an arbitrary JSON value. + * + * You should usually call [Builder.orderNo] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun orderNo(orderNo: JsonField) = apply { + this.orderNo = orderNo + } + + /** Price per unit (NSDL/CDSL MF transactions) */ + fun price(price: Float) = price(JsonField.of(price)) + + /** + * Sets [Builder.price] to an arbitrary JSON value. + * + * You should usually call [Builder.price] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun price(price: JsonField) = apply { this.price = price } + + /** Stamp duty charged */ + fun stampDuty(stampDuty: Float) = stampDuty(JsonField.of(stampDuty)) + + /** + * Sets [Builder.stampDuty] to an arbitrary JSON value. + * + * You should usually call [Builder.stampDuty] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun stampDuty(stampDuty: JsonField) = apply { + this.stampDuty = stampDuty + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties.toMutableMap(), + ) + } - /** - * Adds a single [LifeInsurancePolicy] to [lifeInsurancePolicies]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addLifeInsurancePolicy(lifeInsurancePolicy: LifeInsurancePolicy) = apply { - lifeInsurancePolicies = - (lifeInsurancePolicies ?: JsonField.of(mutableListOf())).also { - checkKnown("lifeInsurancePolicies", it).add(lifeInsurancePolicy) + private var validated: Boolean = false + + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } + + capitalWithdrawal() + credit() + debit() + incomeDistribution() + orderNo() + price() + stampDuty() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (capitalWithdrawal.asKnown().isPresent) 1 else 0) + + (if (credit.asKnown().isPresent) 1 else 0) + + (if (debit.asKnown().isPresent) 1 else 0) + + (if (incomeDistribution.asKnown().isPresent) 1 else 0) + + (if (orderNo.asKnown().isPresent) 1 else 0) + + (if (price.asKnown().isPresent) 1 else 0) + + (if (stampDuty.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AdditionalInfo && + capitalWithdrawal == other.capitalWithdrawal && + credit == other.credit && + debit == other.debit && + incomeDistribution == other.incomeDistribution && + orderNo == other.orderNo && + price == other.price && + stampDuty == other.stampDuty && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{capitalWithdrawal=$capitalWithdrawal, credit=$credit, debit=$debit, incomeDistribution=$incomeDistribution, orderNo=$orderNo, price=$price, stampDuty=$stampDuty, additionalProperties=$additionalProperties}" } - } - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + */ + class Type + @JsonCreator + private constructor(private val value: JsonField) : Enum { - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data + * that doesn't match any known member, and you want to know that value. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value - fun putAllAdditionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.putAll(additionalProperties) - } + companion object { - fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + @JvmField val PURCHASE = of("PURCHASE") - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + @JvmField val PURCHASE_SIP = of("PURCHASE_SIP") - /** - * Returns an immutable instance of [Insurance]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Insurance = - Insurance( - (lifeInsurancePolicies ?: JsonMissing.of()).map { it.toImmutable() }, - additionalProperties.toMutableMap(), - ) - } + @JvmField val REDEMPTION = of("REDEMPTION") - private var validated: Boolean = false + @JvmField val SWITCH_IN = of("SWITCH_IN") - fun validate(): Insurance = apply { - if (validated) { - return@apply - } + @JvmField val SWITCH_IN_MERGER = of("SWITCH_IN_MERGER") - lifeInsurancePolicies().ifPresent { it.forEach { it.validate() } } - validated = true - } + @JvmField val SWITCH_OUT = of("SWITCH_OUT") - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + @JvmField val SWITCH_OUT_MERGER = of("SWITCH_OUT_MERGER") - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (lifeInsurancePolicies.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + @JvmField val DIVIDEND_PAYOUT = of("DIVIDEND_PAYOUT") - class LifeInsurancePolicy - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val additionalInfo: JsonValue, - private val lifeAssured: JsonField, - private val policyName: JsonField, - private val policyNumber: JsonField, - private val premiumAmount: JsonField, - private val premiumFrequency: JsonField, - private val provider: JsonField, - private val status: JsonField, - private val sumAssured: JsonField, - private val additionalProperties: MutableMap, - ) { + @JvmField val DIVIDEND_REINVEST = of("DIVIDEND_REINVEST") - @JsonCreator - private constructor( - @JsonProperty("additional_info") - @ExcludeMissing - additionalInfo: JsonValue = JsonMissing.of(), - @JsonProperty("life_assured") - @ExcludeMissing - lifeAssured: JsonField = JsonMissing.of(), - @JsonProperty("policy_name") - @ExcludeMissing - policyName: JsonField = JsonMissing.of(), - @JsonProperty("policy_number") - @ExcludeMissing - policyNumber: JsonField = JsonMissing.of(), - @JsonProperty("premium_amount") - @ExcludeMissing - premiumAmount: JsonField = JsonMissing.of(), - @JsonProperty("premium_frequency") - @ExcludeMissing - premiumFrequency: JsonField = JsonMissing.of(), - @JsonProperty("provider") - @ExcludeMissing - provider: JsonField = JsonMissing.of(), - @JsonProperty("status") - @ExcludeMissing - status: JsonField = JsonMissing.of(), - @JsonProperty("sum_assured") - @ExcludeMissing - sumAssured: JsonField = JsonMissing.of(), - ) : this( - additionalInfo, - lifeAssured, - policyName, - policyNumber, - premiumAmount, - premiumFrequency, - provider, - status, - sumAssured, - mutableMapOf(), - ) + @JvmField val SEGREGATION = of("SEGREGATION") - /** Additional information specific to the policy */ - @JsonProperty("additional_info") - @ExcludeMissing - fun _additionalInfo(): JsonValue = additionalInfo + @JvmField val STAMP_DUTY_TAX = of("STAMP_DUTY_TAX") - /** - * Name of the life assured - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun lifeAssured(): Optional = lifeAssured.getOptional("life_assured") + @JvmField val TDS_TAX = of("TDS_TAX") - /** - * Name of the insurance policy - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun policyName(): Optional = policyName.getOptional("policy_name") + @JvmField val STT_TAX = of("STT_TAX") - /** - * Insurance policy number - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun policyNumber(): Optional = policyNumber.getOptional("policy_number") + @JvmField val MISC = of("MISC") - /** - * Premium amount - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun premiumAmount(): Optional = premiumAmount.getOptional("premium_amount") + @JvmField val REVERSAL = of("REVERSAL") - /** - * Frequency of premium payment (e.g., Annual, Monthly) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun premiumFrequency(): Optional = - premiumFrequency.getOptional("premium_frequency") + @JvmField val UNKNOWN = of("UNKNOWN") - /** - * Insurance company name - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun provider(): Optional = provider.getOptional("provider") + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } - /** - * Status of the policy (e.g., Active, Lapsed) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun status(): Optional = status.getOptional("status") + /** An enum containing [Type]'s known values. */ + enum class Known { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + } - /** - * Sum assured amount - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun sumAssured(): Optional = sumAssured.getOptional("sum_assured") + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API + * may respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + /** + * An enum member indicating that [Type] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } - /** - * Returns the raw JSON value of [lifeAssured]. - * - * Unlike [lifeAssured], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("life_assured") - @ExcludeMissing - fun _lifeAssured(): JsonField = lifeAssured + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always + * known or if you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PURCHASE -> Value.PURCHASE + PURCHASE_SIP -> Value.PURCHASE_SIP + REDEMPTION -> Value.REDEMPTION + SWITCH_IN -> Value.SWITCH_IN + SWITCH_IN_MERGER -> Value.SWITCH_IN_MERGER + SWITCH_OUT -> Value.SWITCH_OUT + SWITCH_OUT_MERGER -> Value.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Value.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Value.DIVIDEND_REINVEST + SEGREGATION -> Value.SEGREGATION + STAMP_DUTY_TAX -> Value.STAMP_DUTY_TAX + TDS_TAX -> Value.TDS_TAX + STT_TAX -> Value.STT_TAX + MISC -> Value.MISC + REVERSAL -> Value.REVERSAL + UNKNOWN -> Value.UNKNOWN + else -> Value._UNKNOWN + } - /** - * Returns the raw JSON value of [policyName]. - * - * Unlike [policyName], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("policy_name") - @ExcludeMissing - fun _policyName(): JsonField = policyName + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always + * known and don't want to throw for the unknown case. + * + * @throws CasParserInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + PURCHASE -> Known.PURCHASE + PURCHASE_SIP -> Known.PURCHASE_SIP + REDEMPTION -> Known.REDEMPTION + SWITCH_IN -> Known.SWITCH_IN + SWITCH_IN_MERGER -> Known.SWITCH_IN_MERGER + SWITCH_OUT -> Known.SWITCH_OUT + SWITCH_OUT_MERGER -> Known.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Known.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Known.DIVIDEND_REINVEST + SEGREGATION -> Known.SEGREGATION + STAMP_DUTY_TAX -> Known.STAMP_DUTY_TAX + TDS_TAX -> Known.TDS_TAX + STT_TAX -> Known.STT_TAX + MISC -> Known.MISC + REVERSAL -> Known.REVERSAL + UNKNOWN -> Known.UNKNOWN + else -> throw CasParserInvalidDataException("Unknown Type: $value") + } - /** - * Returns the raw JSON value of [policyNumber]. - * - * Unlike [policyNumber], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("policy_number") - @ExcludeMissing - fun _policyNumber(): JsonField = policyNumber + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily + * for debugging and generally doesn't throw. + * + * @throws CasParserInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CasParserInvalidDataException("Value is not a String") + } - /** - * Returns the raw JSON value of [premiumAmount]. - * - * Unlike [premiumAmount], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("premium_amount") - @ExcludeMissing - fun _premiumAmount(): JsonField = premiumAmount + private var validated: Boolean = false - /** - * Returns the raw JSON value of [premiumFrequency]. - * - * Unlike [premiumFrequency], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("premium_frequency") - @ExcludeMissing - fun _premiumFrequency(): JsonField = premiumFrequency + fun validate(): Type = apply { + if (validated) { + return@apply + } - /** - * Returns the raw JSON value of [provider]. - * - * Unlike [provider], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("provider") @ExcludeMissing fun _provider(): JsonField = provider + known() + validated = true + } - /** - * Returns the raw JSON value of [status]. - * - * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } - /** - * Returns the raw JSON value of [sumAssured]. - * - * Unlike [sumAssured], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("sum_assured") - @ExcludeMissing - fun _sumAssured(): JsonField = sumAssured + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + return other is Type && value == other.value + } - fun toBuilder() = Builder().from(this) + override fun hashCode() = value.hashCode() - companion object { + override fun toString() = value.toString() + } - /** - * Returns a mutable builder for constructing an instance of [LifeInsurancePolicy]. - */ - @JvmStatic fun builder() = Builder() - } + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - /** A builder for [LifeInsurancePolicy]. */ - class Builder internal constructor() { + return other is Transaction && + additionalInfo == other.additionalInfo && + amount == other.amount && + balance == other.balance && + date == other.date && + description == other.description && + dividendRate == other.dividendRate && + nav == other.nav && + type == other.type && + units == other.units && + additionalProperties == other.additionalProperties + } - private var additionalInfo: JsonValue = JsonMissing.of() - private var lifeAssured: JsonField = JsonMissing.of() - private var policyName: JsonField = JsonMissing.of() - private var policyNumber: JsonField = JsonMissing.of() - private var premiumAmount: JsonField = JsonMissing.of() - private var premiumFrequency: JsonField = JsonMissing.of() - private var provider: JsonField = JsonMissing.of() - private var status: JsonField = JsonMissing.of() - private var sumAssured: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + additionalProperties, + ) + } - @JvmSynthetic - internal fun from(lifeInsurancePolicy: LifeInsurancePolicy) = apply { - additionalInfo = lifeInsurancePolicy.additionalInfo - lifeAssured = lifeInsurancePolicy.lifeAssured - policyName = lifeInsurancePolicy.policyName - policyNumber = lifeInsurancePolicy.policyNumber - premiumAmount = lifeInsurancePolicy.premiumAmount - premiumFrequency = lifeInsurancePolicy.premiumFrequency - provider = lifeInsurancePolicy.provider - status = lifeInsurancePolicy.status - sumAssured = lifeInsurancePolicy.sumAssured - additionalProperties = lifeInsurancePolicy.additionalProperties.toMutableMap() + override fun hashCode(): Int = hashCode + + override fun toString() = + "Transaction{additionalInfo=$additionalInfo, amount=$amount, balance=$balance, date=$date, description=$description, dividendRate=$dividendRate, nav=$nav, type=$type, units=$units, additionalProperties=$additionalProperties}" } - /** Additional information specific to the policy */ - fun additionalInfo(additionalInfo: JsonValue) = apply { - this.additionalInfo = additionalInfo + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CorporateBond && + additionalInfo == other.additionalInfo && + isin == other.isin && + name == other.name && + transactions == other.transactions && + units == other.units && + value == other.value && + additionalProperties == other.additionalProperties } - /** Name of the life assured */ - fun lifeAssured(lifeAssured: String) = lifeAssured(JsonField.of(lifeAssured)) + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + isin, + name, + transactions, + units, + value, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CorporateBond{additionalInfo=$additionalInfo, isin=$isin, name=$name, transactions=$transactions, units=$units, value=$value, additionalProperties=$additionalProperties}" + } + + class DematMutualFund + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val isin: JsonField, + private val name: JsonField, + private val transactions: JsonField>, + private val units: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("isin") + @ExcludeMissing + isin: JsonField = JsonMissing.of(), + @JsonProperty("name") + @ExcludeMissing + name: JsonField = JsonMissing.of(), + @JsonProperty("transactions") + @ExcludeMissing + transactions: JsonField> = JsonMissing.of(), + @JsonProperty("units") + @ExcludeMissing + units: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(additionalInfo, isin, name, transactions, units, value, mutableMapOf()) /** - * Sets [Builder.lifeAssured] to an arbitrary JSON value. + * Additional information specific to the mutual fund * - * You should usually call [Builder.lifeAssured] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not - * yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). */ - fun lifeAssured(lifeAssured: JsonField) = apply { - this.lifeAssured = lifeAssured - } - - /** Name of the insurance policy */ - fun policyName(policyName: String) = policyName(JsonField.of(policyName)) + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") /** - * Sets [Builder.policyName] to an arbitrary JSON value. + * ISIN code of the mutual fund * - * You should usually call [Builder.policyName] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not - * yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). */ - fun policyName(policyName: JsonField) = apply { - this.policyName = policyName - } - - /** Insurance policy number */ - fun policyNumber(policyNumber: String) = policyNumber(JsonField.of(policyNumber)) + fun isin(): Optional = isin.getOptional("isin") /** - * Sets [Builder.policyNumber] to an arbitrary JSON value. + * Name of the mutual fund * - * You should usually call [Builder.policyNumber] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not - * yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). */ - fun policyNumber(policyNumber: JsonField) = apply { - this.policyNumber = policyNumber - } - - /** Premium amount */ - fun premiumAmount(premiumAmount: Float) = premiumAmount(JsonField.of(premiumAmount)) + fun name(): Optional = name.getOptional("name") /** - * Sets [Builder.premiumAmount] to an arbitrary JSON value. + * List of transactions for this holding (beta) * - * You should usually call [Builder.premiumAmount] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or not - * yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). */ - fun premiumAmount(premiumAmount: JsonField) = apply { - this.premiumAmount = premiumAmount - } - - /** Frequency of premium payment (e.g., Annual, Monthly) */ - fun premiumFrequency(premiumFrequency: String) = - premiumFrequency(JsonField.of(premiumFrequency)) + fun transactions(): Optional> = + transactions.getOptional("transactions") /** - * Sets [Builder.premiumFrequency] to an arbitrary JSON value. + * Number of units held * - * You should usually call [Builder.premiumFrequency] with a well-typed [String] - * value instead. This method is primarily for setting the field to an undocumented - * or not yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). */ - fun premiumFrequency(premiumFrequency: JsonField) = apply { - this.premiumFrequency = premiumFrequency - } + fun units(): Optional = units.getOptional("units") - /** Insurance company name */ - fun provider(provider: String) = provider(JsonField.of(provider)) + /** + * Current market value of the holding + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") /** - * Sets [Builder.provider] to an arbitrary JSON value. + * Returns the raw JSON value of [additionalInfo]. * - * You should usually call [Builder.provider] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not - * yet supported value. + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. */ - fun provider(provider: JsonField) = apply { this.provider = provider } + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo - /** Status of the policy (e.g., Active, Lapsed) */ - fun status(status: String) = status(JsonField.of(status)) + /** + * Returns the raw JSON value of [isin]. + * + * Unlike [isin], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("isin") @ExcludeMissing fun _isin(): JsonField = isin /** - * Sets [Builder.status] to an arbitrary JSON value. + * Returns the raw JSON value of [name]. * - * You should usually call [Builder.status] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not - * yet supported value. + * Unlike [name], this method doesn't throw if the JSON field has an unexpected + * type. */ - fun status(status: JsonField) = apply { this.status = status } + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name - /** Sum assured amount */ - fun sumAssured(sumAssured: Float) = sumAssured(JsonField.of(sumAssured)) + /** + * Returns the raw JSON value of [transactions]. + * + * Unlike [transactions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("transactions") + @ExcludeMissing + fun _transactions(): JsonField> = transactions /** - * Sets [Builder.sumAssured] to an arbitrary JSON value. + * Returns the raw JSON value of [units]. * - * You should usually call [Builder.sumAssured] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or not - * yet supported value. + * Unlike [units], this method doesn't throw if the JSON field has an unexpected + * type. */ - fun sumAssured(sumAssured: JsonField) = apply { - this.sumAssured = sumAssured - } + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value - fun putAdditionalProperty(key: String, value: JsonValue) = apply { + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) } - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) - } + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } + fun toBuilder() = Builder().from(this) - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) + companion object { + + /** + * Returns a mutable builder for constructing an instance of [DematMutualFund]. + */ + @JvmStatic fun builder() = Builder() } - /** - * Returns an immutable instance of [LifeInsurancePolicy]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): LifeInsurancePolicy = - LifeInsurancePolicy( - additionalInfo, - lifeAssured, - policyName, - policyNumber, - premiumAmount, - premiumFrequency, - provider, - status, - sumAssured, - additionalProperties.toMutableMap(), - ) - } + /** A builder for [DematMutualFund]. */ + class Builder internal constructor() { - private var validated: Boolean = false + private var additionalInfo: JsonField = JsonMissing.of() + private var isin: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var transactions: JsonField>? = null + private var units: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() - fun validate(): LifeInsurancePolicy = apply { - if (validated) { - return@apply - } + @JvmSynthetic + internal fun from(dematMutualFund: DematMutualFund) = apply { + additionalInfo = dematMutualFund.additionalInfo + isin = dematMutualFund.isin + name = dematMutualFund.name + transactions = dematMutualFund.transactions.map { it.toMutableList() } + units = dematMutualFund.units + value = dematMutualFund.value + additionalProperties = dematMutualFund.additionalProperties.toMutableMap() + } - lifeAssured() - policyName() - policyNumber() - premiumAmount() - premiumFrequency() - provider() - status() - sumAssured() - validated = true - } + /** Additional information specific to the mutual fund */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (lifeAssured.asKnown().isPresent) 1 else 0) + - (if (policyName.asKnown().isPresent) 1 else 0) + - (if (policyNumber.asKnown().isPresent) 1 else 0) + - (if (premiumAmount.asKnown().isPresent) 1 else 0) + - (if (premiumFrequency.asKnown().isPresent) 1 else 0) + - (if (provider.asKnown().isPresent) 1 else 0) + - (if (status.asKnown().isPresent) 1 else 0) + - (if (sumAssured.asKnown().isPresent) 1 else 0) + /** ISIN code of the mutual fund */ + fun isin(isin: String) = isin(JsonField.of(isin)) - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** + * Sets [Builder.isin] to an arbitrary JSON value. + * + * You should usually call [Builder.isin] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun isin(isin: JsonField) = apply { this.isin = isin } - return other is LifeInsurancePolicy && - additionalInfo == other.additionalInfo && - lifeAssured == other.lifeAssured && - policyName == other.policyName && - policyNumber == other.policyNumber && - premiumAmount == other.premiumAmount && - premiumFrequency == other.premiumFrequency && - provider == other.provider && - status == other.status && - sumAssured == other.sumAssured && - additionalProperties == other.additionalProperties - } + /** Name of the mutual fund */ + fun name(name: String) = name(JsonField.of(name)) - private val hashCode: Int by lazy { - Objects.hash( - additionalInfo, - lifeAssured, - policyName, - policyNumber, - premiumAmount, - premiumFrequency, - provider, - status, - sumAssured, - additionalProperties, - ) - } + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } - override fun hashCode(): Int = hashCode + /** List of transactions for this holding (beta) */ + fun transactions(transactions: List) = + transactions(JsonField.of(transactions)) - override fun toString() = - "LifeInsurancePolicy{additionalInfo=$additionalInfo, lifeAssured=$lifeAssured, policyName=$policyName, policyNumber=$policyNumber, premiumAmount=$premiumAmount, premiumFrequency=$premiumFrequency, provider=$provider, status=$status, sumAssured=$sumAssured, additionalProperties=$additionalProperties}" - } + /** + * Sets [Builder.transactions] to an arbitrary JSON value. + * + * You should usually call [Builder.transactions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun transactions(transactions: JsonField>) = apply { + this.transactions = transactions.map { it.toMutableList() } + } - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** + * Adds a single [Transaction] to [transactions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTransaction(transaction: Transaction) = apply { + transactions = + (transactions ?: JsonField.of(mutableListOf())).also { + checkKnown("transactions", it).add(transaction) + } + } - return other is Insurance && - lifeInsurancePolicies == other.lifeInsurancePolicies && - additionalProperties == other.additionalProperties - } + /** Number of units held */ + fun units(units: Float) = units(JsonField.of(units)) - private val hashCode: Int by lazy { - Objects.hash(lifeInsurancePolicies, additionalProperties) - } + /** + * Sets [Builder.units] to an arbitrary JSON value. + * + * You should usually call [Builder.units] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun units(units: JsonField) = apply { this.units = units } - override fun hashCode(): Int = hashCode + /** Current market value of the holding */ + fun value(value: Float) = value(JsonField.of(value)) - override fun toString() = - "Insurance{lifeInsurancePolicies=$lifeInsurancePolicies, additionalProperties=$additionalProperties}" - } + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } - class Investor - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val address: JsonField, - private val casId: JsonField, - private val email: JsonField, - private val mobile: JsonField, - private val name: JsonField, - private val pan: JsonField, - private val pincode: JsonField, - private val additionalProperties: MutableMap, - ) { + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - @JsonCreator - private constructor( - @JsonProperty("address") @ExcludeMissing address: JsonField = JsonMissing.of(), - @JsonProperty("cas_id") @ExcludeMissing casId: JsonField = JsonMissing.of(), - @JsonProperty("email") @ExcludeMissing email: JsonField = JsonMissing.of(), - @JsonProperty("mobile") @ExcludeMissing mobile: JsonField = JsonMissing.of(), - @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), - @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), - @JsonProperty("pincode") @ExcludeMissing pincode: JsonField = JsonMissing.of(), - ) : this(address, casId, email, mobile, name, pan, pincode, mutableMapOf()) + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - /** - * Address of the investor - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun address(): Optional = address.getOptional("address") + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } - /** - * CAS ID of the investor (only for NSDL and CDSL) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun casId(): Optional = casId.getOptional("cas_id") + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } - /** - * Email address of the investor - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun email(): Optional = email.getOptional("email") + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } - /** - * Mobile number of the investor - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun mobile(): Optional = mobile.getOptional("mobile") + /** + * Returns an immutable instance of [DematMutualFund]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): DematMutualFund = + DematMutualFund( + additionalInfo, + isin, + name, + (transactions ?: JsonMissing.of()).map { it.toImmutable() }, + units, + value, + additionalProperties.toMutableMap(), + ) + } - /** - * Name of the investor - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun name(): Optional = name.getOptional("name") + private var validated: Boolean = false - /** - * PAN (Permanent Account Number) of the investor - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun pan(): Optional = pan.getOptional("pan") - - /** - * Postal code of the investor's address - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun pincode(): Optional = pincode.getOptional("pincode") + fun validate(): DematMutualFund = apply { + if (validated) { + return@apply + } - /** - * Returns the raw JSON value of [address]. - * - * Unlike [address], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("address") @ExcludeMissing fun _address(): JsonField = address + additionalInfo().ifPresent { it.validate() } + isin() + name() + transactions().ifPresent { it.forEach { it.validate() } } + units() + value() + validated = true + } - /** - * Returns the raw JSON value of [casId]. - * - * Unlike [casId], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("cas_id") @ExcludeMissing fun _casId(): JsonField = casId + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } - /** - * Returns the raw JSON value of [email]. - * - * Unlike [email], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("email") @ExcludeMissing fun _email(): JsonField = email + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (isin.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (transactions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (units.asKnown().isPresent) 1 else 0) + + (if (value.asKnown().isPresent) 1 else 0) - /** - * Returns the raw JSON value of [mobile]. - * - * Unlike [mobile], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("mobile") @ExcludeMissing fun _mobile(): JsonField = mobile + /** Additional information specific to the mutual fund */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val closeUnits: JsonField, + private val openUnits: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("close_units") + @ExcludeMissing + closeUnits: JsonField = JsonMissing.of(), + @JsonProperty("open_units") + @ExcludeMissing + openUnits: JsonField = JsonMissing.of(), + ) : this(closeUnits, openUnits, mutableMapOf()) - /** - * Returns the raw JSON value of [name]. - * - * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + /** + * Closing balance units for the statement period (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun closeUnits(): Optional = closeUnits.getOptional("close_units") - /** - * Returns the raw JSON value of [pan]. - * - * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + /** + * Opening balance units for the statement period (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun openUnits(): Optional = openUnits.getOptional("open_units") - /** - * Returns the raw JSON value of [pincode]. - * - * Unlike [pincode], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("pincode") @ExcludeMissing fun _pincode(): JsonField = pincode + /** + * Returns the raw JSON value of [closeUnits]. + * + * Unlike [closeUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("close_units") + @ExcludeMissing + fun _closeUnits(): JsonField = closeUnits - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** + * Returns the raw JSON value of [openUnits]. + * + * Unlike [openUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("open_units") + @ExcludeMissing + fun _openUnits(): JsonField = openUnits - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - fun toBuilder() = Builder().from(this) + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - companion object { + fun toBuilder() = Builder().from(this) - /** Returns a mutable builder for constructing an instance of [Investor]. */ - @JvmStatic fun builder() = Builder() - } + companion object { - /** A builder for [Investor]. */ - class Builder internal constructor() { + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } - private var address: JsonField = JsonMissing.of() - private var casId: JsonField = JsonMissing.of() - private var email: JsonField = JsonMissing.of() - private var mobile: JsonField = JsonMissing.of() - private var name: JsonField = JsonMissing.of() - private var pan: JsonField = JsonMissing.of() - private var pincode: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { - @JvmSynthetic - internal fun from(investor: Investor) = apply { - address = investor.address - casId = investor.casId - email = investor.email - mobile = investor.mobile - name = investor.name - pan = investor.pan - pincode = investor.pincode - additionalProperties = investor.additionalProperties.toMutableMap() - } + private var closeUnits: JsonField = JsonMissing.of() + private var openUnits: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() - /** Address of the investor */ - fun address(address: String) = address(JsonField.of(address)) + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + closeUnits = additionalInfo.closeUnits + openUnits = additionalInfo.openUnits + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() + } - /** - * Sets [Builder.address] to an arbitrary JSON value. - * - * You should usually call [Builder.address] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun address(address: JsonField) = apply { this.address = address } + /** Closing balance units for the statement period (beta) */ + fun closeUnits(closeUnits: Float?) = + closeUnits(JsonField.ofNullable(closeUnits)) - /** CAS ID of the investor (only for NSDL and CDSL) */ - fun casId(casId: String) = casId(JsonField.of(casId)) + /** + * Alias for [Builder.closeUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun closeUnits(closeUnits: Float) = closeUnits(closeUnits as Float?) - /** - * Sets [Builder.casId] to an arbitrary JSON value. - * - * You should usually call [Builder.casId] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun casId(casId: JsonField) = apply { this.casId = casId } + /** + * Alias for calling [Builder.closeUnits] with `closeUnits.orElse(null)`. + */ + fun closeUnits(closeUnits: Optional) = + closeUnits(closeUnits.getOrNull()) - /** Email address of the investor */ - fun email(email: String) = email(JsonField.of(email)) + /** + * Sets [Builder.closeUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.closeUnits] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun closeUnits(closeUnits: JsonField) = apply { + this.closeUnits = closeUnits + } - /** - * Sets [Builder.email] to an arbitrary JSON value. - * - * You should usually call [Builder.email] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun email(email: JsonField) = apply { this.email = email } + /** Opening balance units for the statement period (beta) */ + fun openUnits(openUnits: Float?) = + openUnits(JsonField.ofNullable(openUnits)) - /** Mobile number of the investor */ - fun mobile(mobile: String) = mobile(JsonField.of(mobile)) + /** + * Alias for [Builder.openUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun openUnits(openUnits: Float) = openUnits(openUnits as Float?) - /** - * Sets [Builder.mobile] to an arbitrary JSON value. - * - * You should usually call [Builder.mobile] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun mobile(mobile: JsonField) = apply { this.mobile = mobile } + /** Alias for calling [Builder.openUnits] with `openUnits.orElse(null)`. */ + fun openUnits(openUnits: Optional) = openUnits(openUnits.getOrNull()) - /** Name of the investor */ - fun name(name: String) = name(JsonField.of(name)) + /** + * Sets [Builder.openUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.openUnits] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun openUnits(openUnits: JsonField) = apply { + this.openUnits = openUnits + } - /** - * Sets [Builder.name] to an arbitrary JSON value. - * - * You should usually call [Builder.name] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun name(name: JsonField) = apply { this.name = name } + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - /** PAN (Permanent Account Number) of the investor */ - fun pan(pan: String) = pan(JsonField.of(pan)) + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - /** - * Sets [Builder.pan] to an arbitrary JSON value. - * - * You should usually call [Builder.pan] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun pan(pan: JsonField) = apply { this.pan = pan } + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } - /** Postal code of the investor's address */ - fun pincode(pincode: String) = pincode(JsonField.of(pincode)) + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } - /** - * Sets [Builder.pincode] to an arbitrary JSON value. - * - * You should usually call [Builder.pincode] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun pincode(pincode: JsonField) = apply { this.pincode = pincode } + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + closeUnits, + openUnits, + additionalProperties.toMutableMap(), + ) + } - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + private var validated: Boolean = false - fun putAllAdditionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.putAll(additionalProperties) - } + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } - fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + closeUnits() + openUnits() + validated = true + } - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } - /** - * Returns an immutable instance of [Investor]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Investor = - Investor( - address, - casId, - email, - mobile, - name, - pan, - pincode, - additionalProperties.toMutableMap(), - ) - } + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (closeUnits.asKnown().isPresent) 1 else 0) + + (if (openUnits.asKnown().isPresent) 1 else 0) - private var validated: Boolean = false + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - fun validate(): Investor = apply { - if (validated) { - return@apply - } + return other is AdditionalInfo && + closeUnits == other.closeUnits && + openUnits == other.openUnits && + additionalProperties == other.additionalProperties + } - address() - casId() - email() - mobile() - name() - pan() - pincode() - validated = true - } + private val hashCode: Int by lazy { + Objects.hash(closeUnits, openUnits, additionalProperties) + } - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + override fun hashCode(): Int = hashCode - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (address.asKnown().isPresent) 1 else 0) + - (if (casId.asKnown().isPresent) 1 else 0) + - (if (email.asKnown().isPresent) 1 else 0) + - (if (mobile.asKnown().isPresent) 1 else 0) + - (if (name.asKnown().isPresent) 1 else 0) + - (if (pan.asKnown().isPresent) 1 else 0) + - (if (pincode.asKnown().isPresent) 1 else 0) + override fun toString() = + "AdditionalInfo{closeUnits=$closeUnits, openUnits=$openUnits, additionalProperties=$additionalProperties}" + } - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** + * Unified transaction schema for all holding types (MF folios, equities, bonds, + * etc.) + */ + class Transaction + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val amount: JsonField, + private val balance: JsonField, + private val date: JsonField, + private val description: JsonField, + private val dividendRate: JsonField, + private val nav: JsonField, + private val type: JsonField, + private val units: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("amount") + @ExcludeMissing + amount: JsonField = JsonMissing.of(), + @JsonProperty("balance") + @ExcludeMissing + balance: JsonField = JsonMissing.of(), + @JsonProperty("date") + @ExcludeMissing + date: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("dividend_rate") + @ExcludeMissing + dividendRate: JsonField = JsonMissing.of(), + @JsonProperty("nav") + @ExcludeMissing + nav: JsonField = JsonMissing.of(), + @JsonProperty("type") + @ExcludeMissing + type: JsonField = JsonMissing.of(), + @JsonProperty("units") + @ExcludeMissing + units: JsonField = JsonMissing.of(), + ) : this( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + mutableMapOf(), + ) - return other is Investor && - address == other.address && - casId == other.casId && - email == other.email && - mobile == other.mobile && - name == other.name && - pan == other.pan && - pincode == other.pincode && - additionalProperties == other.additionalProperties - } + /** + * Additional transaction-specific fields that vary by source + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") - private val hashCode: Int by lazy { - Objects.hash(address, casId, email, mobile, name, pan, pincode, additionalProperties) - } + /** + * Transaction amount in currency (computed from units × price/NAV) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") - override fun hashCode(): Int = hashCode + /** + * Balance units after transaction + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun balance(): Optional = balance.getOptional("balance") - override fun toString() = - "Investor{address=$address, casId=$casId, email=$email, mobile=$mobile, name=$name, pan=$pan, pincode=$pincode, additionalProperties=$additionalProperties}" - } + /** + * Transaction date (YYYY-MM-DD) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun date(): Optional = date.getOptional("date") - class Meta - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val casType: JsonField, - private val generatedAt: JsonField, - private val statementPeriod: JsonField, - private val additionalProperties: MutableMap, - ) { + /** + * Transaction description/particulars + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") - @JsonCreator - private constructor( - @JsonProperty("cas_type") - @ExcludeMissing - casType: JsonField = JsonMissing.of(), - @JsonProperty("generated_at") - @ExcludeMissing - generatedAt: JsonField = JsonMissing.of(), - @JsonProperty("statement_period") - @ExcludeMissing - statementPeriod: JsonField = JsonMissing.of(), - ) : this(casType, generatedAt, statementPeriod, mutableMapOf()) + /** + * Dividend rate (for DIVIDEND_PAYOUT transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun dividendRate(): Optional = dividendRate.getOptional("dividend_rate") - /** - * Type of CAS detected and processed - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun casType(): Optional = casType.getOptional("cas_type") + /** + * NAV/price per unit on transaction date + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun nav(): Optional = nav.getOptional("nav") - /** - * Timestamp when the response was generated - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun generatedAt(): Optional = generatedAt.getOptional("generated_at") + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun type(): Optional = type.getOptional("type") - /** - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun statementPeriod(): Optional = - statementPeriod.getOptional("statement_period") + /** + * Number of units involved in transaction + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun units(): Optional = units.getOptional("units") - /** - * Returns the raw JSON value of [casType]. - * - * Unlike [casType], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("cas_type") @ExcludeMissing fun _casType(): JsonField = casType + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo - /** - * Returns the raw JSON value of [generatedAt]. - * - * Unlike [generatedAt], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("generated_at") - @ExcludeMissing - fun _generatedAt(): JsonField = generatedAt + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount - /** - * Returns the raw JSON value of [statementPeriod]. - * - * Unlike [statementPeriod], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("statement_period") - @ExcludeMissing - fun _statementPeriod(): JsonField = statementPeriod + /** + * Returns the raw JSON value of [balance]. + * + * Unlike [balance], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("balance") + @ExcludeMissing + fun _balance(): JsonField = balance - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** + * Returns the raw JSON value of [date]. + * + * Unlike [date], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description - fun toBuilder() = Builder().from(this) + /** + * Returns the raw JSON value of [dividendRate]. + * + * Unlike [dividendRate], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("dividend_rate") + @ExcludeMissing + fun _dividendRate(): JsonField = dividendRate - companion object { + /** + * Returns the raw JSON value of [nav]. + * + * Unlike [nav], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("nav") @ExcludeMissing fun _nav(): JsonField = nav - /** Returns a mutable builder for constructing an instance of [Meta]. */ - @JvmStatic fun builder() = Builder() - } + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type - /** A builder for [Meta]. */ - class Builder internal constructor() { + /** + * Returns the raw JSON value of [units]. + * + * Unlike [units], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units - private var casType: JsonField = JsonMissing.of() - private var generatedAt: JsonField = JsonMissing.of() - private var statementPeriod: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - @JvmSynthetic - internal fun from(meta: Meta) = apply { - casType = meta.casType - generatedAt = meta.generatedAt - statementPeriod = meta.statementPeriod - additionalProperties = meta.additionalProperties.toMutableMap() - } + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - /** Type of CAS detected and processed */ - fun casType(casType: CasType) = casType(JsonField.of(casType)) + fun toBuilder() = Builder().from(this) - /** - * Sets [Builder.casType] to an arbitrary JSON value. - * - * You should usually call [Builder.casType] with a well-typed [CasType] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun casType(casType: JsonField) = apply { this.casType = casType } + companion object { - /** Timestamp when the response was generated */ - fun generatedAt(generatedAt: OffsetDateTime) = generatedAt(JsonField.of(generatedAt)) + /** + * Returns a mutable builder for constructing an instance of [Transaction]. + */ + @JvmStatic fun builder() = Builder() + } - /** - * Sets [Builder.generatedAt] to an arbitrary JSON value. - * - * You should usually call [Builder.generatedAt] with a well-typed [OffsetDateTime] - * value instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun generatedAt(generatedAt: JsonField) = apply { - this.generatedAt = generatedAt - } + /** A builder for [Transaction]. */ + class Builder internal constructor() { + + private var additionalInfo: JsonField = JsonMissing.of() + private var amount: JsonField = JsonMissing.of() + private var balance: JsonField = JsonMissing.of() + private var date: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var dividendRate: JsonField = JsonMissing.of() + private var nav: JsonField = JsonMissing.of() + private var type: JsonField = JsonMissing.of() + private var units: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(transaction: Transaction) = apply { + additionalInfo = transaction.additionalInfo + amount = transaction.amount + balance = transaction.balance + date = transaction.date + description = transaction.description + dividendRate = transaction.dividendRate + nav = transaction.nav + type = transaction.type + units = transaction.units + additionalProperties = transaction.additionalProperties.toMutableMap() + } - fun statementPeriod(statementPeriod: StatementPeriod) = - statementPeriod(JsonField.of(statementPeriod)) + /** Additional transaction-specific fields that vary by source */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) - /** - * Sets [Builder.statementPeriod] to an arbitrary JSON value. - * - * You should usually call [Builder.statementPeriod] with a well-typed [StatementPeriod] - * value instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun statementPeriod(statementPeriod: JsonField) = apply { - this.statementPeriod = statementPeriod - } + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** Transaction amount in currency (computed from units × price/NAV) */ + fun amount(amount: Float?) = amount(JsonField.ofNullable(amount)) - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + /** + * Alias for [Builder.amount]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun amount(amount: Float) = amount(amount as Float?) - fun putAllAdditionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.putAll(additionalProperties) - } + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) - fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + /** Balance units after transaction */ + fun balance(balance: Float) = balance(JsonField.of(balance)) - /** - * Returns an immutable instance of [Meta]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Meta = - Meta(casType, generatedAt, statementPeriod, additionalProperties.toMutableMap()) - } + /** + * Sets [Builder.balance] to an arbitrary JSON value. + * + * You should usually call [Builder.balance] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun balance(balance: JsonField) = apply { this.balance = balance } - private var validated: Boolean = false + /** Transaction date (YYYY-MM-DD) */ + fun date(date: LocalDate) = date(JsonField.of(date)) - fun validate(): Meta = apply { - if (validated) { - return@apply - } + /** + * Sets [Builder.date] to an arbitrary JSON value. + * + * You should usually call [Builder.date] with a well-typed [LocalDate] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun date(date: JsonField) = apply { this.date = date } - casType().ifPresent { it.validate() } - generatedAt() - statementPeriod().ifPresent { it.validate() } - validated = true - } + /** Transaction description/particulars */ + fun description(description: String) = + description(JsonField.of(description)) - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (casType.asKnown().getOrNull()?.validity() ?: 0) + - (if (generatedAt.asKnown().isPresent) 1 else 0) + - (statementPeriod.asKnown().getOrNull()?.validity() ?: 0) + /** Dividend rate (for DIVIDEND_PAYOUT transactions) */ + fun dividendRate(dividendRate: Float?) = + dividendRate(JsonField.ofNullable(dividendRate)) - /** Type of CAS detected and processed */ - class CasType @JsonCreator private constructor(private val value: JsonField) : - Enum { + /** + * Alias for [Builder.dividendRate]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun dividendRate(dividendRate: Float) = dividendRate(dividendRate as Float?) - /** - * Returns this class instance's raw value. - * - * This is usually only useful if this instance was deserialized from data that doesn't - * match any known member, and you want to know that value. For example, if the SDK is - * on an older version than the API, then the API may respond with new members that the - * SDK is unaware of. - */ - @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + /** + * Alias for calling [Builder.dividendRate] with + * `dividendRate.orElse(null)`. + */ + fun dividendRate(dividendRate: Optional) = + dividendRate(dividendRate.getOrNull()) - companion object { + /** + * Sets [Builder.dividendRate] to an arbitrary JSON value. + * + * You should usually call [Builder.dividendRate] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun dividendRate(dividendRate: JsonField) = apply { + this.dividendRate = dividendRate + } - @JvmField val NSDL = of("NSDL") + /** NAV/price per unit on transaction date */ + fun nav(nav: Float?) = nav(JsonField.ofNullable(nav)) - @JvmField val CDSL = of("CDSL") + /** + * Alias for [Builder.nav]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun nav(nav: Float) = nav(nav as Float?) - @JvmField val CAMS_KFINTECH = of("CAMS_KFINTECH") + /** Alias for calling [Builder.nav] with `nav.orElse(null)`. */ + fun nav(nav: Optional) = nav(nav.getOrNull()) - @JvmStatic fun of(value: String) = CasType(JsonField.of(value)) - } + /** + * Sets [Builder.nav] to an arbitrary JSON value. + * + * You should usually call [Builder.nav] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun nav(nav: JsonField) = apply { this.nav = nav } - /** An enum containing [CasType]'s known values. */ - enum class Known { - NSDL, - CDSL, - CAMS_KFINTECH, - } + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, + * DIVIDEND_PAYOUT, DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, + * STT_TAX, MISC, REVERSAL, UNKNOWN. + */ + fun type(type: Type) = type(JsonField.of(type)) - /** - * An enum containing [CasType]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [CasType] can contain an unknown value in a couple of cases: - * - It was deserialized from data that doesn't match any known member. For example, if - * the SDK is on an older version than the API, then the API may respond with new - * members that the SDK is unaware of. - * - It was constructed with an arbitrary value using the [of] method. - */ - enum class Value { - NSDL, - CDSL, - CAMS_KFINTECH, - /** - * An enum member indicating that [CasType] was instantiated with an unknown value. - */ - _UNKNOWN, - } + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } - /** - * Returns an enum member corresponding to this class instance's value, or - * [Value._UNKNOWN] if the class was instantiated with an unknown value. - * - * Use the [known] method instead if you're certain the value is always known or if you - * want to throw for the unknown case. - */ - fun value(): Value = - when (this) { - NSDL -> Value.NSDL - CDSL -> Value.CDSL - CAMS_KFINTECH -> Value.CAMS_KFINTECH - else -> Value._UNKNOWN - } + /** Number of units involved in transaction */ + fun units(units: Float) = units(JsonField.of(units)) - /** - * Returns an enum member corresponding to this class instance's value. - * - * Use the [value] method instead if you're uncertain the value is always known and - * don't want to throw for the unknown case. - * - * @throws CasParserInvalidDataException if this class instance's value is a not a known - * member. - */ - fun known(): Known = - when (this) { - NSDL -> Known.NSDL - CDSL -> Known.CDSL - CAMS_KFINTECH -> Known.CAMS_KFINTECH - else -> throw CasParserInvalidDataException("Unknown CasType: $value") - } + /** + * Sets [Builder.units] to an arbitrary JSON value. + * + * You should usually call [Builder.units] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun units(units: JsonField) = apply { this.units = units } - /** - * Returns this class instance's primitive wire representation. - * - * This differs from the [toString] method because that method is primarily for - * debugging and generally doesn't throw. - * - * @throws CasParserInvalidDataException if this class instance's value does not have - * the expected primitive type. - */ - fun asString(): String = - _value().asString().orElseThrow { - CasParserInvalidDataException("Value is not a String") - } + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - private var validated: Boolean = false + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - fun validate(): CasType = apply { - if (validated) { - return@apply - } + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } - known() - validated = true - } + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + /** + * Returns an immutable instance of [Transaction]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Transaction = + Transaction( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + additionalProperties.toMutableMap(), + ) + } - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + private var validated: Boolean = false - return other is CasType && value == other.value - } + fun validate(): Transaction = apply { + if (validated) { + return@apply + } - override fun hashCode() = value.hashCode() + additionalInfo().ifPresent { it.validate() } + amount() + balance() + date() + description() + dividendRate() + nav() + type().ifPresent { it.validate() } + units() + validated = true + } - override fun toString() = value.toString() - } + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } - class StatementPeriod - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val from: JsonField, - private val to: JsonField, - private val additionalProperties: MutableMap, - ) { + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (amount.asKnown().isPresent) 1 else 0) + + (if (balance.asKnown().isPresent) 1 else 0) + + (if (date.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (if (dividendRate.asKnown().isPresent) 1 else 0) + + (if (nav.asKnown().isPresent) 1 else 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (units.asKnown().isPresent) 1 else 0) + + /** Additional transaction-specific fields that vary by source */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val capitalWithdrawal: JsonField, + private val credit: JsonField, + private val debit: JsonField, + private val incomeDistribution: JsonField, + private val orderNo: JsonField, + private val price: JsonField, + private val stampDuty: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("capital_withdrawal") + @ExcludeMissing + capitalWithdrawal: JsonField = JsonMissing.of(), + @JsonProperty("credit") + @ExcludeMissing + credit: JsonField = JsonMissing.of(), + @JsonProperty("debit") + @ExcludeMissing + debit: JsonField = JsonMissing.of(), + @JsonProperty("income_distribution") + @ExcludeMissing + incomeDistribution: JsonField = JsonMissing.of(), + @JsonProperty("order_no") + @ExcludeMissing + orderNo: JsonField = JsonMissing.of(), + @JsonProperty("price") + @ExcludeMissing + price: JsonField = JsonMissing.of(), + @JsonProperty("stamp_duty") + @ExcludeMissing + stampDuty: JsonField = JsonMissing.of(), + ) : this( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + mutableMapOf(), + ) - @JsonCreator - private constructor( - @JsonProperty("from") @ExcludeMissing from: JsonField = JsonMissing.of(), - @JsonProperty("to") @ExcludeMissing to: JsonField = JsonMissing.of(), - ) : this(from, to, mutableMapOf()) + /** + * Capital withdrawal amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun capitalWithdrawal(): Optional = + capitalWithdrawal.getOptional("capital_withdrawal") - /** - * Start date of the statement period - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun from(): Optional = from.getOptional("from") + /** + * Units credited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun credit(): Optional = credit.getOptional("credit") - /** - * End date of the statement period - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun to(): Optional = to.getOptional("to") + /** + * Units debited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun debit(): Optional = debit.getOptional("debit") - /** - * Returns the raw JSON value of [from]. - * - * Unlike [from], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("from") @ExcludeMissing fun _from(): JsonField = from + /** + * Income distribution amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun incomeDistribution(): Optional = + incomeDistribution.getOptional("income_distribution") - /** - * Returns the raw JSON value of [to]. - * - * Unlike [to], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("to") @ExcludeMissing fun _to(): JsonField = to + /** + * Order/transaction reference number (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun orderNo(): Optional = orderNo.getOptional("order_no") - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** + * Price per unit (NSDL/CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun price(): Optional = price.getOptional("price") - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + /** + * Stamp duty charged + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun stampDuty(): Optional = stampDuty.getOptional("stamp_duty") - fun toBuilder() = Builder().from(this) + /** + * Returns the raw JSON value of [capitalWithdrawal]. + * + * Unlike [capitalWithdrawal], this method doesn't throw if the JSON field + * has an unexpected type. + */ + @JsonProperty("capital_withdrawal") + @ExcludeMissing + fun _capitalWithdrawal(): JsonField = capitalWithdrawal - companion object { + /** + * Returns the raw JSON value of [credit]. + * + * Unlike [credit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("credit") + @ExcludeMissing + fun _credit(): JsonField = credit - /** Returns a mutable builder for constructing an instance of [StatementPeriod]. */ - @JvmStatic fun builder() = Builder() - } + /** + * Returns the raw JSON value of [debit]. + * + * Unlike [debit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("debit") + @ExcludeMissing + fun _debit(): JsonField = debit - /** A builder for [StatementPeriod]. */ - class Builder internal constructor() { + /** + * Returns the raw JSON value of [incomeDistribution]. + * + * Unlike [incomeDistribution], this method doesn't throw if the JSON field + * has an unexpected type. + */ + @JsonProperty("income_distribution") + @ExcludeMissing + fun _incomeDistribution(): JsonField = incomeDistribution - private var from: JsonField = JsonMissing.of() - private var to: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + /** + * Returns the raw JSON value of [orderNo]. + * + * Unlike [orderNo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("order_no") + @ExcludeMissing + fun _orderNo(): JsonField = orderNo - @JvmSynthetic - internal fun from(statementPeriod: StatementPeriod) = apply { - from = statementPeriod.from - to = statementPeriod.to - additionalProperties = statementPeriod.additionalProperties.toMutableMap() - } + /** + * Returns the raw JSON value of [price]. + * + * Unlike [price], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("price") + @ExcludeMissing + fun _price(): JsonField = price - /** Start date of the statement period */ - fun from(from: LocalDate) = from(JsonField.of(from)) + /** + * Returns the raw JSON value of [stampDuty]. + * + * Unlike [stampDuty], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("stamp_duty") + @ExcludeMissing + fun _stampDuty(): JsonField = stampDuty - /** - * Sets [Builder.from] to an arbitrary JSON value. - * - * You should usually call [Builder.from] with a well-typed [LocalDate] value - * instead. This method is primarily for setting the field to an undocumented or not - * yet supported value. - */ - fun from(from: JsonField) = apply { this.from = from } + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - /** End date of the statement period */ - fun to(to: LocalDate) = to(JsonField.of(to)) + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - /** - * Sets [Builder.to] to an arbitrary JSON value. - * - * You should usually call [Builder.to] with a well-typed [LocalDate] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun to(to: JsonField) = apply { this.to = to } + fun toBuilder() = Builder().from(this) - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + companion object { - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { + + private var capitalWithdrawal: JsonField = JsonMissing.of() + private var credit: JsonField = JsonMissing.of() + private var debit: JsonField = JsonMissing.of() + private var incomeDistribution: JsonField = JsonMissing.of() + private var orderNo: JsonField = JsonMissing.of() + private var price: JsonField = JsonMissing.of() + private var stampDuty: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + capitalWithdrawal = additionalInfo.capitalWithdrawal + credit = additionalInfo.credit + debit = additionalInfo.debit + incomeDistribution = additionalInfo.incomeDistribution + orderNo = additionalInfo.orderNo + price = additionalInfo.price + stampDuty = additionalInfo.stampDuty + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() + } + + /** Capital withdrawal amount (CDSL MF transactions) */ + fun capitalWithdrawal(capitalWithdrawal: Float) = + capitalWithdrawal(JsonField.of(capitalWithdrawal)) + + /** + * Sets [Builder.capitalWithdrawal] to an arbitrary JSON value. + * + * You should usually call [Builder.capitalWithdrawal] with a well-typed + * [Float] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun capitalWithdrawal(capitalWithdrawal: JsonField) = apply { + this.capitalWithdrawal = capitalWithdrawal + } + + /** Units credited (demat transactions) */ + fun credit(credit: Float) = credit(JsonField.of(credit)) + + /** + * Sets [Builder.credit] to an arbitrary JSON value. + * + * You should usually call [Builder.credit] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun credit(credit: JsonField) = apply { this.credit = credit } + + /** Units debited (demat transactions) */ + fun debit(debit: Float) = debit(JsonField.of(debit)) + + /** + * Sets [Builder.debit] to an arbitrary JSON value. + * + * You should usually call [Builder.debit] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun debit(debit: JsonField) = apply { this.debit = debit } + + /** Income distribution amount (CDSL MF transactions) */ + fun incomeDistribution(incomeDistribution: Float) = + incomeDistribution(JsonField.of(incomeDistribution)) + + /** + * Sets [Builder.incomeDistribution] to an arbitrary JSON value. + * + * You should usually call [Builder.incomeDistribution] with a + * well-typed [Float] value instead. This method is primarily for + * setting the field to an undocumented or not yet supported value. + */ + fun incomeDistribution(incomeDistribution: JsonField) = apply { + this.incomeDistribution = incomeDistribution + } + + /** Order/transaction reference number (demat transactions) */ + fun orderNo(orderNo: String) = orderNo(JsonField.of(orderNo)) + + /** + * Sets [Builder.orderNo] to an arbitrary JSON value. + * + * You should usually call [Builder.orderNo] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun orderNo(orderNo: JsonField) = apply { + this.orderNo = orderNo + } + + /** Price per unit (NSDL/CDSL MF transactions) */ + fun price(price: Float) = price(JsonField.of(price)) + + /** + * Sets [Builder.price] to an arbitrary JSON value. + * + * You should usually call [Builder.price] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun price(price: JsonField) = apply { this.price = price } + + /** Stamp duty charged */ + fun stampDuty(stampDuty: Float) = stampDuty(JsonField.of(stampDuty)) + + /** + * Sets [Builder.stampDuty] to an arbitrary JSON value. + * + * You should usually call [Builder.stampDuty] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun stampDuty(stampDuty: JsonField) = apply { + this.stampDuty = stampDuty + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } + + capitalWithdrawal() + credit() + debit() + incomeDistribution() + orderNo() + price() + stampDuty() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (capitalWithdrawal.asKnown().isPresent) 1 else 0) + + (if (credit.asKnown().isPresent) 1 else 0) + + (if (debit.asKnown().isPresent) 1 else 0) + + (if (incomeDistribution.asKnown().isPresent) 1 else 0) + + (if (orderNo.asKnown().isPresent) 1 else 0) + + (if (price.asKnown().isPresent) 1 else 0) + + (if (stampDuty.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AdditionalInfo && + capitalWithdrawal == other.capitalWithdrawal && + credit == other.credit && + debit == other.debit && + incomeDistribution == other.incomeDistribution && + orderNo == other.orderNo && + price == other.price && + stampDuty == other.stampDuty && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{capitalWithdrawal=$capitalWithdrawal, credit=$credit, debit=$debit, incomeDistribution=$incomeDistribution, orderNo=$orderNo, price=$price, stampDuty=$stampDuty, additionalProperties=$additionalProperties}" } - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + */ + class Type + @JsonCreator + private constructor(private val value: JsonField) : Enum { - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data + * that doesn't match any known member, and you want to know that value. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value - /** - * Returns an immutable instance of [StatementPeriod]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): StatementPeriod = - StatementPeriod(from, to, additionalProperties.toMutableMap()) - } + companion object { - private var validated: Boolean = false + @JvmField val PURCHASE = of("PURCHASE") - fun validate(): StatementPeriod = apply { - if (validated) { - return@apply - } + @JvmField val PURCHASE_SIP = of("PURCHASE_SIP") - from() - to() - validated = true - } + @JvmField val REDEMPTION = of("REDEMPTION") - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + @JvmField val SWITCH_IN = of("SWITCH_IN") - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (from.asKnown().isPresent) 1 else 0) + (if (to.asKnown().isPresent) 1 else 0) + @JvmField val SWITCH_IN_MERGER = of("SWITCH_IN_MERGER") - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + @JvmField val SWITCH_OUT = of("SWITCH_OUT") - return other is StatementPeriod && - from == other.from && - to == other.to && - additionalProperties == other.additionalProperties - } + @JvmField val SWITCH_OUT_MERGER = of("SWITCH_OUT_MERGER") - private val hashCode: Int by lazy { Objects.hash(from, to, additionalProperties) } + @JvmField val DIVIDEND_PAYOUT = of("DIVIDEND_PAYOUT") - override fun hashCode(): Int = hashCode + @JvmField val DIVIDEND_REINVEST = of("DIVIDEND_REINVEST") - override fun toString() = - "StatementPeriod{from=$from, to=$to, additionalProperties=$additionalProperties}" - } + @JvmField val SEGREGATION = of("SEGREGATION") - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + @JvmField val STAMP_DUTY_TAX = of("STAMP_DUTY_TAX") - return other is Meta && - casType == other.casType && - generatedAt == other.generatedAt && - statementPeriod == other.statementPeriod && - additionalProperties == other.additionalProperties - } + @JvmField val TDS_TAX = of("TDS_TAX") - private val hashCode: Int by lazy { - Objects.hash(casType, generatedAt, statementPeriod, additionalProperties) - } + @JvmField val STT_TAX = of("STT_TAX") - override fun hashCode(): Int = hashCode + @JvmField val MISC = of("MISC") - override fun toString() = - "Meta{casType=$casType, generatedAt=$generatedAt, statementPeriod=$statementPeriod, additionalProperties=$additionalProperties}" - } + @JvmField val REVERSAL = of("REVERSAL") - class MutualFund - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val additionalInfo: JsonField, - private val amc: JsonField, - private val folioNumber: JsonField, - private val linkedHolders: JsonField>, - private val registrar: JsonField, - private val schemes: JsonField>, - private val value: JsonField, - private val additionalProperties: MutableMap, - ) { + @JvmField val UNKNOWN = of("UNKNOWN") - @JsonCreator - private constructor( - @JsonProperty("additional_info") - @ExcludeMissing - additionalInfo: JsonField = JsonMissing.of(), - @JsonProperty("amc") @ExcludeMissing amc: JsonField = JsonMissing.of(), - @JsonProperty("folio_number") - @ExcludeMissing - folioNumber: JsonField = JsonMissing.of(), - @JsonProperty("linked_holders") - @ExcludeMissing - linkedHolders: JsonField> = JsonMissing.of(), - @JsonProperty("registrar") - @ExcludeMissing - registrar: JsonField = JsonMissing.of(), - @JsonProperty("schemes") - @ExcludeMissing - schemes: JsonField> = JsonMissing.of(), - @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), - ) : this( - additionalInfo, - amc, - folioNumber, - linkedHolders, - registrar, - schemes, - value, - mutableMapOf(), - ) + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } - /** - * Additional folio information - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun additionalInfo(): Optional = - additionalInfo.getOptional("additional_info") + /** An enum containing [Type]'s known values. */ + enum class Known { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + } - /** - * Asset Management Company name - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun amc(): Optional = amc.getOptional("amc") + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API + * may respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + /** + * An enum member indicating that [Type] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } - /** - * Folio number - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun folioNumber(): Optional = folioNumber.getOptional("folio_number") + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always + * known or if you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PURCHASE -> Value.PURCHASE + PURCHASE_SIP -> Value.PURCHASE_SIP + REDEMPTION -> Value.REDEMPTION + SWITCH_IN -> Value.SWITCH_IN + SWITCH_IN_MERGER -> Value.SWITCH_IN_MERGER + SWITCH_OUT -> Value.SWITCH_OUT + SWITCH_OUT_MERGER -> Value.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Value.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Value.DIVIDEND_REINVEST + SEGREGATION -> Value.SEGREGATION + STAMP_DUTY_TAX -> Value.STAMP_DUTY_TAX + TDS_TAX -> Value.TDS_TAX + STT_TAX -> Value.STT_TAX + MISC -> Value.MISC + REVERSAL -> Value.REVERSAL + UNKNOWN -> Value.UNKNOWN + else -> Value._UNKNOWN + } - /** - * List of account holders linked to this mutual fund folio - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun linkedHolders(): Optional> = - linkedHolders.getOptional("linked_holders") + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always + * known and don't want to throw for the unknown case. + * + * @throws CasParserInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + PURCHASE -> Known.PURCHASE + PURCHASE_SIP -> Known.PURCHASE_SIP + REDEMPTION -> Known.REDEMPTION + SWITCH_IN -> Known.SWITCH_IN + SWITCH_IN_MERGER -> Known.SWITCH_IN_MERGER + SWITCH_OUT -> Known.SWITCH_OUT + SWITCH_OUT_MERGER -> Known.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Known.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Known.DIVIDEND_REINVEST + SEGREGATION -> Known.SEGREGATION + STAMP_DUTY_TAX -> Known.STAMP_DUTY_TAX + TDS_TAX -> Known.TDS_TAX + STT_TAX -> Known.STT_TAX + MISC -> Known.MISC + REVERSAL -> Known.REVERSAL + UNKNOWN -> Known.UNKNOWN + else -> throw CasParserInvalidDataException("Unknown Type: $value") + } - /** - * Registrar and Transfer Agent name - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun registrar(): Optional = registrar.getOptional("registrar") + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily + * for debugging and generally doesn't throw. + * + * @throws CasParserInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CasParserInvalidDataException("Value is not a String") + } - /** - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun schemes(): Optional> = schemes.getOptional("schemes") + private var validated: Boolean = false - /** - * Total value of the folio - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun value(): Optional = value.getOptional("value") + fun validate(): Type = apply { + if (validated) { + return@apply + } - /** - * Returns the raw JSON value of [additionalInfo]. - * - * Unlike [additionalInfo], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("additional_info") - @ExcludeMissing - fun _additionalInfo(): JsonField = additionalInfo + known() + validated = true + } - /** - * Returns the raw JSON value of [amc]. - * - * Unlike [amc], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("amc") @ExcludeMissing fun _amc(): JsonField = amc + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } - /** - * Returns the raw JSON value of [folioNumber]. - * - * Unlike [folioNumber], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("folio_number") - @ExcludeMissing - fun _folioNumber(): JsonField = folioNumber + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 - /** - * Returns the raw JSON value of [linkedHolders]. - * - * Unlike [linkedHolders], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("linked_holders") - @ExcludeMissing - fun _linkedHolders(): JsonField> = linkedHolders + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - /** - * Returns the raw JSON value of [registrar]. - * - * Unlike [registrar], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("registrar") @ExcludeMissing fun _registrar(): JsonField = registrar + return other is Type && value == other.value + } - /** - * Returns the raw JSON value of [schemes]. - * - * Unlike [schemes], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("schemes") @ExcludeMissing fun _schemes(): JsonField> = schemes + override fun hashCode() = value.hashCode() - /** - * Returns the raw JSON value of [value]. - * - * Unlike [value], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + override fun toString() = value.toString() + } - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + return other is Transaction && + additionalInfo == other.additionalInfo && + amount == other.amount && + balance == other.balance && + date == other.date && + description == other.description && + dividendRate == other.dividendRate && + nav == other.nav && + type == other.type && + units == other.units && + additionalProperties == other.additionalProperties + } - fun toBuilder() = Builder().from(this) + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + additionalProperties, + ) + } - companion object { + override fun hashCode(): Int = hashCode - /** Returns a mutable builder for constructing an instance of [MutualFund]. */ - @JvmStatic fun builder() = Builder() - } + override fun toString() = + "Transaction{additionalInfo=$additionalInfo, amount=$amount, balance=$balance, date=$date, description=$description, dividendRate=$dividendRate, nav=$nav, type=$type, units=$units, additionalProperties=$additionalProperties}" + } - /** A builder for [MutualFund]. */ - class Builder internal constructor() { + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - private var additionalInfo: JsonField = JsonMissing.of() - private var amc: JsonField = JsonMissing.of() - private var folioNumber: JsonField = JsonMissing.of() - private var linkedHolders: JsonField>? = null - private var registrar: JsonField = JsonMissing.of() - private var schemes: JsonField>? = null - private var value: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + return other is DematMutualFund && + additionalInfo == other.additionalInfo && + isin == other.isin && + name == other.name && + transactions == other.transactions && + units == other.units && + value == other.value && + additionalProperties == other.additionalProperties + } - @JvmSynthetic - internal fun from(mutualFund: MutualFund) = apply { - additionalInfo = mutualFund.additionalInfo - amc = mutualFund.amc - folioNumber = mutualFund.folioNumber - linkedHolders = mutualFund.linkedHolders.map { it.toMutableList() } - registrar = mutualFund.registrar - schemes = mutualFund.schemes.map { it.toMutableList() } - value = mutualFund.value - additionalProperties = mutualFund.additionalProperties.toMutableMap() - } + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + isin, + name, + transactions, + units, + value, + additionalProperties, + ) + } - /** Additional folio information */ - fun additionalInfo(additionalInfo: AdditionalInfo) = - additionalInfo(JsonField.of(additionalInfo)) + override fun hashCode(): Int = hashCode - /** - * Sets [Builder.additionalInfo] to an arbitrary JSON value. - * - * You should usually call [Builder.additionalInfo] with a well-typed [AdditionalInfo] - * value instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun additionalInfo(additionalInfo: JsonField) = apply { - this.additionalInfo = additionalInfo + override fun toString() = + "DematMutualFund{additionalInfo=$additionalInfo, isin=$isin, name=$name, transactions=$transactions, units=$units, value=$value, additionalProperties=$additionalProperties}" } - /** Asset Management Company name */ - fun amc(amc: String) = amc(JsonField.of(amc)) - - /** - * Sets [Builder.amc] to an arbitrary JSON value. - * - * You should usually call [Builder.amc] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun amc(amc: JsonField) = apply { this.amc = amc } + class Equity + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val isin: JsonField, + private val name: JsonField, + private val transactions: JsonField>, + private val units: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { - /** Folio number */ - fun folioNumber(folioNumber: String) = folioNumber(JsonField.of(folioNumber)) + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("isin") + @ExcludeMissing + isin: JsonField = JsonMissing.of(), + @JsonProperty("name") + @ExcludeMissing + name: JsonField = JsonMissing.of(), + @JsonProperty("transactions") + @ExcludeMissing + transactions: JsonField> = JsonMissing.of(), + @JsonProperty("units") + @ExcludeMissing + units: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(additionalInfo, isin, name, transactions, units, value, mutableMapOf()) - /** - * Sets [Builder.folioNumber] to an arbitrary JSON value. - * - * You should usually call [Builder.folioNumber] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun folioNumber(folioNumber: JsonField) = apply { - this.folioNumber = folioNumber - } + /** + * Additional information specific to the equity + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") - /** List of account holders linked to this mutual fund folio */ - fun linkedHolders(linkedHolders: List) = - linkedHolders(JsonField.of(linkedHolders)) + /** + * ISIN code of the equity + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun isin(): Optional = isin.getOptional("isin") - /** - * Sets [Builder.linkedHolders] to an arbitrary JSON value. - * - * You should usually call [Builder.linkedHolders] with a well-typed - * `List` value instead. This method is primarily for setting the field to - * an undocumented or not yet supported value. - */ - fun linkedHolders(linkedHolders: JsonField>) = apply { - this.linkedHolders = linkedHolders.map { it.toMutableList() } - } + /** + * Name of the equity + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") - /** - * Adds a single [LinkedHolder] to [linkedHolders]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addLinkedHolder(linkedHolder: LinkedHolder) = apply { - linkedHolders = - (linkedHolders ?: JsonField.of(mutableListOf())).also { - checkKnown("linkedHolders", it).add(linkedHolder) - } - } + /** + * List of transactions for this holding (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun transactions(): Optional> = + transactions.getOptional("transactions") - /** Registrar and Transfer Agent name */ - fun registrar(registrar: String) = registrar(JsonField.of(registrar)) + /** + * Number of units held + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun units(): Optional = units.getOptional("units") - /** - * Sets [Builder.registrar] to an arbitrary JSON value. - * - * You should usually call [Builder.registrar] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun registrar(registrar: JsonField) = apply { this.registrar = registrar } + /** + * Current market value of the holding + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") - fun schemes(schemes: List) = schemes(JsonField.of(schemes)) + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo - /** - * Sets [Builder.schemes] to an arbitrary JSON value. - * - * You should usually call [Builder.schemes] with a well-typed `List` value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun schemes(schemes: JsonField>) = apply { - this.schemes = schemes.map { it.toMutableList() } - } + /** + * Returns the raw JSON value of [isin]. + * + * Unlike [isin], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("isin") @ExcludeMissing fun _isin(): JsonField = isin - /** - * Adds a single [Scheme] to [schemes]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addScheme(scheme: Scheme) = apply { - schemes = - (schemes ?: JsonField.of(mutableListOf())).also { - checkKnown("schemes", it).add(scheme) - } - } + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name - /** Total value of the folio */ - fun value(value: Float) = value(JsonField.of(value)) + /** + * Returns the raw JSON value of [transactions]. + * + * Unlike [transactions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("transactions") + @ExcludeMissing + fun _transactions(): JsonField> = transactions - /** - * Sets [Builder.value] to an arbitrary JSON value. - * - * You should usually call [Builder.value] with a well-typed [Float] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun value(value: JsonField) = apply { this.value = value } + /** + * Returns the raw JSON value of [units]. + * + * Unlike [units], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - fun putAllAdditionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.putAll(additionalProperties) - } + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + fun toBuilder() = Builder().from(this) - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + companion object { - /** - * Returns an immutable instance of [MutualFund]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): MutualFund = - MutualFund( - additionalInfo, - amc, - folioNumber, - (linkedHolders ?: JsonMissing.of()).map { it.toImmutable() }, - registrar, - (schemes ?: JsonMissing.of()).map { it.toImmutable() }, - value, - additionalProperties.toMutableMap(), - ) - } + /** Returns a mutable builder for constructing an instance of [Equity]. */ + @JvmStatic fun builder() = Builder() + } - private var validated: Boolean = false + /** A builder for [Equity]. */ + class Builder internal constructor() { - fun validate(): MutualFund = apply { - if (validated) { - return@apply - } + private var additionalInfo: JsonField = JsonMissing.of() + private var isin: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var transactions: JsonField>? = null + private var units: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() - additionalInfo().ifPresent { it.validate() } - amc() - folioNumber() - linkedHolders().ifPresent { it.forEach { it.validate() } } - registrar() - schemes().ifPresent { it.forEach { it.validate() } } - value() - validated = true - } + @JvmSynthetic + internal fun from(equity: Equity) = apply { + additionalInfo = equity.additionalInfo + isin = equity.isin + name = equity.name + transactions = equity.transactions.map { it.toMutableList() } + units = equity.units + value = equity.value + additionalProperties = equity.additionalProperties.toMutableMap() + } - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + /** Additional information specific to the equity */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + - (if (amc.asKnown().isPresent) 1 else 0) + - (if (folioNumber.asKnown().isPresent) 1 else 0) + - (linkedHolders.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + - (if (registrar.asKnown().isPresent) 1 else 0) + - (schemes.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + - (if (value.asKnown().isPresent) 1 else 0) + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } - /** Additional folio information */ - class AdditionalInfo - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val kyc: JsonField, - private val pan: JsonField, - private val pankyc: JsonField, - private val additionalProperties: MutableMap, - ) { + /** ISIN code of the equity */ + fun isin(isin: String) = isin(JsonField.of(isin)) - @JsonCreator - private constructor( - @JsonProperty("kyc") @ExcludeMissing kyc: JsonField = JsonMissing.of(), - @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), - @JsonProperty("pankyc") @ExcludeMissing pankyc: JsonField = JsonMissing.of(), - ) : this(kyc, pan, pankyc, mutableMapOf()) + /** + * Sets [Builder.isin] to an arbitrary JSON value. + * + * You should usually call [Builder.isin] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun isin(isin: JsonField) = apply { this.isin = isin } - /** - * KYC status of the folio - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun kyc(): Optional = kyc.getOptional("kyc") + /** Name of the equity */ + fun name(name: String) = name(JsonField.of(name)) - /** - * PAN associated with the folio - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun pan(): Optional = pan.getOptional("pan") + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } - /** - * PAN KYC status - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun pankyc(): Optional = pankyc.getOptional("pankyc") + /** List of transactions for this holding (beta) */ + fun transactions(transactions: List) = + transactions(JsonField.of(transactions)) - /** - * Returns the raw JSON value of [kyc]. - * - * Unlike [kyc], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("kyc") @ExcludeMissing fun _kyc(): JsonField = kyc + /** + * Sets [Builder.transactions] to an arbitrary JSON value. + * + * You should usually call [Builder.transactions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun transactions(transactions: JsonField>) = apply { + this.transactions = transactions.map { it.toMutableList() } + } - /** - * Returns the raw JSON value of [pan]. - * - * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + /** + * Adds a single [Transaction] to [transactions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTransaction(transaction: Transaction) = apply { + transactions = + (transactions ?: JsonField.of(mutableListOf())).also { + checkKnown("transactions", it).add(transaction) + } + } - /** - * Returns the raw JSON value of [pankyc]. - * - * Unlike [pankyc], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("pankyc") @ExcludeMissing fun _pankyc(): JsonField = pankyc + /** Number of units held */ + fun units(units: Float) = units(JsonField.of(units)) - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** + * Sets [Builder.units] to an arbitrary JSON value. + * + * You should usually call [Builder.units] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun units(units: JsonField) = apply { this.units = units } - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + /** Current market value of the holding */ + fun value(value: Float) = value(JsonField.of(value)) - fun toBuilder() = Builder().from(this) + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } - companion object { + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - /** Returns a mutable builder for constructing an instance of [AdditionalInfo]. */ - @JvmStatic fun builder() = Builder() - } + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - /** A builder for [AdditionalInfo]. */ - class Builder internal constructor() { + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } - private var kyc: JsonField = JsonMissing.of() - private var pan: JsonField = JsonMissing.of() - private var pankyc: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } - @JvmSynthetic - internal fun from(additionalInfo: AdditionalInfo) = apply { - kyc = additionalInfo.kyc - pan = additionalInfo.pan - pankyc = additionalInfo.pankyc - additionalProperties = additionalInfo.additionalProperties.toMutableMap() + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Equity]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Equity = + Equity( + additionalInfo, + isin, + name, + (transactions ?: JsonMissing.of()).map { it.toImmutable() }, + units, + value, + additionalProperties.toMutableMap(), + ) } - /** KYC status of the folio */ - fun kyc(kyc: String) = kyc(JsonField.of(kyc)) + private var validated: Boolean = false - /** - * Sets [Builder.kyc] to an arbitrary JSON value. - * - * You should usually call [Builder.kyc] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun kyc(kyc: JsonField) = apply { this.kyc = kyc } + fun validate(): Equity = apply { + if (validated) { + return@apply + } - /** PAN associated with the folio */ - fun pan(pan: String) = pan(JsonField.of(pan)) + additionalInfo().ifPresent { it.validate() } + isin() + name() + transactions().ifPresent { it.forEach { it.validate() } } + units() + value() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } /** - * Sets [Builder.pan] to an arbitrary JSON value. + * Returns a score indicating how many valid values are contained in this object + * recursively. * - * You should usually call [Builder.pan] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. + * Used for best match union deserialization. */ - fun pan(pan: JsonField) = apply { this.pan = pan } + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (isin.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (transactions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (units.asKnown().isPresent) 1 else 0) + + (if (value.asKnown().isPresent) 1 else 0) - /** PAN KYC status */ - fun pankyc(pankyc: String) = pankyc(JsonField.of(pankyc)) + /** Additional information specific to the equity */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val closeUnits: JsonField, + private val openUnits: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("close_units") + @ExcludeMissing + closeUnits: JsonField = JsonMissing.of(), + @JsonProperty("open_units") + @ExcludeMissing + openUnits: JsonField = JsonMissing.of(), + ) : this(closeUnits, openUnits, mutableMapOf()) - /** - * Sets [Builder.pankyc] to an arbitrary JSON value. - * - * You should usually call [Builder.pankyc] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not - * yet supported value. - */ - fun pankyc(pankyc: JsonField) = apply { this.pankyc = pankyc } + /** + * Closing balance units for the statement period (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun closeUnits(): Optional = closeUnits.getOptional("close_units") - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * Opening balance units for the statement period (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun openUnits(): Optional = openUnits.getOptional("open_units") - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + /** + * Returns the raw JSON value of [closeUnits]. + * + * Unlike [closeUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("close_units") + @ExcludeMissing + fun _closeUnits(): JsonField = closeUnits - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) + /** + * Returns the raw JSON value of [openUnits]. + * + * Unlike [openUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("open_units") + @ExcludeMissing + fun _openUnits(): JsonField = openUnits + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) } - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + fun toBuilder() = Builder().from(this) - /** - * Returns an immutable instance of [AdditionalInfo]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): AdditionalInfo = - AdditionalInfo(kyc, pan, pankyc, additionalProperties.toMutableMap()) - } + companion object { - private var validated: Boolean = false + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } - fun validate(): AdditionalInfo = apply { - if (validated) { - return@apply - } + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { - kyc() - pan() - pankyc() - validated = true - } + private var closeUnits: JsonField = JsonMissing.of() + private var openUnits: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } - - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (kyc.asKnown().isPresent) 1 else 0) + - (if (pan.asKnown().isPresent) 1 else 0) + - (if (pankyc.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is AdditionalInfo && - kyc == other.kyc && - pan == other.pan && - pankyc == other.pankyc && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash(kyc, pan, pankyc, additionalProperties) - } - - override fun hashCode(): Int = hashCode + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + closeUnits = additionalInfo.closeUnits + openUnits = additionalInfo.openUnits + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() + } - override fun toString() = - "AdditionalInfo{kyc=$kyc, pan=$pan, pankyc=$pankyc, additionalProperties=$additionalProperties}" - } + /** Closing balance units for the statement period (beta) */ + fun closeUnits(closeUnits: Float?) = + closeUnits(JsonField.ofNullable(closeUnits)) - class LinkedHolder - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val name: JsonField, - private val pan: JsonField, - private val additionalProperties: MutableMap, - ) { + /** + * Alias for [Builder.closeUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun closeUnits(closeUnits: Float) = closeUnits(closeUnits as Float?) - @JsonCreator - private constructor( - @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), - @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), - ) : this(name, pan, mutableMapOf()) + /** + * Alias for calling [Builder.closeUnits] with `closeUnits.orElse(null)`. + */ + fun closeUnits(closeUnits: Optional) = + closeUnits(closeUnits.getOrNull()) - /** - * Name of the account holder - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun name(): Optional = name.getOptional("name") + /** + * Sets [Builder.closeUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.closeUnits] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun closeUnits(closeUnits: JsonField) = apply { + this.closeUnits = closeUnits + } - /** - * PAN of the account holder - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun pan(): Optional = pan.getOptional("pan") + /** Opening balance units for the statement period (beta) */ + fun openUnits(openUnits: Float?) = + openUnits(JsonField.ofNullable(openUnits)) - /** - * Returns the raw JSON value of [name]. - * - * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + /** + * Alias for [Builder.openUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun openUnits(openUnits: Float) = openUnits(openUnits as Float?) - /** - * Returns the raw JSON value of [pan]. - * - * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + /** Alias for calling [Builder.openUnits] with `openUnits.orElse(null)`. */ + fun openUnits(openUnits: Optional) = openUnits(openUnits.getOrNull()) - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** + * Sets [Builder.openUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.openUnits] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun openUnits(openUnits: JsonField) = apply { + this.openUnits = openUnits + } - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - fun toBuilder() = Builder().from(this) + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - companion object { + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } - /** Returns a mutable builder for constructing an instance of [LinkedHolder]. */ - @JvmStatic fun builder() = Builder() - } + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } - /** A builder for [LinkedHolder]. */ - class Builder internal constructor() { + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } - private var name: JsonField = JsonMissing.of() - private var pan: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + closeUnits, + openUnits, + additionalProperties.toMutableMap(), + ) + } - @JvmSynthetic - internal fun from(linkedHolder: LinkedHolder) = apply { - name = linkedHolder.name - pan = linkedHolder.pan - additionalProperties = linkedHolder.additionalProperties.toMutableMap() - } + private var validated: Boolean = false - /** Name of the account holder */ - fun name(name: String) = name(JsonField.of(name)) + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } - /** - * Sets [Builder.name] to an arbitrary JSON value. - * - * You should usually call [Builder.name] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun name(name: JsonField) = apply { this.name = name } + closeUnits() + openUnits() + validated = true + } - /** PAN of the account holder */ - fun pan(pan: String) = pan(JsonField.of(pan)) + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } - /** - * Sets [Builder.pan] to an arbitrary JSON value. - * - * You should usually call [Builder.pan] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun pan(pan: JsonField) = apply { this.pan = pan } + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (closeUnits.asKnown().isPresent) 1 else 0) + + (if (openUnits.asKnown().isPresent) 1 else 0) - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + return other is AdditionalInfo && + closeUnits == other.closeUnits && + openUnits == other.openUnits && + additionalProperties == other.additionalProperties + } - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) + private val hashCode: Int by lazy { + Objects.hash(closeUnits, openUnits, additionalProperties) } - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } + override fun hashCode(): Int = hashCode - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) + override fun toString() = + "AdditionalInfo{closeUnits=$closeUnits, openUnits=$openUnits, additionalProperties=$additionalProperties}" } /** - * Returns an immutable instance of [LinkedHolder]. - * - * Further updates to this [Builder] will not mutate the returned instance. + * Unified transaction schema for all holding types (MF folios, equities, bonds, + * etc.) */ - fun build(): LinkedHolder = - LinkedHolder(name, pan, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false + class Transaction + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val amount: JsonField, + private val balance: JsonField, + private val date: JsonField, + private val description: JsonField, + private val dividendRate: JsonField, + private val nav: JsonField, + private val type: JsonField, + private val units: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("amount") + @ExcludeMissing + amount: JsonField = JsonMissing.of(), + @JsonProperty("balance") + @ExcludeMissing + balance: JsonField = JsonMissing.of(), + @JsonProperty("date") + @ExcludeMissing + date: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("dividend_rate") + @ExcludeMissing + dividendRate: JsonField = JsonMissing.of(), + @JsonProperty("nav") + @ExcludeMissing + nav: JsonField = JsonMissing.of(), + @JsonProperty("type") + @ExcludeMissing + type: JsonField = JsonMissing.of(), + @JsonProperty("units") + @ExcludeMissing + units: JsonField = JsonMissing.of(), + ) : this( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + mutableMapOf(), + ) - fun validate(): LinkedHolder = apply { - if (validated) { - return@apply - } + /** + * Additional transaction-specific fields that vary by source + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") - name() - pan() - validated = true - } + /** + * Transaction amount in currency (computed from units × price/NAV) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + /** + * Balance units after transaction + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun balance(): Optional = balance.getOptional("balance") - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (name.asKnown().isPresent) 1 else 0) + (if (pan.asKnown().isPresent) 1 else 0) + /** + * Transaction date (YYYY-MM-DD) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun date(): Optional = date.getOptional("date") - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** + * Transaction description/particulars + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") - return other is LinkedHolder && - name == other.name && - pan == other.pan && - additionalProperties == other.additionalProperties - } + /** + * Dividend rate (for DIVIDEND_PAYOUT transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun dividendRate(): Optional = dividendRate.getOptional("dividend_rate") - private val hashCode: Int by lazy { Objects.hash(name, pan, additionalProperties) } + /** + * NAV/price per unit on transaction date + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun nav(): Optional = nav.getOptional("nav") - override fun hashCode(): Int = hashCode + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun type(): Optional = type.getOptional("type") - override fun toString() = - "LinkedHolder{name=$name, pan=$pan, additionalProperties=$additionalProperties}" - } + /** + * Number of units involved in transaction + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun units(): Optional = units.getOptional("units") - class Scheme - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val additionalInfo: JsonField, - private val cost: JsonField, - private val gain: JsonField, - private val isin: JsonField, - private val name: JsonField, - private val nav: JsonField, - private val nominees: JsonField>, - private val transactions: JsonField>, - private val type: JsonField, - private val units: JsonField, - private val value: JsonField, - private val additionalProperties: MutableMap, - ) { + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo - @JsonCreator - private constructor( - @JsonProperty("additional_info") - @ExcludeMissing - additionalInfo: JsonField = JsonMissing.of(), - @JsonProperty("cost") @ExcludeMissing cost: JsonField = JsonMissing.of(), - @JsonProperty("gain") @ExcludeMissing gain: JsonField = JsonMissing.of(), - @JsonProperty("isin") @ExcludeMissing isin: JsonField = JsonMissing.of(), - @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), - @JsonProperty("nav") @ExcludeMissing nav: JsonField = JsonMissing.of(), - @JsonProperty("nominees") - @ExcludeMissing - nominees: JsonField> = JsonMissing.of(), - @JsonProperty("transactions") - @ExcludeMissing - transactions: JsonField> = JsonMissing.of(), - @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), - @JsonProperty("units") @ExcludeMissing units: JsonField = JsonMissing.of(), - @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), - ) : this( - additionalInfo, - cost, - gain, - isin, - name, - nav, - nominees, - transactions, - type, - units, - value, - mutableMapOf(), - ) + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount - /** - * Additional information specific to the scheme - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun additionalInfo(): Optional = - additionalInfo.getOptional("additional_info") + /** + * Returns the raw JSON value of [balance]. + * + * Unlike [balance], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("balance") + @ExcludeMissing + fun _balance(): JsonField = balance - /** - * Cost of investment - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun cost(): Optional = cost.getOptional("cost") + /** + * Returns the raw JSON value of [date]. + * + * Unlike [date], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date - /** - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun gain(): Optional = gain.getOptional("gain") + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description - /** - * ISIN code of the scheme - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun isin(): Optional = isin.getOptional("isin") + /** + * Returns the raw JSON value of [dividendRate]. + * + * Unlike [dividendRate], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("dividend_rate") + @ExcludeMissing + fun _dividendRate(): JsonField = dividendRate - /** - * Scheme name - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun name(): Optional = name.getOptional("name") + /** + * Returns the raw JSON value of [nav]. + * + * Unlike [nav], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("nav") @ExcludeMissing fun _nav(): JsonField = nav - /** - * Net Asset Value per unit - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun nav(): Optional = nav.getOptional("nav") + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type - /** - * List of nominees - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun nominees(): Optional> = nominees.getOptional("nominees") + /** + * Returns the raw JSON value of [units]. + * + * Unlike [units], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units - /** - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun transactions(): Optional> = - transactions.getOptional("transactions") + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - /** - * Type of mutual fund scheme - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun type(): Optional = type.getOptional("type") + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - /** - * Number of units held - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun units(): Optional = units.getOptional("units") + fun toBuilder() = Builder().from(this) - /** - * Current market value of the holding - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. - * if the server responded with an unexpected value). - */ - fun value(): Optional = value.getOptional("value") + companion object { - /** - * Returns the raw JSON value of [additionalInfo]. - * - * Unlike [additionalInfo], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("additional_info") - @ExcludeMissing - fun _additionalInfo(): JsonField = additionalInfo + /** + * Returns a mutable builder for constructing an instance of [Transaction]. + */ + @JvmStatic fun builder() = Builder() + } - /** - * Returns the raw JSON value of [cost]. - * - * Unlike [cost], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("cost") @ExcludeMissing fun _cost(): JsonField = cost + /** A builder for [Transaction]. */ + class Builder internal constructor() { + + private var additionalInfo: JsonField = JsonMissing.of() + private var amount: JsonField = JsonMissing.of() + private var balance: JsonField = JsonMissing.of() + private var date: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var dividendRate: JsonField = JsonMissing.of() + private var nav: JsonField = JsonMissing.of() + private var type: JsonField = JsonMissing.of() + private var units: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(transaction: Transaction) = apply { + additionalInfo = transaction.additionalInfo + amount = transaction.amount + balance = transaction.balance + date = transaction.date + description = transaction.description + dividendRate = transaction.dividendRate + nav = transaction.nav + type = transaction.type + units = transaction.units + additionalProperties = transaction.additionalProperties.toMutableMap() + } - /** - * Returns the raw JSON value of [gain]. - * - * Unlike [gain], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("gain") @ExcludeMissing fun _gain(): JsonField = gain + /** Additional transaction-specific fields that vary by source */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) - /** - * Returns the raw JSON value of [isin]. - * - * Unlike [isin], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("isin") @ExcludeMissing fun _isin(): JsonField = isin + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } - /** - * Returns the raw JSON value of [name]. - * - * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + /** Transaction amount in currency (computed from units × price/NAV) */ + fun amount(amount: Float?) = amount(JsonField.ofNullable(amount)) - /** - * Returns the raw JSON value of [nav]. - * - * Unlike [nav], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("nav") @ExcludeMissing fun _nav(): JsonField = nav + /** + * Alias for [Builder.amount]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun amount(amount: Float) = amount(amount as Float?) - /** - * Returns the raw JSON value of [nominees]. - * - * Unlike [nominees], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("nominees") - @ExcludeMissing - fun _nominees(): JsonField> = nominees + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) - /** - * Returns the raw JSON value of [transactions]. - * - * Unlike [transactions], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("transactions") - @ExcludeMissing - fun _transactions(): JsonField> = transactions + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } - /** - * Returns the raw JSON value of [type]. - * - * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + /** Balance units after transaction */ + fun balance(balance: Float) = balance(JsonField.of(balance)) - /** - * Returns the raw JSON value of [units]. - * - * Unlike [units], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units + /** + * Sets [Builder.balance] to an arbitrary JSON value. + * + * You should usually call [Builder.balance] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun balance(balance: JsonField) = apply { this.balance = balance } - /** + /** Transaction date (YYYY-MM-DD) */ + fun date(date: LocalDate) = date(JsonField.of(date)) + + /** + * Sets [Builder.date] to an arbitrary JSON value. + * + * You should usually call [Builder.date] with a well-typed [LocalDate] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun date(date: JsonField) = apply { this.date = date } + + /** Transaction description/particulars */ + fun description(description: String) = + description(JsonField.of(description)) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } + + /** Dividend rate (for DIVIDEND_PAYOUT transactions) */ + fun dividendRate(dividendRate: Float?) = + dividendRate(JsonField.ofNullable(dividendRate)) + + /** + * Alias for [Builder.dividendRate]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun dividendRate(dividendRate: Float) = dividendRate(dividendRate as Float?) + + /** + * Alias for calling [Builder.dividendRate] with + * `dividendRate.orElse(null)`. + */ + fun dividendRate(dividendRate: Optional) = + dividendRate(dividendRate.getOrNull()) + + /** + * Sets [Builder.dividendRate] to an arbitrary JSON value. + * + * You should usually call [Builder.dividendRate] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun dividendRate(dividendRate: JsonField) = apply { + this.dividendRate = dividendRate + } + + /** NAV/price per unit on transaction date */ + fun nav(nav: Float?) = nav(JsonField.ofNullable(nav)) + + /** + * Alias for [Builder.nav]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun nav(nav: Float) = nav(nav as Float?) + + /** Alias for calling [Builder.nav] with `nav.orElse(null)`. */ + fun nav(nav: Optional) = nav(nav.getOrNull()) + + /** + * Sets [Builder.nav] to an arbitrary JSON value. + * + * You should usually call [Builder.nav] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun nav(nav: JsonField) = apply { this.nav = nav } + + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, + * DIVIDEND_PAYOUT, DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, + * STT_TAX, MISC, REVERSAL, UNKNOWN. + */ + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + /** Number of units involved in transaction */ + fun units(units: Float) = units(JsonField.of(units)) + + /** + * Sets [Builder.units] to an arbitrary JSON value. + * + * You should usually call [Builder.units] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun units(units: JsonField) = apply { this.units = units } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Transaction]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Transaction = + Transaction( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Transaction = apply { + if (validated) { + return@apply + } + + additionalInfo().ifPresent { it.validate() } + amount() + balance() + date() + description() + dividendRate() + nav() + type().ifPresent { it.validate() } + units() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (amount.asKnown().isPresent) 1 else 0) + + (if (balance.asKnown().isPresent) 1 else 0) + + (if (date.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (if (dividendRate.asKnown().isPresent) 1 else 0) + + (if (nav.asKnown().isPresent) 1 else 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (units.asKnown().isPresent) 1 else 0) + + /** Additional transaction-specific fields that vary by source */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val capitalWithdrawal: JsonField, + private val credit: JsonField, + private val debit: JsonField, + private val incomeDistribution: JsonField, + private val orderNo: JsonField, + private val price: JsonField, + private val stampDuty: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("capital_withdrawal") + @ExcludeMissing + capitalWithdrawal: JsonField = JsonMissing.of(), + @JsonProperty("credit") + @ExcludeMissing + credit: JsonField = JsonMissing.of(), + @JsonProperty("debit") + @ExcludeMissing + debit: JsonField = JsonMissing.of(), + @JsonProperty("income_distribution") + @ExcludeMissing + incomeDistribution: JsonField = JsonMissing.of(), + @JsonProperty("order_no") + @ExcludeMissing + orderNo: JsonField = JsonMissing.of(), + @JsonProperty("price") + @ExcludeMissing + price: JsonField = JsonMissing.of(), + @JsonProperty("stamp_duty") + @ExcludeMissing + stampDuty: JsonField = JsonMissing.of(), + ) : this( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + mutableMapOf(), + ) + + /** + * Capital withdrawal amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun capitalWithdrawal(): Optional = + capitalWithdrawal.getOptional("capital_withdrawal") + + /** + * Units credited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun credit(): Optional = credit.getOptional("credit") + + /** + * Units debited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun debit(): Optional = debit.getOptional("debit") + + /** + * Income distribution amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun incomeDistribution(): Optional = + incomeDistribution.getOptional("income_distribution") + + /** + * Order/transaction reference number (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun orderNo(): Optional = orderNo.getOptional("order_no") + + /** + * Price per unit (NSDL/CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun price(): Optional = price.getOptional("price") + + /** + * Stamp duty charged + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun stampDuty(): Optional = stampDuty.getOptional("stamp_duty") + + /** + * Returns the raw JSON value of [capitalWithdrawal]. + * + * Unlike [capitalWithdrawal], this method doesn't throw if the JSON field + * has an unexpected type. + */ + @JsonProperty("capital_withdrawal") + @ExcludeMissing + fun _capitalWithdrawal(): JsonField = capitalWithdrawal + + /** + * Returns the raw JSON value of [credit]. + * + * Unlike [credit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("credit") + @ExcludeMissing + fun _credit(): JsonField = credit + + /** + * Returns the raw JSON value of [debit]. + * + * Unlike [debit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("debit") + @ExcludeMissing + fun _debit(): JsonField = debit + + /** + * Returns the raw JSON value of [incomeDistribution]. + * + * Unlike [incomeDistribution], this method doesn't throw if the JSON field + * has an unexpected type. + */ + @JsonProperty("income_distribution") + @ExcludeMissing + fun _incomeDistribution(): JsonField = incomeDistribution + + /** + * Returns the raw JSON value of [orderNo]. + * + * Unlike [orderNo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("order_no") + @ExcludeMissing + fun _orderNo(): JsonField = orderNo + + /** + * Returns the raw JSON value of [price]. + * + * Unlike [price], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("price") + @ExcludeMissing + fun _price(): JsonField = price + + /** + * Returns the raw JSON value of [stampDuty]. + * + * Unlike [stampDuty], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("stamp_duty") + @ExcludeMissing + fun _stampDuty(): JsonField = stampDuty + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { + + private var capitalWithdrawal: JsonField = JsonMissing.of() + private var credit: JsonField = JsonMissing.of() + private var debit: JsonField = JsonMissing.of() + private var incomeDistribution: JsonField = JsonMissing.of() + private var orderNo: JsonField = JsonMissing.of() + private var price: JsonField = JsonMissing.of() + private var stampDuty: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + capitalWithdrawal = additionalInfo.capitalWithdrawal + credit = additionalInfo.credit + debit = additionalInfo.debit + incomeDistribution = additionalInfo.incomeDistribution + orderNo = additionalInfo.orderNo + price = additionalInfo.price + stampDuty = additionalInfo.stampDuty + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() + } + + /** Capital withdrawal amount (CDSL MF transactions) */ + fun capitalWithdrawal(capitalWithdrawal: Float) = + capitalWithdrawal(JsonField.of(capitalWithdrawal)) + + /** + * Sets [Builder.capitalWithdrawal] to an arbitrary JSON value. + * + * You should usually call [Builder.capitalWithdrawal] with a well-typed + * [Float] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun capitalWithdrawal(capitalWithdrawal: JsonField) = apply { + this.capitalWithdrawal = capitalWithdrawal + } + + /** Units credited (demat transactions) */ + fun credit(credit: Float) = credit(JsonField.of(credit)) + + /** + * Sets [Builder.credit] to an arbitrary JSON value. + * + * You should usually call [Builder.credit] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun credit(credit: JsonField) = apply { this.credit = credit } + + /** Units debited (demat transactions) */ + fun debit(debit: Float) = debit(JsonField.of(debit)) + + /** + * Sets [Builder.debit] to an arbitrary JSON value. + * + * You should usually call [Builder.debit] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun debit(debit: JsonField) = apply { this.debit = debit } + + /** Income distribution amount (CDSL MF transactions) */ + fun incomeDistribution(incomeDistribution: Float) = + incomeDistribution(JsonField.of(incomeDistribution)) + + /** + * Sets [Builder.incomeDistribution] to an arbitrary JSON value. + * + * You should usually call [Builder.incomeDistribution] with a + * well-typed [Float] value instead. This method is primarily for + * setting the field to an undocumented or not yet supported value. + */ + fun incomeDistribution(incomeDistribution: JsonField) = apply { + this.incomeDistribution = incomeDistribution + } + + /** Order/transaction reference number (demat transactions) */ + fun orderNo(orderNo: String) = orderNo(JsonField.of(orderNo)) + + /** + * Sets [Builder.orderNo] to an arbitrary JSON value. + * + * You should usually call [Builder.orderNo] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun orderNo(orderNo: JsonField) = apply { + this.orderNo = orderNo + } + + /** Price per unit (NSDL/CDSL MF transactions) */ + fun price(price: Float) = price(JsonField.of(price)) + + /** + * Sets [Builder.price] to an arbitrary JSON value. + * + * You should usually call [Builder.price] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun price(price: JsonField) = apply { this.price = price } + + /** Stamp duty charged */ + fun stampDuty(stampDuty: Float) = stampDuty(JsonField.of(stampDuty)) + + /** + * Sets [Builder.stampDuty] to an arbitrary JSON value. + * + * You should usually call [Builder.stampDuty] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun stampDuty(stampDuty: JsonField) = apply { + this.stampDuty = stampDuty + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } + + capitalWithdrawal() + credit() + debit() + incomeDistribution() + orderNo() + price() + stampDuty() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (capitalWithdrawal.asKnown().isPresent) 1 else 0) + + (if (credit.asKnown().isPresent) 1 else 0) + + (if (debit.asKnown().isPresent) 1 else 0) + + (if (incomeDistribution.asKnown().isPresent) 1 else 0) + + (if (orderNo.asKnown().isPresent) 1 else 0) + + (if (price.asKnown().isPresent) 1 else 0) + + (if (stampDuty.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AdditionalInfo && + capitalWithdrawal == other.capitalWithdrawal && + credit == other.credit && + debit == other.debit && + incomeDistribution == other.incomeDistribution && + orderNo == other.orderNo && + price == other.price && + stampDuty == other.stampDuty && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{capitalWithdrawal=$capitalWithdrawal, credit=$credit, debit=$debit, incomeDistribution=$incomeDistribution, orderNo=$orderNo, price=$price, stampDuty=$stampDuty, additionalProperties=$additionalProperties}" + } + + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + */ + class Type + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data + * that doesn't match any known member, and you want to know that value. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value + + companion object { + + @JvmField val PURCHASE = of("PURCHASE") + + @JvmField val PURCHASE_SIP = of("PURCHASE_SIP") + + @JvmField val REDEMPTION = of("REDEMPTION") + + @JvmField val SWITCH_IN = of("SWITCH_IN") + + @JvmField val SWITCH_IN_MERGER = of("SWITCH_IN_MERGER") + + @JvmField val SWITCH_OUT = of("SWITCH_OUT") + + @JvmField val SWITCH_OUT_MERGER = of("SWITCH_OUT_MERGER") + + @JvmField val DIVIDEND_PAYOUT = of("DIVIDEND_PAYOUT") + + @JvmField val DIVIDEND_REINVEST = of("DIVIDEND_REINVEST") + + @JvmField val SEGREGATION = of("SEGREGATION") + + @JvmField val STAMP_DUTY_TAX = of("STAMP_DUTY_TAX") + + @JvmField val TDS_TAX = of("TDS_TAX") + + @JvmField val STT_TAX = of("STT_TAX") + + @JvmField val MISC = of("MISC") + + @JvmField val REVERSAL = of("REVERSAL") + + @JvmField val UNKNOWN = of("UNKNOWN") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API + * may respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + /** + * An enum member indicating that [Type] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always + * known or if you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PURCHASE -> Value.PURCHASE + PURCHASE_SIP -> Value.PURCHASE_SIP + REDEMPTION -> Value.REDEMPTION + SWITCH_IN -> Value.SWITCH_IN + SWITCH_IN_MERGER -> Value.SWITCH_IN_MERGER + SWITCH_OUT -> Value.SWITCH_OUT + SWITCH_OUT_MERGER -> Value.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Value.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Value.DIVIDEND_REINVEST + SEGREGATION -> Value.SEGREGATION + STAMP_DUTY_TAX -> Value.STAMP_DUTY_TAX + TDS_TAX -> Value.TDS_TAX + STT_TAX -> Value.STT_TAX + MISC -> Value.MISC + REVERSAL -> Value.REVERSAL + UNKNOWN -> Value.UNKNOWN + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always + * known and don't want to throw for the unknown case. + * + * @throws CasParserInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + PURCHASE -> Known.PURCHASE + PURCHASE_SIP -> Known.PURCHASE_SIP + REDEMPTION -> Known.REDEMPTION + SWITCH_IN -> Known.SWITCH_IN + SWITCH_IN_MERGER -> Known.SWITCH_IN_MERGER + SWITCH_OUT -> Known.SWITCH_OUT + SWITCH_OUT_MERGER -> Known.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Known.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Known.DIVIDEND_REINVEST + SEGREGATION -> Known.SEGREGATION + STAMP_DUTY_TAX -> Known.STAMP_DUTY_TAX + TDS_TAX -> Known.TDS_TAX + STT_TAX -> Known.STT_TAX + MISC -> Known.MISC + REVERSAL -> Known.REVERSAL + UNKNOWN -> Known.UNKNOWN + else -> throw CasParserInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily + * for debugging and generally doesn't throw. + * + * @throws CasParserInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CasParserInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Transaction && + additionalInfo == other.additionalInfo && + amount == other.amount && + balance == other.balance && + date == other.date && + description == other.description && + dividendRate == other.dividendRate && + nav == other.nav && + type == other.type && + units == other.units && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Transaction{additionalInfo=$additionalInfo, amount=$amount, balance=$balance, date=$date, description=$description, dividendRate=$dividendRate, nav=$nav, type=$type, units=$units, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Equity && + additionalInfo == other.additionalInfo && + isin == other.isin && + name == other.name && + transactions == other.transactions && + units == other.units && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + isin, + name, + transactions, + units, + value, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Equity{additionalInfo=$additionalInfo, isin=$isin, name=$name, transactions=$transactions, units=$units, value=$value, additionalProperties=$additionalProperties}" + } + + class GovernmentSecurity + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val isin: JsonField, + private val name: JsonField, + private val transactions: JsonField>, + private val units: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("isin") + @ExcludeMissing + isin: JsonField = JsonMissing.of(), + @JsonProperty("name") + @ExcludeMissing + name: JsonField = JsonMissing.of(), + @JsonProperty("transactions") + @ExcludeMissing + transactions: JsonField> = JsonMissing.of(), + @JsonProperty("units") + @ExcludeMissing + units: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(additionalInfo, isin, name, transactions, units, value, mutableMapOf()) + + /** + * Additional information specific to the government security + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") + + /** + * ISIN code of the government security + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun isin(): Optional = isin.getOptional("isin") + + /** + * Name of the government security + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * List of transactions for this holding (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun transactions(): Optional> = + transactions.getOptional("transactions") + + /** + * Number of units held + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun units(): Optional = units.getOptional("units") + + /** + * Current market value of the holding + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo + + /** + * Returns the raw JSON value of [isin]. + * + * Unlike [isin], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("isin") @ExcludeMissing fun _isin(): JsonField = isin + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [transactions]. + * + * Unlike [transactions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("transactions") + @ExcludeMissing + fun _transactions(): JsonField> = transactions + + /** + * Returns the raw JSON value of [units]. + * + * Unlike [units], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [GovernmentSecurity]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [GovernmentSecurity]. */ + class Builder internal constructor() { + + private var additionalInfo: JsonField = JsonMissing.of() + private var isin: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var transactions: JsonField>? = null + private var units: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(governmentSecurity: GovernmentSecurity) = apply { + additionalInfo = governmentSecurity.additionalInfo + isin = governmentSecurity.isin + name = governmentSecurity.name + transactions = governmentSecurity.transactions.map { it.toMutableList() } + units = governmentSecurity.units + value = governmentSecurity.value + additionalProperties = + governmentSecurity.additionalProperties.toMutableMap() + } + + /** Additional information specific to the government security */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) + + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } + + /** ISIN code of the government security */ + fun isin(isin: String) = isin(JsonField.of(isin)) + + /** + * Sets [Builder.isin] to an arbitrary JSON value. + * + * You should usually call [Builder.isin] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun isin(isin: JsonField) = apply { this.isin = isin } + + /** Name of the government security */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** List of transactions for this holding (beta) */ + fun transactions(transactions: List) = + transactions(JsonField.of(transactions)) + + /** + * Sets [Builder.transactions] to an arbitrary JSON value. + * + * You should usually call [Builder.transactions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun transactions(transactions: JsonField>) = apply { + this.transactions = transactions.map { it.toMutableList() } + } + + /** + * Adds a single [Transaction] to [transactions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTransaction(transaction: Transaction) = apply { + transactions = + (transactions ?: JsonField.of(mutableListOf())).also { + checkKnown("transactions", it).add(transaction) + } + } + + /** Number of units held */ + fun units(units: Float) = units(JsonField.of(units)) + + /** + * Sets [Builder.units] to an arbitrary JSON value. + * + * You should usually call [Builder.units] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun units(units: JsonField) = apply { this.units = units } + + /** Current market value of the holding */ + fun value(value: Float) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [GovernmentSecurity]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): GovernmentSecurity = + GovernmentSecurity( + additionalInfo, + isin, + name, + (transactions ?: JsonMissing.of()).map { it.toImmutable() }, + units, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): GovernmentSecurity = apply { + if (validated) { + return@apply + } + + additionalInfo().ifPresent { it.validate() } + isin() + name() + transactions().ifPresent { it.forEach { it.validate() } } + units() + value() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (isin.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (transactions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (units.asKnown().isPresent) 1 else 0) + + (if (value.asKnown().isPresent) 1 else 0) + + /** Additional information specific to the government security */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val closeUnits: JsonField, + private val openUnits: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("close_units") + @ExcludeMissing + closeUnits: JsonField = JsonMissing.of(), + @JsonProperty("open_units") + @ExcludeMissing + openUnits: JsonField = JsonMissing.of(), + ) : this(closeUnits, openUnits, mutableMapOf()) + + /** + * Closing balance units for the statement period (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun closeUnits(): Optional = closeUnits.getOptional("close_units") + + /** + * Opening balance units for the statement period (beta) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun openUnits(): Optional = openUnits.getOptional("open_units") + + /** + * Returns the raw JSON value of [closeUnits]. + * + * Unlike [closeUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("close_units") + @ExcludeMissing + fun _closeUnits(): JsonField = closeUnits + + /** + * Returns the raw JSON value of [openUnits]. + * + * Unlike [openUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("open_units") + @ExcludeMissing + fun _openUnits(): JsonField = openUnits + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { + + private var closeUnits: JsonField = JsonMissing.of() + private var openUnits: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + closeUnits = additionalInfo.closeUnits + openUnits = additionalInfo.openUnits + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() + } + + /** Closing balance units for the statement period (beta) */ + fun closeUnits(closeUnits: Float?) = + closeUnits(JsonField.ofNullable(closeUnits)) + + /** + * Alias for [Builder.closeUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun closeUnits(closeUnits: Float) = closeUnits(closeUnits as Float?) + + /** + * Alias for calling [Builder.closeUnits] with `closeUnits.orElse(null)`. + */ + fun closeUnits(closeUnits: Optional) = + closeUnits(closeUnits.getOrNull()) + + /** + * Sets [Builder.closeUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.closeUnits] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun closeUnits(closeUnits: JsonField) = apply { + this.closeUnits = closeUnits + } + + /** Opening balance units for the statement period (beta) */ + fun openUnits(openUnits: Float?) = + openUnits(JsonField.ofNullable(openUnits)) + + /** + * Alias for [Builder.openUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun openUnits(openUnits: Float) = openUnits(openUnits as Float?) + + /** Alias for calling [Builder.openUnits] with `openUnits.orElse(null)`. */ + fun openUnits(openUnits: Optional) = openUnits(openUnits.getOrNull()) + + /** + * Sets [Builder.openUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.openUnits] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun openUnits(openUnits: JsonField) = apply { + this.openUnits = openUnits + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + closeUnits, + openUnits, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } + + closeUnits() + openUnits() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (closeUnits.asKnown().isPresent) 1 else 0) + + (if (openUnits.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AdditionalInfo && + closeUnits == other.closeUnits && + openUnits == other.openUnits && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(closeUnits, openUnits, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{closeUnits=$closeUnits, openUnits=$openUnits, additionalProperties=$additionalProperties}" + } + + /** + * Unified transaction schema for all holding types (MF folios, equities, bonds, + * etc.) + */ + class Transaction + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val amount: JsonField, + private val balance: JsonField, + private val date: JsonField, + private val description: JsonField, + private val dividendRate: JsonField, + private val nav: JsonField, + private val type: JsonField, + private val units: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("amount") + @ExcludeMissing + amount: JsonField = JsonMissing.of(), + @JsonProperty("balance") + @ExcludeMissing + balance: JsonField = JsonMissing.of(), + @JsonProperty("date") + @ExcludeMissing + date: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + description: JsonField = JsonMissing.of(), + @JsonProperty("dividend_rate") + @ExcludeMissing + dividendRate: JsonField = JsonMissing.of(), + @JsonProperty("nav") + @ExcludeMissing + nav: JsonField = JsonMissing.of(), + @JsonProperty("type") + @ExcludeMissing + type: JsonField = JsonMissing.of(), + @JsonProperty("units") + @ExcludeMissing + units: JsonField = JsonMissing.of(), + ) : this( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + mutableMapOf(), + ) + + /** + * Additional transaction-specific fields that vary by source + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") + + /** + * Transaction amount in currency (computed from units × price/NAV) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun amount(): Optional = amount.getOptional("amount") + + /** + * Balance units after transaction + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun balance(): Optional = balance.getOptional("balance") + + /** + * Transaction date (YYYY-MM-DD) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun date(): Optional = date.getOptional("date") + + /** + * Transaction description/particulars + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun description(): Optional = description.getOptional("description") + + /** + * Dividend rate (for DIVIDEND_PAYOUT transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun dividendRate(): Optional = dividendRate.getOptional("dividend_rate") + + /** + * NAV/price per unit on transaction date + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun nav(): Optional = nav.getOptional("nav") + + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun type(): Optional = type.getOptional("type") + + /** + * Number of units involved in transaction + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun units(): Optional = units.getOptional("units") + + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + + /** + * Returns the raw JSON value of [balance]. + * + * Unlike [balance], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("balance") + @ExcludeMissing + fun _balance(): JsonField = balance + + /** + * Returns the raw JSON value of [date]. + * + * Unlike [date], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description + + /** + * Returns the raw JSON value of [dividendRate]. + * + * Unlike [dividendRate], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("dividend_rate") + @ExcludeMissing + fun _dividendRate(): JsonField = dividendRate + + /** + * Returns the raw JSON value of [nav]. + * + * Unlike [nav], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("nav") @ExcludeMissing fun _nav(): JsonField = nav + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [units]. + * + * Unlike [units], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Transaction]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Transaction]. */ + class Builder internal constructor() { + + private var additionalInfo: JsonField = JsonMissing.of() + private var amount: JsonField = JsonMissing.of() + private var balance: JsonField = JsonMissing.of() + private var date: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var dividendRate: JsonField = JsonMissing.of() + private var nav: JsonField = JsonMissing.of() + private var type: JsonField = JsonMissing.of() + private var units: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(transaction: Transaction) = apply { + additionalInfo = transaction.additionalInfo + amount = transaction.amount + balance = transaction.balance + date = transaction.date + description = transaction.description + dividendRate = transaction.dividendRate + nav = transaction.nav + type = transaction.type + units = transaction.units + additionalProperties = transaction.additionalProperties.toMutableMap() + } + + /** Additional transaction-specific fields that vary by source */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) + + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } + + /** Transaction amount in currency (computed from units × price/NAV) */ + fun amount(amount: Float?) = amount(JsonField.ofNullable(amount)) + + /** + * Alias for [Builder.amount]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun amount(amount: Float) = amount(amount as Float?) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** Balance units after transaction */ + fun balance(balance: Float) = balance(JsonField.of(balance)) + + /** + * Sets [Builder.balance] to an arbitrary JSON value. + * + * You should usually call [Builder.balance] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun balance(balance: JsonField) = apply { this.balance = balance } + + /** Transaction date (YYYY-MM-DD) */ + fun date(date: LocalDate) = date(JsonField.of(date)) + + /** + * Sets [Builder.date] to an arbitrary JSON value. + * + * You should usually call [Builder.date] with a well-typed [LocalDate] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun date(date: JsonField) = apply { this.date = date } + + /** Transaction description/particulars */ + fun description(description: String) = + description(JsonField.of(description)) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun description(description: JsonField) = apply { + this.description = description + } + + /** Dividend rate (for DIVIDEND_PAYOUT transactions) */ + fun dividendRate(dividendRate: Float?) = + dividendRate(JsonField.ofNullable(dividendRate)) + + /** + * Alias for [Builder.dividendRate]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun dividendRate(dividendRate: Float) = dividendRate(dividendRate as Float?) + + /** + * Alias for calling [Builder.dividendRate] with + * `dividendRate.orElse(null)`. + */ + fun dividendRate(dividendRate: Optional) = + dividendRate(dividendRate.getOrNull()) + + /** + * Sets [Builder.dividendRate] to an arbitrary JSON value. + * + * You should usually call [Builder.dividendRate] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun dividendRate(dividendRate: JsonField) = apply { + this.dividendRate = dividendRate + } + + /** NAV/price per unit on transaction date */ + fun nav(nav: Float?) = nav(JsonField.ofNullable(nav)) + + /** + * Alias for [Builder.nav]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun nav(nav: Float) = nav(nav as Float?) + + /** Alias for calling [Builder.nav] with `nav.orElse(null)`. */ + fun nav(nav: Optional) = nav(nav.getOrNull()) + + /** + * Sets [Builder.nav] to an arbitrary JSON value. + * + * You should usually call [Builder.nav] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun nav(nav: JsonField) = apply { this.nav = nav } + + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, + * DIVIDEND_PAYOUT, DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, + * STT_TAX, MISC, REVERSAL, UNKNOWN. + */ + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + /** Number of units involved in transaction */ + fun units(units: Float) = units(JsonField.of(units)) + + /** + * Sets [Builder.units] to an arbitrary JSON value. + * + * You should usually call [Builder.units] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun units(units: JsonField) = apply { this.units = units } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Transaction]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Transaction = + Transaction( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Transaction = apply { + if (validated) { + return@apply + } + + additionalInfo().ifPresent { it.validate() } + amount() + balance() + date() + description() + dividendRate() + nav() + type().ifPresent { it.validate() } + units() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (amount.asKnown().isPresent) 1 else 0) + + (if (balance.asKnown().isPresent) 1 else 0) + + (if (date.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (if (dividendRate.asKnown().isPresent) 1 else 0) + + (if (nav.asKnown().isPresent) 1 else 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (units.asKnown().isPresent) 1 else 0) + + /** Additional transaction-specific fields that vary by source */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val capitalWithdrawal: JsonField, + private val credit: JsonField, + private val debit: JsonField, + private val incomeDistribution: JsonField, + private val orderNo: JsonField, + private val price: JsonField, + private val stampDuty: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("capital_withdrawal") + @ExcludeMissing + capitalWithdrawal: JsonField = JsonMissing.of(), + @JsonProperty("credit") + @ExcludeMissing + credit: JsonField = JsonMissing.of(), + @JsonProperty("debit") + @ExcludeMissing + debit: JsonField = JsonMissing.of(), + @JsonProperty("income_distribution") + @ExcludeMissing + incomeDistribution: JsonField = JsonMissing.of(), + @JsonProperty("order_no") + @ExcludeMissing + orderNo: JsonField = JsonMissing.of(), + @JsonProperty("price") + @ExcludeMissing + price: JsonField = JsonMissing.of(), + @JsonProperty("stamp_duty") + @ExcludeMissing + stampDuty: JsonField = JsonMissing.of(), + ) : this( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + mutableMapOf(), + ) + + /** + * Capital withdrawal amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun capitalWithdrawal(): Optional = + capitalWithdrawal.getOptional("capital_withdrawal") + + /** + * Units credited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun credit(): Optional = credit.getOptional("credit") + + /** + * Units debited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun debit(): Optional = debit.getOptional("debit") + + /** + * Income distribution amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun incomeDistribution(): Optional = + incomeDistribution.getOptional("income_distribution") + + /** + * Order/transaction reference number (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun orderNo(): Optional = orderNo.getOptional("order_no") + + /** + * Price per unit (NSDL/CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun price(): Optional = price.getOptional("price") + + /** + * Stamp duty charged + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun stampDuty(): Optional = stampDuty.getOptional("stamp_duty") + + /** + * Returns the raw JSON value of [capitalWithdrawal]. + * + * Unlike [capitalWithdrawal], this method doesn't throw if the JSON field + * has an unexpected type. + */ + @JsonProperty("capital_withdrawal") + @ExcludeMissing + fun _capitalWithdrawal(): JsonField = capitalWithdrawal + + /** + * Returns the raw JSON value of [credit]. + * + * Unlike [credit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("credit") + @ExcludeMissing + fun _credit(): JsonField = credit + + /** + * Returns the raw JSON value of [debit]. + * + * Unlike [debit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("debit") + @ExcludeMissing + fun _debit(): JsonField = debit + + /** + * Returns the raw JSON value of [incomeDistribution]. + * + * Unlike [incomeDistribution], this method doesn't throw if the JSON field + * has an unexpected type. + */ + @JsonProperty("income_distribution") + @ExcludeMissing + fun _incomeDistribution(): JsonField = incomeDistribution + + /** + * Returns the raw JSON value of [orderNo]. + * + * Unlike [orderNo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("order_no") + @ExcludeMissing + fun _orderNo(): JsonField = orderNo + + /** + * Returns the raw JSON value of [price]. + * + * Unlike [price], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("price") + @ExcludeMissing + fun _price(): JsonField = price + + /** + * Returns the raw JSON value of [stampDuty]. + * + * Unlike [stampDuty], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("stamp_duty") + @ExcludeMissing + fun _stampDuty(): JsonField = stampDuty + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { + + private var capitalWithdrawal: JsonField = JsonMissing.of() + private var credit: JsonField = JsonMissing.of() + private var debit: JsonField = JsonMissing.of() + private var incomeDistribution: JsonField = JsonMissing.of() + private var orderNo: JsonField = JsonMissing.of() + private var price: JsonField = JsonMissing.of() + private var stampDuty: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + capitalWithdrawal = additionalInfo.capitalWithdrawal + credit = additionalInfo.credit + debit = additionalInfo.debit + incomeDistribution = additionalInfo.incomeDistribution + orderNo = additionalInfo.orderNo + price = additionalInfo.price + stampDuty = additionalInfo.stampDuty + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() + } + + /** Capital withdrawal amount (CDSL MF transactions) */ + fun capitalWithdrawal(capitalWithdrawal: Float) = + capitalWithdrawal(JsonField.of(capitalWithdrawal)) + + /** + * Sets [Builder.capitalWithdrawal] to an arbitrary JSON value. + * + * You should usually call [Builder.capitalWithdrawal] with a well-typed + * [Float] value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun capitalWithdrawal(capitalWithdrawal: JsonField) = apply { + this.capitalWithdrawal = capitalWithdrawal + } + + /** Units credited (demat transactions) */ + fun credit(credit: Float) = credit(JsonField.of(credit)) + + /** + * Sets [Builder.credit] to an arbitrary JSON value. + * + * You should usually call [Builder.credit] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun credit(credit: JsonField) = apply { this.credit = credit } + + /** Units debited (demat transactions) */ + fun debit(debit: Float) = debit(JsonField.of(debit)) + + /** + * Sets [Builder.debit] to an arbitrary JSON value. + * + * You should usually call [Builder.debit] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun debit(debit: JsonField) = apply { this.debit = debit } + + /** Income distribution amount (CDSL MF transactions) */ + fun incomeDistribution(incomeDistribution: Float) = + incomeDistribution(JsonField.of(incomeDistribution)) + + /** + * Sets [Builder.incomeDistribution] to an arbitrary JSON value. + * + * You should usually call [Builder.incomeDistribution] with a + * well-typed [Float] value instead. This method is primarily for + * setting the field to an undocumented or not yet supported value. + */ + fun incomeDistribution(incomeDistribution: JsonField) = apply { + this.incomeDistribution = incomeDistribution + } + + /** Order/transaction reference number (demat transactions) */ + fun orderNo(orderNo: String) = orderNo(JsonField.of(orderNo)) + + /** + * Sets [Builder.orderNo] to an arbitrary JSON value. + * + * You should usually call [Builder.orderNo] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun orderNo(orderNo: JsonField) = apply { + this.orderNo = orderNo + } + + /** Price per unit (NSDL/CDSL MF transactions) */ + fun price(price: Float) = price(JsonField.of(price)) + + /** + * Sets [Builder.price] to an arbitrary JSON value. + * + * You should usually call [Builder.price] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun price(price: JsonField) = apply { this.price = price } + + /** Stamp duty charged */ + fun stampDuty(stampDuty: Float) = stampDuty(JsonField.of(stampDuty)) + + /** + * Sets [Builder.stampDuty] to an arbitrary JSON value. + * + * You should usually call [Builder.stampDuty] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun stampDuty(stampDuty: JsonField) = apply { + this.stampDuty = stampDuty + } + + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } + + capitalWithdrawal() + credit() + debit() + incomeDistribution() + orderNo() + price() + stampDuty() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (capitalWithdrawal.asKnown().isPresent) 1 else 0) + + (if (credit.asKnown().isPresent) 1 else 0) + + (if (debit.asKnown().isPresent) 1 else 0) + + (if (incomeDistribution.asKnown().isPresent) 1 else 0) + + (if (orderNo.asKnown().isPresent) 1 else 0) + + (if (price.asKnown().isPresent) 1 else 0) + + (if (stampDuty.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AdditionalInfo && + capitalWithdrawal == other.capitalWithdrawal && + credit == other.credit && + debit == other.debit && + incomeDistribution == other.incomeDistribution && + orderNo == other.orderNo && + price == other.price && + stampDuty == other.stampDuty && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{capitalWithdrawal=$capitalWithdrawal, credit=$credit, debit=$debit, incomeDistribution=$incomeDistribution, orderNo=$orderNo, price=$price, stampDuty=$stampDuty, additionalProperties=$additionalProperties}" + } + + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + */ + class Type + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data + * that doesn't match any known member, and you want to know that value. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value + + companion object { + + @JvmField val PURCHASE = of("PURCHASE") + + @JvmField val PURCHASE_SIP = of("PURCHASE_SIP") + + @JvmField val REDEMPTION = of("REDEMPTION") + + @JvmField val SWITCH_IN = of("SWITCH_IN") + + @JvmField val SWITCH_IN_MERGER = of("SWITCH_IN_MERGER") + + @JvmField val SWITCH_OUT = of("SWITCH_OUT") + + @JvmField val SWITCH_OUT_MERGER = of("SWITCH_OUT_MERGER") + + @JvmField val DIVIDEND_PAYOUT = of("DIVIDEND_PAYOUT") + + @JvmField val DIVIDEND_REINVEST = of("DIVIDEND_REINVEST") + + @JvmField val SEGREGATION = of("SEGREGATION") + + @JvmField val STAMP_DUTY_TAX = of("STAMP_DUTY_TAX") + + @JvmField val TDS_TAX = of("TDS_TAX") + + @JvmField val STT_TAX = of("STT_TAX") + + @JvmField val MISC = of("MISC") + + @JvmField val REVERSAL = of("REVERSAL") + + @JvmField val UNKNOWN = of("UNKNOWN") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API + * may respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + /** + * An enum member indicating that [Type] was instantiated with an + * unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always + * known or if you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + PURCHASE -> Value.PURCHASE + PURCHASE_SIP -> Value.PURCHASE_SIP + REDEMPTION -> Value.REDEMPTION + SWITCH_IN -> Value.SWITCH_IN + SWITCH_IN_MERGER -> Value.SWITCH_IN_MERGER + SWITCH_OUT -> Value.SWITCH_OUT + SWITCH_OUT_MERGER -> Value.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Value.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Value.DIVIDEND_REINVEST + SEGREGATION -> Value.SEGREGATION + STAMP_DUTY_TAX -> Value.STAMP_DUTY_TAX + TDS_TAX -> Value.TDS_TAX + STT_TAX -> Value.STT_TAX + MISC -> Value.MISC + REVERSAL -> Value.REVERSAL + UNKNOWN -> Value.UNKNOWN + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always + * known and don't want to throw for the unknown case. + * + * @throws CasParserInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + PURCHASE -> Known.PURCHASE + PURCHASE_SIP -> Known.PURCHASE_SIP + REDEMPTION -> Known.REDEMPTION + SWITCH_IN -> Known.SWITCH_IN + SWITCH_IN_MERGER -> Known.SWITCH_IN_MERGER + SWITCH_OUT -> Known.SWITCH_OUT + SWITCH_OUT_MERGER -> Known.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Known.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Known.DIVIDEND_REINVEST + SEGREGATION -> Known.SEGREGATION + STAMP_DUTY_TAX -> Known.STAMP_DUTY_TAX + TDS_TAX -> Known.TDS_TAX + STT_TAX -> Known.STT_TAX + MISC -> Known.MISC + REVERSAL -> Known.REVERSAL + UNKNOWN -> Known.UNKNOWN + else -> throw CasParserInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily + * for debugging and generally doesn't throw. + * + * @throws CasParserInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CasParserInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this + * object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Transaction && + additionalInfo == other.additionalInfo && + amount == other.amount && + balance == other.balance && + date == other.date && + description == other.description && + dividendRate == other.dividendRate && + nav == other.nav && + type == other.type && + units == other.units && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Transaction{additionalInfo=$additionalInfo, amount=$amount, balance=$balance, date=$date, description=$description, dividendRate=$dividendRate, nav=$nav, type=$type, units=$units, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is GovernmentSecurity && + additionalInfo == other.additionalInfo && + isin == other.isin && + name == other.name && + transactions == other.transactions && + units == other.units && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + isin, + name, + transactions, + units, + value, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "GovernmentSecurity{additionalInfo=$additionalInfo, isin=$isin, name=$name, transactions=$transactions, units=$units, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Holdings && + aifs == other.aifs && + corporateBonds == other.corporateBonds && + dematMutualFunds == other.dematMutualFunds && + equities == other.equities && + governmentSecurities == other.governmentSecurities && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + aifs, + corporateBonds, + dematMutualFunds, + equities, + governmentSecurities, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Holdings{aifs=$aifs, corporateBonds=$corporateBonds, dematMutualFunds=$dematMutualFunds, equities=$equities, governmentSecurities=$governmentSecurities, additionalProperties=$additionalProperties}" + } + + class LinkedHolder + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val name: JsonField, + private val pan: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), + ) : this(name, pan, mutableMapOf()) + + /** + * Name of the account holder + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * PAN of the account holder + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun pan(): Optional = pan.getOptional("pan") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [pan]. + * + * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [LinkedHolder]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LinkedHolder]. */ + class Builder internal constructor() { + + private var name: JsonField = JsonMissing.of() + private var pan: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(linkedHolder: LinkedHolder) = apply { + name = linkedHolder.name + pan = linkedHolder.pan + additionalProperties = linkedHolder.additionalProperties.toMutableMap() + } + + /** Name of the account holder */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** PAN of the account holder */ + fun pan(pan: String) = pan(JsonField.of(pan)) + + /** + * Sets [Builder.pan] to an arbitrary JSON value. + * + * You should usually call [Builder.pan] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun pan(pan: JsonField) = apply { this.pan = pan } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [LinkedHolder]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): LinkedHolder = + LinkedHolder(name, pan, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): LinkedHolder = apply { + if (validated) { + return@apply + } + + name() + pan() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (name.asKnown().isPresent) 1 else 0) + (if (pan.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is LinkedHolder && + name == other.name && + pan == other.pan && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(name, pan, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "LinkedHolder{name=$name, pan=$pan, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is DematAccount && + additionalInfo == other.additionalInfo && + boId == other.boId && + clientId == other.clientId && + dematType == other.dematType && + dpId == other.dpId && + dpName == other.dpName && + holdings == other.holdings && + linkedHolders == other.linkedHolders && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + boId, + clientId, + dematType, + dpId, + dpName, + holdings, + linkedHolders, + value, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "DematAccount{additionalInfo=$additionalInfo, boId=$boId, clientId=$clientId, dematType=$dematType, dpId=$dpId, dpName=$dpName, holdings=$holdings, linkedHolders=$linkedHolders, value=$value, additionalProperties=$additionalProperties}" + } + + class Insurance + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val lifeInsurancePolicies: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("life_insurance_policies") + @ExcludeMissing + lifeInsurancePolicies: JsonField> = JsonMissing.of() + ) : this(lifeInsurancePolicies, mutableMapOf()) + + /** + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun lifeInsurancePolicies(): Optional> = + lifeInsurancePolicies.getOptional("life_insurance_policies") + + /** + * Returns the raw JSON value of [lifeInsurancePolicies]. + * + * Unlike [lifeInsurancePolicies], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("life_insurance_policies") + @ExcludeMissing + fun _lifeInsurancePolicies(): JsonField> = lifeInsurancePolicies + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Insurance]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Insurance]. */ + class Builder internal constructor() { + + private var lifeInsurancePolicies: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(insurance: Insurance) = apply { + lifeInsurancePolicies = insurance.lifeInsurancePolicies.map { it.toMutableList() } + additionalProperties = insurance.additionalProperties.toMutableMap() + } + + fun lifeInsurancePolicies(lifeInsurancePolicies: List) = + lifeInsurancePolicies(JsonField.of(lifeInsurancePolicies)) + + /** + * Sets [Builder.lifeInsurancePolicies] to an arbitrary JSON value. + * + * You should usually call [Builder.lifeInsurancePolicies] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun lifeInsurancePolicies(lifeInsurancePolicies: JsonField>) = + apply { + this.lifeInsurancePolicies = lifeInsurancePolicies.map { it.toMutableList() } + } + + /** + * Adds a single [LifeInsurancePolicy] to [lifeInsurancePolicies]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addLifeInsurancePolicy(lifeInsurancePolicy: LifeInsurancePolicy) = apply { + lifeInsurancePolicies = + (lifeInsurancePolicies ?: JsonField.of(mutableListOf())).also { + checkKnown("lifeInsurancePolicies", it).add(lifeInsurancePolicy) + } + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Insurance]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Insurance = + Insurance( + (lifeInsurancePolicies ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Insurance = apply { + if (validated) { + return@apply + } + + lifeInsurancePolicies().ifPresent { it.forEach { it.validate() } } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (lifeInsurancePolicies.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + class LifeInsurancePolicy + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonValue, + private val lifeAssured: JsonField, + private val policyName: JsonField, + private val policyNumber: JsonField, + private val premiumAmount: JsonField, + private val premiumFrequency: JsonField, + private val provider: JsonField, + private val status: JsonField, + private val sumAssured: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonValue = JsonMissing.of(), + @JsonProperty("life_assured") + @ExcludeMissing + lifeAssured: JsonField = JsonMissing.of(), + @JsonProperty("policy_name") + @ExcludeMissing + policyName: JsonField = JsonMissing.of(), + @JsonProperty("policy_number") + @ExcludeMissing + policyNumber: JsonField = JsonMissing.of(), + @JsonProperty("premium_amount") + @ExcludeMissing + premiumAmount: JsonField = JsonMissing.of(), + @JsonProperty("premium_frequency") + @ExcludeMissing + premiumFrequency: JsonField = JsonMissing.of(), + @JsonProperty("provider") + @ExcludeMissing + provider: JsonField = JsonMissing.of(), + @JsonProperty("status") + @ExcludeMissing + status: JsonField = JsonMissing.of(), + @JsonProperty("sum_assured") + @ExcludeMissing + sumAssured: JsonField = JsonMissing.of(), + ) : this( + additionalInfo, + lifeAssured, + policyName, + policyNumber, + premiumAmount, + premiumFrequency, + provider, + status, + sumAssured, + mutableMapOf(), + ) + + /** Additional information specific to the policy */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonValue = additionalInfo + + /** + * Name of the life assured + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun lifeAssured(): Optional = lifeAssured.getOptional("life_assured") + + /** + * Name of the insurance policy + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun policyName(): Optional = policyName.getOptional("policy_name") + + /** + * Insurance policy number + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun policyNumber(): Optional = policyNumber.getOptional("policy_number") + + /** + * Premium amount + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun premiumAmount(): Optional = premiumAmount.getOptional("premium_amount") + + /** + * Frequency of premium payment (e.g., Annual, Monthly) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun premiumFrequency(): Optional = + premiumFrequency.getOptional("premium_frequency") + + /** + * Insurance company name + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun provider(): Optional = provider.getOptional("provider") + + /** + * Status of the policy (e.g., Active, Lapsed) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun status(): Optional = status.getOptional("status") + + /** + * Sum assured amount + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun sumAssured(): Optional = sumAssured.getOptional("sum_assured") + + /** + * Returns the raw JSON value of [lifeAssured]. + * + * Unlike [lifeAssured], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("life_assured") + @ExcludeMissing + fun _lifeAssured(): JsonField = lifeAssured + + /** + * Returns the raw JSON value of [policyName]. + * + * Unlike [policyName], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("policy_name") + @ExcludeMissing + fun _policyName(): JsonField = policyName + + /** + * Returns the raw JSON value of [policyNumber]. + * + * Unlike [policyNumber], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("policy_number") + @ExcludeMissing + fun _policyNumber(): JsonField = policyNumber + + /** + * Returns the raw JSON value of [premiumAmount]. + * + * Unlike [premiumAmount], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("premium_amount") + @ExcludeMissing + fun _premiumAmount(): JsonField = premiumAmount + + /** + * Returns the raw JSON value of [premiumFrequency]. + * + * Unlike [premiumFrequency], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("premium_frequency") + @ExcludeMissing + fun _premiumFrequency(): JsonField = premiumFrequency + + /** + * Returns the raw JSON value of [provider]. + * + * Unlike [provider], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("provider") @ExcludeMissing fun _provider(): JsonField = provider + + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status + + /** + * Returns the raw JSON value of [sumAssured]. + * + * Unlike [sumAssured], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("sum_assured") + @ExcludeMissing + fun _sumAssured(): JsonField = sumAssured + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [LifeInsurancePolicy]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LifeInsurancePolicy]. */ + class Builder internal constructor() { + + private var additionalInfo: JsonValue = JsonMissing.of() + private var lifeAssured: JsonField = JsonMissing.of() + private var policyName: JsonField = JsonMissing.of() + private var policyNumber: JsonField = JsonMissing.of() + private var premiumAmount: JsonField = JsonMissing.of() + private var premiumFrequency: JsonField = JsonMissing.of() + private var provider: JsonField = JsonMissing.of() + private var status: JsonField = JsonMissing.of() + private var sumAssured: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(lifeInsurancePolicy: LifeInsurancePolicy) = apply { + additionalInfo = lifeInsurancePolicy.additionalInfo + lifeAssured = lifeInsurancePolicy.lifeAssured + policyName = lifeInsurancePolicy.policyName + policyNumber = lifeInsurancePolicy.policyNumber + premiumAmount = lifeInsurancePolicy.premiumAmount + premiumFrequency = lifeInsurancePolicy.premiumFrequency + provider = lifeInsurancePolicy.provider + status = lifeInsurancePolicy.status + sumAssured = lifeInsurancePolicy.sumAssured + additionalProperties = lifeInsurancePolicy.additionalProperties.toMutableMap() + } + + /** Additional information specific to the policy */ + fun additionalInfo(additionalInfo: JsonValue) = apply { + this.additionalInfo = additionalInfo + } + + /** Name of the life assured */ + fun lifeAssured(lifeAssured: String) = lifeAssured(JsonField.of(lifeAssured)) + + /** + * Sets [Builder.lifeAssured] to an arbitrary JSON value. + * + * You should usually call [Builder.lifeAssured] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun lifeAssured(lifeAssured: JsonField) = apply { + this.lifeAssured = lifeAssured + } + + /** Name of the insurance policy */ + fun policyName(policyName: String) = policyName(JsonField.of(policyName)) + + /** + * Sets [Builder.policyName] to an arbitrary JSON value. + * + * You should usually call [Builder.policyName] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun policyName(policyName: JsonField) = apply { + this.policyName = policyName + } + + /** Insurance policy number */ + fun policyNumber(policyNumber: String) = policyNumber(JsonField.of(policyNumber)) + + /** + * Sets [Builder.policyNumber] to an arbitrary JSON value. + * + * You should usually call [Builder.policyNumber] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun policyNumber(policyNumber: JsonField) = apply { + this.policyNumber = policyNumber + } + + /** Premium amount */ + fun premiumAmount(premiumAmount: Float) = premiumAmount(JsonField.of(premiumAmount)) + + /** + * Sets [Builder.premiumAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.premiumAmount] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun premiumAmount(premiumAmount: JsonField) = apply { + this.premiumAmount = premiumAmount + } + + /** Frequency of premium payment (e.g., Annual, Monthly) */ + fun premiumFrequency(premiumFrequency: String) = + premiumFrequency(JsonField.of(premiumFrequency)) + + /** + * Sets [Builder.premiumFrequency] to an arbitrary JSON value. + * + * You should usually call [Builder.premiumFrequency] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun premiumFrequency(premiumFrequency: JsonField) = apply { + this.premiumFrequency = premiumFrequency + } + + /** Insurance company name */ + fun provider(provider: String) = provider(JsonField.of(provider)) + + /** + * Sets [Builder.provider] to an arbitrary JSON value. + * + * You should usually call [Builder.provider] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun provider(provider: JsonField) = apply { this.provider = provider } + + /** Status of the policy (e.g., Active, Lapsed) */ + fun status(status: String) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + + /** Sum assured amount */ + fun sumAssured(sumAssured: Float) = sumAssured(JsonField.of(sumAssured)) + + /** + * Sets [Builder.sumAssured] to an arbitrary JSON value. + * + * You should usually call [Builder.sumAssured] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun sumAssured(sumAssured: JsonField) = apply { + this.sumAssured = sumAssured + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [LifeInsurancePolicy]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): LifeInsurancePolicy = + LifeInsurancePolicy( + additionalInfo, + lifeAssured, + policyName, + policyNumber, + premiumAmount, + premiumFrequency, + provider, + status, + sumAssured, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): LifeInsurancePolicy = apply { + if (validated) { + return@apply + } + + lifeAssured() + policyName() + policyNumber() + premiumAmount() + premiumFrequency() + provider() + status() + sumAssured() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (lifeAssured.asKnown().isPresent) 1 else 0) + + (if (policyName.asKnown().isPresent) 1 else 0) + + (if (policyNumber.asKnown().isPresent) 1 else 0) + + (if (premiumAmount.asKnown().isPresent) 1 else 0) + + (if (premiumFrequency.asKnown().isPresent) 1 else 0) + + (if (provider.asKnown().isPresent) 1 else 0) + + (if (status.asKnown().isPresent) 1 else 0) + + (if (sumAssured.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is LifeInsurancePolicy && + additionalInfo == other.additionalInfo && + lifeAssured == other.lifeAssured && + policyName == other.policyName && + policyNumber == other.policyNumber && + premiumAmount == other.premiumAmount && + premiumFrequency == other.premiumFrequency && + provider == other.provider && + status == other.status && + sumAssured == other.sumAssured && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + additionalInfo, + lifeAssured, + policyName, + policyNumber, + premiumAmount, + premiumFrequency, + provider, + status, + sumAssured, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "LifeInsurancePolicy{additionalInfo=$additionalInfo, lifeAssured=$lifeAssured, policyName=$policyName, policyNumber=$policyNumber, premiumAmount=$premiumAmount, premiumFrequency=$premiumFrequency, provider=$provider, status=$status, sumAssured=$sumAssured, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Insurance && + lifeInsurancePolicies == other.lifeInsurancePolicies && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(lifeInsurancePolicies, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Insurance{lifeInsurancePolicies=$lifeInsurancePolicies, additionalProperties=$additionalProperties}" + } + + class Investor + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val address: JsonField, + private val casId: JsonField, + private val email: JsonField, + private val mobile: JsonField, + private val name: JsonField, + private val pan: JsonField, + private val pincode: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("address") @ExcludeMissing address: JsonField = JsonMissing.of(), + @JsonProperty("cas_id") @ExcludeMissing casId: JsonField = JsonMissing.of(), + @JsonProperty("email") @ExcludeMissing email: JsonField = JsonMissing.of(), + @JsonProperty("mobile") @ExcludeMissing mobile: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), + @JsonProperty("pincode") @ExcludeMissing pincode: JsonField = JsonMissing.of(), + ) : this(address, casId, email, mobile, name, pan, pincode, mutableMapOf()) + + /** + * Address of the investor + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun address(): Optional = address.getOptional("address") + + /** + * CAS ID of the investor (only for NSDL and CDSL) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun casId(): Optional = casId.getOptional("cas_id") + + /** + * Email address of the investor + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun email(): Optional = email.getOptional("email") + + /** + * Mobile number of the investor + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun mobile(): Optional = mobile.getOptional("mobile") + + /** + * Name of the investor + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * PAN (Permanent Account Number) of the investor + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun pan(): Optional = pan.getOptional("pan") + + /** + * Postal code of the investor's address + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun pincode(): Optional = pincode.getOptional("pincode") + + /** + * Returns the raw JSON value of [address]. + * + * Unlike [address], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("address") @ExcludeMissing fun _address(): JsonField = address + + /** + * Returns the raw JSON value of [casId]. + * + * Unlike [casId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("cas_id") @ExcludeMissing fun _casId(): JsonField = casId + + /** + * Returns the raw JSON value of [email]. + * + * Unlike [email], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("email") @ExcludeMissing fun _email(): JsonField = email + + /** + * Returns the raw JSON value of [mobile]. + * + * Unlike [mobile], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("mobile") @ExcludeMissing fun _mobile(): JsonField = mobile + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [pan]. + * + * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + + /** + * Returns the raw JSON value of [pincode]. + * + * Unlike [pincode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pincode") @ExcludeMissing fun _pincode(): JsonField = pincode + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Investor]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Investor]. */ + class Builder internal constructor() { + + private var address: JsonField = JsonMissing.of() + private var casId: JsonField = JsonMissing.of() + private var email: JsonField = JsonMissing.of() + private var mobile: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var pan: JsonField = JsonMissing.of() + private var pincode: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(investor: Investor) = apply { + address = investor.address + casId = investor.casId + email = investor.email + mobile = investor.mobile + name = investor.name + pan = investor.pan + pincode = investor.pincode + additionalProperties = investor.additionalProperties.toMutableMap() + } + + /** Address of the investor */ + fun address(address: String) = address(JsonField.of(address)) + + /** + * Sets [Builder.address] to an arbitrary JSON value. + * + * You should usually call [Builder.address] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun address(address: JsonField) = apply { this.address = address } + + /** CAS ID of the investor (only for NSDL and CDSL) */ + fun casId(casId: String) = casId(JsonField.of(casId)) + + /** + * Sets [Builder.casId] to an arbitrary JSON value. + * + * You should usually call [Builder.casId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun casId(casId: JsonField) = apply { this.casId = casId } + + /** Email address of the investor */ + fun email(email: String) = email(JsonField.of(email)) + + /** + * Sets [Builder.email] to an arbitrary JSON value. + * + * You should usually call [Builder.email] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun email(email: JsonField) = apply { this.email = email } + + /** Mobile number of the investor */ + fun mobile(mobile: String) = mobile(JsonField.of(mobile)) + + /** + * Sets [Builder.mobile] to an arbitrary JSON value. + * + * You should usually call [Builder.mobile] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun mobile(mobile: JsonField) = apply { this.mobile = mobile } + + /** Name of the investor */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** PAN (Permanent Account Number) of the investor */ + fun pan(pan: String) = pan(JsonField.of(pan)) + + /** + * Sets [Builder.pan] to an arbitrary JSON value. + * + * You should usually call [Builder.pan] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun pan(pan: JsonField) = apply { this.pan = pan } + + /** Postal code of the investor's address */ + fun pincode(pincode: String) = pincode(JsonField.of(pincode)) + + /** + * Sets [Builder.pincode] to an arbitrary JSON value. + * + * You should usually call [Builder.pincode] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun pincode(pincode: JsonField) = apply { this.pincode = pincode } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Investor]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Investor = + Investor( + address, + casId, + email, + mobile, + name, + pan, + pincode, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Investor = apply { + if (validated) { + return@apply + } + + address() + casId() + email() + mobile() + name() + pan() + pincode() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (address.asKnown().isPresent) 1 else 0) + + (if (casId.asKnown().isPresent) 1 else 0) + + (if (email.asKnown().isPresent) 1 else 0) + + (if (mobile.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (if (pan.asKnown().isPresent) 1 else 0) + + (if (pincode.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Investor && + address == other.address && + casId == other.casId && + email == other.email && + mobile == other.mobile && + name == other.name && + pan == other.pan && + pincode == other.pincode && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(address, casId, email, mobile, name, pan, pincode, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Investor{address=$address, casId=$casId, email=$email, mobile=$mobile, name=$name, pan=$pan, pincode=$pincode, additionalProperties=$additionalProperties}" + } + + class Meta + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val casType: JsonField, + private val generatedAt: JsonField, + private val statementPeriod: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("cas_type") + @ExcludeMissing + casType: JsonField = JsonMissing.of(), + @JsonProperty("generated_at") + @ExcludeMissing + generatedAt: JsonField = JsonMissing.of(), + @JsonProperty("statement_period") + @ExcludeMissing + statementPeriod: JsonField = JsonMissing.of(), + ) : this(casType, generatedAt, statementPeriod, mutableMapOf()) + + /** + * Type of CAS detected and processed + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun casType(): Optional = casType.getOptional("cas_type") + + /** + * Timestamp when the response was generated + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun generatedAt(): Optional = generatedAt.getOptional("generated_at") + + /** + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun statementPeriod(): Optional = + statementPeriod.getOptional("statement_period") + + /** + * Returns the raw JSON value of [casType]. + * + * Unlike [casType], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("cas_type") @ExcludeMissing fun _casType(): JsonField = casType + + /** + * Returns the raw JSON value of [generatedAt]. + * + * Unlike [generatedAt], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("generated_at") + @ExcludeMissing + fun _generatedAt(): JsonField = generatedAt + + /** + * Returns the raw JSON value of [statementPeriod]. + * + * Unlike [statementPeriod], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("statement_period") + @ExcludeMissing + fun _statementPeriod(): JsonField = statementPeriod + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Meta]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Meta]. */ + class Builder internal constructor() { + + private var casType: JsonField = JsonMissing.of() + private var generatedAt: JsonField = JsonMissing.of() + private var statementPeriod: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(meta: Meta) = apply { + casType = meta.casType + generatedAt = meta.generatedAt + statementPeriod = meta.statementPeriod + additionalProperties = meta.additionalProperties.toMutableMap() + } + + /** Type of CAS detected and processed */ + fun casType(casType: CasType) = casType(JsonField.of(casType)) + + /** + * Sets [Builder.casType] to an arbitrary JSON value. + * + * You should usually call [Builder.casType] with a well-typed [CasType] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun casType(casType: JsonField) = apply { this.casType = casType } + + /** Timestamp when the response was generated */ + fun generatedAt(generatedAt: OffsetDateTime) = generatedAt(JsonField.of(generatedAt)) + + /** + * Sets [Builder.generatedAt] to an arbitrary JSON value. + * + * You should usually call [Builder.generatedAt] with a well-typed [OffsetDateTime] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun generatedAt(generatedAt: JsonField) = apply { + this.generatedAt = generatedAt + } + + fun statementPeriod(statementPeriod: StatementPeriod) = + statementPeriod(JsonField.of(statementPeriod)) + + /** + * Sets [Builder.statementPeriod] to an arbitrary JSON value. + * + * You should usually call [Builder.statementPeriod] with a well-typed [StatementPeriod] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun statementPeriod(statementPeriod: JsonField) = apply { + this.statementPeriod = statementPeriod + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Meta]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Meta = + Meta(casType, generatedAt, statementPeriod, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Meta = apply { + if (validated) { + return@apply + } + + casType().ifPresent { it.validate() } + generatedAt() + statementPeriod().ifPresent { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (casType.asKnown().getOrNull()?.validity() ?: 0) + + (if (generatedAt.asKnown().isPresent) 1 else 0) + + (statementPeriod.asKnown().getOrNull()?.validity() ?: 0) + + /** Type of CAS detected and processed */ + class CasType @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val NSDL = of("NSDL") + + @JvmField val CDSL = of("CDSL") + + @JvmField val CAMS_KFINTECH = of("CAMS_KFINTECH") + + @JvmStatic fun of(value: String) = CasType(JsonField.of(value)) + } + + /** An enum containing [CasType]'s known values. */ + enum class Known { + NSDL, + CDSL, + CAMS_KFINTECH, + } + + /** + * An enum containing [CasType]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [CasType] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + NSDL, + CDSL, + CAMS_KFINTECH, + /** + * An enum member indicating that [CasType] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + NSDL -> Value.NSDL + CDSL -> Value.CDSL + CAMS_KFINTECH -> Value.CAMS_KFINTECH + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws CasParserInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + NSDL -> Known.NSDL + CDSL -> Known.CDSL + CAMS_KFINTECH -> Known.CAMS_KFINTECH + else -> throw CasParserInvalidDataException("Unknown CasType: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws CasParserInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CasParserInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): CasType = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CasType && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class StatementPeriod + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val from: JsonField, + private val to: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("from") @ExcludeMissing from: JsonField = JsonMissing.of(), + @JsonProperty("to") @ExcludeMissing to: JsonField = JsonMissing.of(), + ) : this(from, to, mutableMapOf()) + + /** + * Start date of the statement period + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun from(): Optional = from.getOptional("from") + + /** + * End date of the statement period + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun to(): Optional = to.getOptional("to") + + /** + * Returns the raw JSON value of [from]. + * + * Unlike [from], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("from") @ExcludeMissing fun _from(): JsonField = from + + /** + * Returns the raw JSON value of [to]. + * + * Unlike [to], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("to") @ExcludeMissing fun _to(): JsonField = to + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [StatementPeriod]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [StatementPeriod]. */ + class Builder internal constructor() { + + private var from: JsonField = JsonMissing.of() + private var to: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(statementPeriod: StatementPeriod) = apply { + from = statementPeriod.from + to = statementPeriod.to + additionalProperties = statementPeriod.additionalProperties.toMutableMap() + } + + /** Start date of the statement period */ + fun from(from: LocalDate) = from(JsonField.of(from)) + + /** + * Sets [Builder.from] to an arbitrary JSON value. + * + * You should usually call [Builder.from] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun from(from: JsonField) = apply { this.from = from } + + /** End date of the statement period */ + fun to(to: LocalDate) = to(JsonField.of(to)) + + /** + * Sets [Builder.to] to an arbitrary JSON value. + * + * You should usually call [Builder.to] with a well-typed [LocalDate] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun to(to: JsonField) = apply { this.to = to } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [StatementPeriod]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): StatementPeriod = + StatementPeriod(from, to, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): StatementPeriod = apply { + if (validated) { + return@apply + } + + from() + to() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (from.asKnown().isPresent) 1 else 0) + (if (to.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is StatementPeriod && + from == other.from && + to == other.to && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(from, to, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "StatementPeriod{from=$from, to=$to, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Meta && + casType == other.casType && + generatedAt == other.generatedAt && + statementPeriod == other.statementPeriod && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(casType, generatedAt, statementPeriod, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Meta{casType=$casType, generatedAt=$generatedAt, statementPeriod=$statementPeriod, additionalProperties=$additionalProperties}" + } + + class MutualFund + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val amc: JsonField, + private val folioNumber: JsonField, + private val linkedHolders: JsonField>, + private val registrar: JsonField, + private val schemes: JsonField>, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("amc") @ExcludeMissing amc: JsonField = JsonMissing.of(), + @JsonProperty("folio_number") + @ExcludeMissing + folioNumber: JsonField = JsonMissing.of(), + @JsonProperty("linked_holders") + @ExcludeMissing + linkedHolders: JsonField> = JsonMissing.of(), + @JsonProperty("registrar") + @ExcludeMissing + registrar: JsonField = JsonMissing.of(), + @JsonProperty("schemes") + @ExcludeMissing + schemes: JsonField> = JsonMissing.of(), + @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), + ) : this( + additionalInfo, + amc, + folioNumber, + linkedHolders, + registrar, + schemes, + value, + mutableMapOf(), + ) + + /** + * Additional folio information + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") + + /** + * Asset Management Company name + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun amc(): Optional = amc.getOptional("amc") + + /** + * Folio number + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun folioNumber(): Optional = folioNumber.getOptional("folio_number") + + /** + * List of account holders linked to this mutual fund folio + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun linkedHolders(): Optional> = + linkedHolders.getOptional("linked_holders") + + /** + * Registrar and Transfer Agent name + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun registrar(): Optional = registrar.getOptional("registrar") + + /** + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun schemes(): Optional> = schemes.getOptional("schemes") + + /** + * Total value of the folio + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo + + /** + * Returns the raw JSON value of [amc]. + * + * Unlike [amc], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("amc") @ExcludeMissing fun _amc(): JsonField = amc + + /** + * Returns the raw JSON value of [folioNumber]. + * + * Unlike [folioNumber], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("folio_number") + @ExcludeMissing + fun _folioNumber(): JsonField = folioNumber + + /** + * Returns the raw JSON value of [linkedHolders]. + * + * Unlike [linkedHolders], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("linked_holders") + @ExcludeMissing + fun _linkedHolders(): JsonField> = linkedHolders + + /** + * Returns the raw JSON value of [registrar]. + * + * Unlike [registrar], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("registrar") @ExcludeMissing fun _registrar(): JsonField = registrar + + /** + * Returns the raw JSON value of [schemes]. + * + * Unlike [schemes], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("schemes") @ExcludeMissing fun _schemes(): JsonField> = schemes + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [MutualFund]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [MutualFund]. */ + class Builder internal constructor() { + + private var additionalInfo: JsonField = JsonMissing.of() + private var amc: JsonField = JsonMissing.of() + private var folioNumber: JsonField = JsonMissing.of() + private var linkedHolders: JsonField>? = null + private var registrar: JsonField = JsonMissing.of() + private var schemes: JsonField>? = null + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(mutualFund: MutualFund) = apply { + additionalInfo = mutualFund.additionalInfo + amc = mutualFund.amc + folioNumber = mutualFund.folioNumber + linkedHolders = mutualFund.linkedHolders.map { it.toMutableList() } + registrar = mutualFund.registrar + schemes = mutualFund.schemes.map { it.toMutableList() } + value = mutualFund.value + additionalProperties = mutualFund.additionalProperties.toMutableMap() + } + + /** Additional folio information */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) + + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed [AdditionalInfo] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } + + /** Asset Management Company name */ + fun amc(amc: String) = amc(JsonField.of(amc)) + + /** + * Sets [Builder.amc] to an arbitrary JSON value. + * + * You should usually call [Builder.amc] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun amc(amc: JsonField) = apply { this.amc = amc } + + /** Folio number */ + fun folioNumber(folioNumber: String) = folioNumber(JsonField.of(folioNumber)) + + /** + * Sets [Builder.folioNumber] to an arbitrary JSON value. + * + * You should usually call [Builder.folioNumber] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun folioNumber(folioNumber: JsonField) = apply { + this.folioNumber = folioNumber + } + + /** List of account holders linked to this mutual fund folio */ + fun linkedHolders(linkedHolders: List) = + linkedHolders(JsonField.of(linkedHolders)) + + /** + * Sets [Builder.linkedHolders] to an arbitrary JSON value. + * + * You should usually call [Builder.linkedHolders] with a well-typed + * `List` value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun linkedHolders(linkedHolders: JsonField>) = apply { + this.linkedHolders = linkedHolders.map { it.toMutableList() } + } + + /** + * Adds a single [LinkedHolder] to [linkedHolders]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addLinkedHolder(linkedHolder: LinkedHolder) = apply { + linkedHolders = + (linkedHolders ?: JsonField.of(mutableListOf())).also { + checkKnown("linkedHolders", it).add(linkedHolder) + } + } + + /** Registrar and Transfer Agent name */ + fun registrar(registrar: String) = registrar(JsonField.of(registrar)) + + /** + * Sets [Builder.registrar] to an arbitrary JSON value. + * + * You should usually call [Builder.registrar] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun registrar(registrar: JsonField) = apply { this.registrar = registrar } + + fun schemes(schemes: List) = schemes(JsonField.of(schemes)) + + /** + * Sets [Builder.schemes] to an arbitrary JSON value. + * + * You should usually call [Builder.schemes] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun schemes(schemes: JsonField>) = apply { + this.schemes = schemes.map { it.toMutableList() } + } + + /** + * Adds a single [Scheme] to [schemes]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addScheme(scheme: Scheme) = apply { + schemes = + (schemes ?: JsonField.of(mutableListOf())).also { + checkKnown("schemes", it).add(scheme) + } + } + + /** Total value of the folio */ + fun value(value: Float) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Float] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun value(value: JsonField) = apply { this.value = value } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [MutualFund]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): MutualFund = + MutualFund( + additionalInfo, + amc, + folioNumber, + (linkedHolders ?: JsonMissing.of()).map { it.toImmutable() }, + registrar, + (schemes ?: JsonMissing.of()).map { it.toImmutable() }, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): MutualFund = apply { + if (validated) { + return@apply + } + + additionalInfo().ifPresent { it.validate() } + amc() + folioNumber() + linkedHolders().ifPresent { it.forEach { it.validate() } } + registrar() + schemes().ifPresent { it.forEach { it.validate() } } + value() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (amc.asKnown().isPresent) 1 else 0) + + (if (folioNumber.asKnown().isPresent) 1 else 0) + + (linkedHolders.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (registrar.asKnown().isPresent) 1 else 0) + + (schemes.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (value.asKnown().isPresent) 1 else 0) + + /** Additional folio information */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val kyc: JsonField, + private val pan: JsonField, + private val pankyc: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("kyc") @ExcludeMissing kyc: JsonField = JsonMissing.of(), + @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), + @JsonProperty("pankyc") @ExcludeMissing pankyc: JsonField = JsonMissing.of(), + ) : this(kyc, pan, pankyc, mutableMapOf()) + + /** + * KYC status of the folio + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun kyc(): Optional = kyc.getOptional("kyc") + + /** + * PAN associated with the folio + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun pan(): Optional = pan.getOptional("pan") + + /** + * PAN KYC status + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun pankyc(): Optional = pankyc.getOptional("pankyc") + + /** + * Returns the raw JSON value of [kyc]. + * + * Unlike [kyc], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("kyc") @ExcludeMissing fun _kyc(): JsonField = kyc + + /** + * Returns the raw JSON value of [pan]. + * + * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + + /** + * Returns the raw JSON value of [pankyc]. + * + * Unlike [pankyc], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pankyc") @ExcludeMissing fun _pankyc(): JsonField = pankyc + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [AdditionalInfo]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { + + private var kyc: JsonField = JsonMissing.of() + private var pan: JsonField = JsonMissing.of() + private var pankyc: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + kyc = additionalInfo.kyc + pan = additionalInfo.pan + pankyc = additionalInfo.pankyc + additionalProperties = additionalInfo.additionalProperties.toMutableMap() + } + + /** KYC status of the folio */ + fun kyc(kyc: String) = kyc(JsonField.of(kyc)) + + /** + * Sets [Builder.kyc] to an arbitrary JSON value. + * + * You should usually call [Builder.kyc] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun kyc(kyc: JsonField) = apply { this.kyc = kyc } + + /** PAN associated with the folio */ + fun pan(pan: String) = pan(JsonField.of(pan)) + + /** + * Sets [Builder.pan] to an arbitrary JSON value. + * + * You should usually call [Builder.pan] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun pan(pan: JsonField) = apply { this.pan = pan } + + /** PAN KYC status */ + fun pankyc(pankyc: String) = pankyc(JsonField.of(pankyc)) + + /** + * Sets [Builder.pankyc] to an arbitrary JSON value. + * + * You should usually call [Builder.pankyc] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun pankyc(pankyc: JsonField) = apply { this.pankyc = pankyc } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo(kyc, pan, pankyc, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } + + kyc() + pan() + pankyc() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (kyc.asKnown().isPresent) 1 else 0) + + (if (pan.asKnown().isPresent) 1 else 0) + + (if (pankyc.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is AdditionalInfo && + kyc == other.kyc && + pan == other.pan && + pankyc == other.pankyc && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(kyc, pan, pankyc, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{kyc=$kyc, pan=$pan, pankyc=$pankyc, additionalProperties=$additionalProperties}" + } + + class LinkedHolder + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val name: JsonField, + private val pan: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("pan") @ExcludeMissing pan: JsonField = JsonMissing.of(), + ) : this(name, pan, mutableMapOf()) + + /** + * Name of the account holder + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * PAN of the account holder + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun pan(): Optional = pan.getOptional("pan") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [pan]. + * + * Unlike [pan], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pan") @ExcludeMissing fun _pan(): JsonField = pan + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [LinkedHolder]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LinkedHolder]. */ + class Builder internal constructor() { + + private var name: JsonField = JsonMissing.of() + private var pan: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(linkedHolder: LinkedHolder) = apply { + name = linkedHolder.name + pan = linkedHolder.pan + additionalProperties = linkedHolder.additionalProperties.toMutableMap() + } + + /** Name of the account holder */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** PAN of the account holder */ + fun pan(pan: String) = pan(JsonField.of(pan)) + + /** + * Sets [Builder.pan] to an arbitrary JSON value. + * + * You should usually call [Builder.pan] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun pan(pan: JsonField) = apply { this.pan = pan } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [LinkedHolder]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): LinkedHolder = + LinkedHolder(name, pan, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): LinkedHolder = apply { + if (validated) { + return@apply + } + + name() + pan() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (name.asKnown().isPresent) 1 else 0) + (if (pan.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is LinkedHolder && + name == other.name && + pan == other.pan && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(name, pan, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "LinkedHolder{name=$name, pan=$pan, additionalProperties=$additionalProperties}" + } + + class Scheme + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val additionalInfo: JsonField, + private val cost: JsonField, + private val gain: JsonField, + private val isin: JsonField, + private val name: JsonField, + private val nav: JsonField, + private val nominees: JsonField>, + private val transactions: JsonField>, + private val type: JsonField, + private val units: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("additional_info") + @ExcludeMissing + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("cost") @ExcludeMissing cost: JsonField = JsonMissing.of(), + @JsonProperty("gain") @ExcludeMissing gain: JsonField = JsonMissing.of(), + @JsonProperty("isin") @ExcludeMissing isin: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("nav") @ExcludeMissing nav: JsonField = JsonMissing.of(), + @JsonProperty("nominees") + @ExcludeMissing + nominees: JsonField> = JsonMissing.of(), + @JsonProperty("transactions") + @ExcludeMissing + transactions: JsonField> = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("units") @ExcludeMissing units: JsonField = JsonMissing.of(), + @JsonProperty("value") @ExcludeMissing value: JsonField = JsonMissing.of(), + ) : this( + additionalInfo, + cost, + gain, + isin, + name, + nav, + nominees, + transactions, + type, + units, + value, + mutableMapOf(), + ) + + /** + * Additional information specific to the scheme + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") + + /** + * Cost of investment + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun cost(): Optional = cost.getOptional("cost") + + /** + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun gain(): Optional = gain.getOptional("gain") + + /** + * ISIN code of the scheme + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun isin(): Optional = isin.getOptional("isin") + + /** + * Scheme name + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun name(): Optional = name.getOptional("name") + + /** + * Net Asset Value per unit + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun nav(): Optional = nav.getOptional("nav") + + /** + * List of nominees + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun nominees(): Optional> = nominees.getOptional("nominees") + + /** + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun transactions(): Optional> = + transactions.getOptional("transactions") + + /** + * Type of mutual fund scheme + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun type(): Optional = type.getOptional("type") + + /** + * Number of units held + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun units(): Optional = units.getOptional("units") + + /** + * Current market value of the holding + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo + + /** + * Returns the raw JSON value of [cost]. + * + * Unlike [cost], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("cost") @ExcludeMissing fun _cost(): JsonField = cost + + /** + * Returns the raw JSON value of [gain]. + * + * Unlike [gain], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("gain") @ExcludeMissing fun _gain(): JsonField = gain + + /** + * Returns the raw JSON value of [isin]. + * + * Unlike [isin], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("isin") @ExcludeMissing fun _isin(): JsonField = isin + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [nav]. + * + * Unlike [nav], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("nav") @ExcludeMissing fun _nav(): JsonField = nav + + /** + * Returns the raw JSON value of [nominees]. + * + * Unlike [nominees], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("nominees") + @ExcludeMissing + fun _nominees(): JsonField> = nominees + + /** + * Returns the raw JSON value of [transactions]. + * + * Unlike [transactions], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("transactions") + @ExcludeMissing + fun _transactions(): JsonField> = transactions + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [units]. + * + * Unlike [units], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units + + /** * Returns the raw JSON value of [value]. * - * Unlike [value], this method doesn't throw if the JSON field has an unexpected type. + * Unlike [value], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Scheme]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Scheme]. */ + class Builder internal constructor() { + + private var additionalInfo: JsonField = JsonMissing.of() + private var cost: JsonField = JsonMissing.of() + private var gain: JsonField = JsonMissing.of() + private var isin: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var nav: JsonField = JsonMissing.of() + private var nominees: JsonField>? = null + private var transactions: JsonField>? = null + private var type: JsonField = JsonMissing.of() + private var units: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(scheme: Scheme) = apply { + additionalInfo = scheme.additionalInfo + cost = scheme.cost + gain = scheme.gain + isin = scheme.isin + name = scheme.name + nav = scheme.nav + nominees = scheme.nominees.map { it.toMutableList() } + transactions = scheme.transactions.map { it.toMutableList() } + type = scheme.type + units = scheme.units + value = scheme.value + additionalProperties = scheme.additionalProperties.toMutableMap() + } + + /** Additional information specific to the scheme */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) + + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } + + /** Cost of investment */ + fun cost(cost: Float) = cost(JsonField.of(cost)) + + /** + * Sets [Builder.cost] to an arbitrary JSON value. + * + * You should usually call [Builder.cost] with a well-typed [Float] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun cost(cost: JsonField) = apply { this.cost = cost } + + fun gain(gain: Gain) = gain(JsonField.of(gain)) + + /** + * Sets [Builder.gain] to an arbitrary JSON value. + * + * You should usually call [Builder.gain] with a well-typed [Gain] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun gain(gain: JsonField) = apply { this.gain = gain } + + /** ISIN code of the scheme */ + fun isin(isin: String) = isin(JsonField.of(isin)) + + /** + * Sets [Builder.isin] to an arbitrary JSON value. + * + * You should usually call [Builder.isin] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun isin(isin: JsonField) = apply { this.isin = isin } + + /** Scheme name */ + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + /** Net Asset Value per unit */ + fun nav(nav: Float) = nav(JsonField.of(nav)) + + /** + * Sets [Builder.nav] to an arbitrary JSON value. + * + * You should usually call [Builder.nav] with a well-typed [Float] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun nav(nav: JsonField) = apply { this.nav = nav } + + /** List of nominees */ + fun nominees(nominees: List) = nominees(JsonField.of(nominees)) + + /** + * Sets [Builder.nominees] to an arbitrary JSON value. + * + * You should usually call [Builder.nominees] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun nominees(nominees: JsonField>) = apply { + this.nominees = nominees.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [nominees]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addNominee(nominee: String) = apply { + nominees = + (nominees ?: JsonField.of(mutableListOf())).also { + checkKnown("nominees", it).add(nominee) + } + } + + fun transactions(transactions: List) = + transactions(JsonField.of(transactions)) + + /** + * Sets [Builder.transactions] to an arbitrary JSON value. + * + * You should usually call [Builder.transactions] with a well-typed + * `List` value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun transactions(transactions: JsonField>) = apply { + this.transactions = transactions.map { it.toMutableList() } + } + + /** + * Adds a single [Transaction] to [transactions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTransaction(transaction: Transaction) = apply { + transactions = + (transactions ?: JsonField.of(mutableListOf())).also { + checkKnown("transactions", it).add(transaction) + } + } + + /** Type of mutual fund scheme */ + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + /** Number of units held */ + fun units(units: Float) = units(JsonField.of(units)) + + /** + * Sets [Builder.units] to an arbitrary JSON value. + * + * You should usually call [Builder.units] with a well-typed [Float] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun units(units: JsonField) = apply { this.units = units } + + /** Current market value of the holding */ + fun value(value: Float) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Float] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Scheme]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Scheme = + Scheme( + additionalInfo, + cost, + gain, + isin, + name, + nav, + (nominees ?: JsonMissing.of()).map { it.toImmutable() }, + (transactions ?: JsonMissing.of()).map { it.toImmutable() }, + type, + units, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Scheme = apply { + if (validated) { + return@apply + } + + additionalInfo().ifPresent { it.validate() } + cost() + gain().ifPresent { it.validate() } + isin() + name() + nav() + nominees() + transactions().ifPresent { it.forEach { it.validate() } } + type().ifPresent { it.validate() } + units() + value() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. */ - @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + @JvmSynthetic + internal fun validity(): Int = + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (cost.asKnown().isPresent) 1 else 0) + + (gain.asKnown().getOrNull()?.validity() ?: 0) + + (if (isin.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (if (nav.asKnown().isPresent) 1 else 0) + + (nominees.asKnown().getOrNull()?.size ?: 0) + + (transactions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (units.asKnown().isPresent) 1 else 0) + + (if (value.asKnown().isPresent) 1 else 0) - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** Additional information specific to the scheme */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val advisor: JsonField, + private val amfi: JsonField, + private val closeUnits: JsonField, + private val openUnits: JsonField, + private val rtaCode: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("advisor") + @ExcludeMissing + advisor: JsonField = JsonMissing.of(), + @JsonProperty("amfi") + @ExcludeMissing + amfi: JsonField = JsonMissing.of(), + @JsonProperty("close_units") + @ExcludeMissing + closeUnits: JsonField = JsonMissing.of(), + @JsonProperty("open_units") + @ExcludeMissing + openUnits: JsonField = JsonMissing.of(), + @JsonProperty("rta_code") + @ExcludeMissing + rtaCode: JsonField = JsonMissing.of(), + ) : this(advisor, amfi, closeUnits, openUnits, rtaCode, mutableMapOf()) + + /** + * Financial advisor name (CAMS/KFintech) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun advisor(): Optional = advisor.getOptional("advisor") + + /** + * AMFI code for the scheme (CAMS/KFintech) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun amfi(): Optional = amfi.getOptional("amfi") + + /** + * Closing balance units for the statement period + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun closeUnits(): Optional = closeUnits.getOptional("close_units") + + /** + * Opening balance units for the statement period + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun openUnits(): Optional = openUnits.getOptional("open_units") + + /** + * RTA code for the scheme (CAMS/KFintech) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun rtaCode(): Optional = rtaCode.getOptional("rta_code") + + /** + * Returns the raw JSON value of [advisor]. + * + * Unlike [advisor], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("advisor") @ExcludeMissing fun _advisor(): JsonField = advisor + + /** + * Returns the raw JSON value of [amfi]. + * + * Unlike [amfi], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("amfi") @ExcludeMissing fun _amfi(): JsonField = amfi + + /** + * Returns the raw JSON value of [closeUnits]. + * + * Unlike [closeUnits], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("close_units") + @ExcludeMissing + fun _closeUnits(): JsonField = closeUnits + + /** + * Returns the raw JSON value of [openUnits]. + * + * Unlike [openUnits], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("open_units") + @ExcludeMissing + fun _openUnits(): JsonField = openUnits + + /** + * Returns the raw JSON value of [rtaCode]. + * + * Unlike [rtaCode], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("rta_code") + @ExcludeMissing + fun _rtaCode(): JsonField = rtaCode + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { + + private var advisor: JsonField = JsonMissing.of() + private var amfi: JsonField = JsonMissing.of() + private var closeUnits: JsonField = JsonMissing.of() + private var openUnits: JsonField = JsonMissing.of() + private var rtaCode: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + advisor = additionalInfo.advisor + amfi = additionalInfo.amfi + closeUnits = additionalInfo.closeUnits + openUnits = additionalInfo.openUnits + rtaCode = additionalInfo.rtaCode + additionalProperties = additionalInfo.additionalProperties.toMutableMap() + } + + /** Financial advisor name (CAMS/KFintech) */ + fun advisor(advisor: String) = advisor(JsonField.of(advisor)) + + /** + * Sets [Builder.advisor] to an arbitrary JSON value. + * + * You should usually call [Builder.advisor] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun advisor(advisor: JsonField) = apply { this.advisor = advisor } + + /** AMFI code for the scheme (CAMS/KFintech) */ + fun amfi(amfi: String) = amfi(JsonField.of(amfi)) + + /** + * Sets [Builder.amfi] to an arbitrary JSON value. + * + * You should usually call [Builder.amfi] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun amfi(amfi: JsonField) = apply { this.amfi = amfi } + + /** Closing balance units for the statement period */ + fun closeUnits(closeUnits: Float?) = + closeUnits(JsonField.ofNullable(closeUnits)) + + /** + * Alias for [Builder.closeUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun closeUnits(closeUnits: Float) = closeUnits(closeUnits as Float?) - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + /** Alias for calling [Builder.closeUnits] with `closeUnits.orElse(null)`. */ + fun closeUnits(closeUnits: Optional) = closeUnits(closeUnits.getOrNull()) - fun toBuilder() = Builder().from(this) + /** + * Sets [Builder.closeUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.closeUnits] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun closeUnits(closeUnits: JsonField) = apply { + this.closeUnits = closeUnits + } - companion object { + /** Opening balance units for the statement period */ + fun openUnits(openUnits: Float?) = openUnits(JsonField.ofNullable(openUnits)) - /** Returns a mutable builder for constructing an instance of [Scheme]. */ - @JvmStatic fun builder() = Builder() - } + /** + * Alias for [Builder.openUnits]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun openUnits(openUnits: Float) = openUnits(openUnits as Float?) - /** A builder for [Scheme]. */ - class Builder internal constructor() { + /** Alias for calling [Builder.openUnits] with `openUnits.orElse(null)`. */ + fun openUnits(openUnits: Optional) = openUnits(openUnits.getOrNull()) - private var additionalInfo: JsonField = JsonMissing.of() - private var cost: JsonField = JsonMissing.of() - private var gain: JsonField = JsonMissing.of() - private var isin: JsonField = JsonMissing.of() - private var name: JsonField = JsonMissing.of() - private var nav: JsonField = JsonMissing.of() - private var nominees: JsonField>? = null - private var transactions: JsonField>? = null - private var type: JsonField = JsonMissing.of() - private var units: JsonField = JsonMissing.of() - private var value: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + /** + * Sets [Builder.openUnits] to an arbitrary JSON value. + * + * You should usually call [Builder.openUnits] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun openUnits(openUnits: JsonField) = apply { + this.openUnits = openUnits + } - @JvmSynthetic - internal fun from(scheme: Scheme) = apply { - additionalInfo = scheme.additionalInfo - cost = scheme.cost - gain = scheme.gain - isin = scheme.isin - name = scheme.name - nav = scheme.nav - nominees = scheme.nominees.map { it.toMutableList() } - transactions = scheme.transactions.map { it.toMutableList() } - type = scheme.type - units = scheme.units - value = scheme.value - additionalProperties = scheme.additionalProperties.toMutableMap() - } + /** RTA code for the scheme (CAMS/KFintech) */ + fun rtaCode(rtaCode: String) = rtaCode(JsonField.of(rtaCode)) - /** Additional information specific to the scheme */ - fun additionalInfo(additionalInfo: AdditionalInfo) = - additionalInfo(JsonField.of(additionalInfo)) + /** + * Sets [Builder.rtaCode] to an arbitrary JSON value. + * + * You should usually call [Builder.rtaCode] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun rtaCode(rtaCode: JsonField) = apply { this.rtaCode = rtaCode } - /** - * Sets [Builder.additionalInfo] to an arbitrary JSON value. - * - * You should usually call [Builder.additionalInfo] with a well-typed - * [AdditionalInfo] value instead. This method is primarily for setting the field to - * an undocumented or not yet supported value. - */ - fun additionalInfo(additionalInfo: JsonField) = apply { - this.additionalInfo = additionalInfo - } + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - /** Cost of investment */ - fun cost(cost: Float) = cost(JsonField.of(cost)) + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - /** - * Sets [Builder.cost] to an arbitrary JSON value. - * - * You should usually call [Builder.cost] with a well-typed [Float] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun cost(cost: JsonField) = apply { this.cost = cost } + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } - fun gain(gain: Gain) = gain(JsonField.of(gain)) + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } - /** - * Sets [Builder.gain] to an arbitrary JSON value. - * - * You should usually call [Builder.gain] with a well-typed [Gain] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun gain(gain: JsonField) = apply { this.gain = gain } + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } - /** ISIN code of the scheme */ - fun isin(isin: String) = isin(JsonField.of(isin)) + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + advisor, + amfi, + closeUnits, + openUnits, + rtaCode, + additionalProperties.toMutableMap(), + ) + } - /** - * Sets [Builder.isin] to an arbitrary JSON value. - * - * You should usually call [Builder.isin] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun isin(isin: JsonField) = apply { this.isin = isin } + private var validated: Boolean = false - /** Scheme name */ - fun name(name: String) = name(JsonField.of(name)) + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } - /** - * Sets [Builder.name] to an arbitrary JSON value. - * - * You should usually call [Builder.name] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun name(name: JsonField) = apply { this.name = name } + advisor() + amfi() + closeUnits() + openUnits() + rtaCode() + validated = true + } - /** Net Asset Value per unit */ - fun nav(nav: Float) = nav(JsonField.of(nav)) + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } /** - * Sets [Builder.nav] to an arbitrary JSON value. + * Returns a score indicating how many valid values are contained in this object + * recursively. * - * You should usually call [Builder.nav] with a well-typed [Float] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. + * Used for best match union deserialization. */ - fun nav(nav: JsonField) = apply { this.nav = nav } + @JvmSynthetic + internal fun validity(): Int = + (if (advisor.asKnown().isPresent) 1 else 0) + + (if (amfi.asKnown().isPresent) 1 else 0) + + (if (closeUnits.asKnown().isPresent) 1 else 0) + + (if (openUnits.asKnown().isPresent) 1 else 0) + + (if (rtaCode.asKnown().isPresent) 1 else 0) - /** List of nominees */ - fun nominees(nominees: List) = nominees(JsonField.of(nominees)) + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - /** - * Sets [Builder.nominees] to an arbitrary JSON value. - * - * You should usually call [Builder.nominees] with a well-typed `List` value - * instead. This method is primarily for setting the field to an undocumented or not - * yet supported value. - */ - fun nominees(nominees: JsonField>) = apply { - this.nominees = nominees.map { it.toMutableList() } + return other is AdditionalInfo && + advisor == other.advisor && + amfi == other.amfi && + closeUnits == other.closeUnits && + openUnits == other.openUnits && + rtaCode == other.rtaCode && + additionalProperties == other.additionalProperties } - /** - * Adds a single [String] to [nominees]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addNominee(nominee: String) = apply { - nominees = - (nominees ?: JsonField.of(mutableListOf())).also { - checkKnown("nominees", it).add(nominee) - } + private val hashCode: Int by lazy { + Objects.hash( + advisor, + amfi, + closeUnits, + openUnits, + rtaCode, + additionalProperties, + ) } - fun transactions(transactions: List) = - transactions(JsonField.of(transactions)) + override fun hashCode(): Int = hashCode + + override fun toString() = + "AdditionalInfo{advisor=$advisor, amfi=$amfi, closeUnits=$closeUnits, openUnits=$openUnits, rtaCode=$rtaCode, additionalProperties=$additionalProperties}" + } + + class Gain + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val absolute: JsonField, + private val percentage: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("absolute") + @ExcludeMissing + absolute: JsonField = JsonMissing.of(), + @JsonProperty("percentage") + @ExcludeMissing + percentage: JsonField = JsonMissing.of(), + ) : this(absolute, percentage, mutableMapOf()) /** - * Sets [Builder.transactions] to an arbitrary JSON value. + * Absolute gain or loss * - * You should usually call [Builder.transactions] with a well-typed - * `List` value instead. This method is primarily for setting the field - * to an undocumented or not yet supported value. + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). */ - fun transactions(transactions: JsonField>) = apply { - this.transactions = transactions.map { it.toMutableList() } - } + fun absolute(): Optional = absolute.getOptional("absolute") /** - * Adds a single [Transaction] to [transactions]. + * Percentage gain or loss * - * @throws IllegalStateException if the field was previously set to a non-list. + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). */ - fun addTransaction(transaction: Transaction) = apply { - transactions = - (transactions ?: JsonField.of(mutableListOf())).also { - checkKnown("transactions", it).add(transaction) - } - } - - /** Type of mutual fund scheme */ - fun type(type: Type) = type(JsonField.of(type)) + fun percentage(): Optional = percentage.getOptional("percentage") /** - * Sets [Builder.type] to an arbitrary JSON value. + * Returns the raw JSON value of [absolute]. * - * You should usually call [Builder.type] with a well-typed [Type] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. + * Unlike [absolute], this method doesn't throw if the JSON field has an unexpected + * type. */ - fun type(type: JsonField) = apply { this.type = type } - - /** Number of units held */ - fun units(units: Float) = units(JsonField.of(units)) + @JsonProperty("absolute") + @ExcludeMissing + fun _absolute(): JsonField = absolute /** - * Sets [Builder.units] to an arbitrary JSON value. + * Returns the raw JSON value of [percentage]. * - * You should usually call [Builder.units] with a well-typed [Float] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. + * Unlike [percentage], this method doesn't throw if the JSON field has an + * unexpected type. */ - fun units(units: JsonField) = apply { this.units = units } + @JsonProperty("percentage") + @ExcludeMissing + fun _percentage(): JsonField = percentage - /** Current market value of the holding */ - fun value(value: Float) = value(JsonField.of(value)) + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - /** - * Sets [Builder.value] to an arbitrary JSON value. - * - * You should usually call [Builder.value] with a well-typed [Float] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun value(value: JsonField) = apply { this.value = value } + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + fun toBuilder() = Builder().from(this) - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) + companion object { + + /** Returns a mutable builder for constructing an instance of [Gain]. */ + @JvmStatic fun builder() = Builder() } - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) + /** A builder for [Gain]. */ + class Builder internal constructor() { + + private var absolute: JsonField = JsonMissing.of() + private var percentage: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(gain: Gain) = apply { + absolute = gain.absolute + percentage = gain.percentage + additionalProperties = gain.additionalProperties.toMutableMap() } - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) + /** Absolute gain or loss */ + fun absolute(absolute: Float) = absolute(JsonField.of(absolute)) + + /** + * Sets [Builder.absolute] to an arbitrary JSON value. + * + * You should usually call [Builder.absolute] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun absolute(absolute: JsonField) = apply { this.absolute = absolute } + + /** Percentage gain or loss */ + fun percentage(percentage: Float) = percentage(JsonField.of(percentage)) + + /** + * Sets [Builder.percentage] to an arbitrary JSON value. + * + * You should usually call [Builder.percentage] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun percentage(percentage: JsonField) = apply { + this.percentage = percentage + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Gain]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Gain = + Gain(absolute, percentage, additionalProperties.toMutableMap()) } - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) + private var validated: Boolean = false + + fun validate(): Gain = apply { + if (validated) { + return@apply + } + + absolute() + percentage() + validated = true } + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } + /** - * Returns an immutable instance of [Scheme]. + * Returns a score indicating how many valid values are contained in this object + * recursively. * - * Further updates to this [Builder] will not mutate the returned instance. + * Used for best match union deserialization. */ - fun build(): Scheme = - Scheme( - additionalInfo, - cost, - gain, - isin, - name, - nav, - (nominees ?: JsonMissing.of()).map { it.toImmutable() }, - (transactions ?: JsonMissing.of()).map { it.toImmutable() }, - type, - units, - value, - additionalProperties.toMutableMap(), - ) - } + @JvmSynthetic + internal fun validity(): Int = + (if (absolute.asKnown().isPresent) 1 else 0) + + (if (percentage.asKnown().isPresent) 1 else 0) - private var validated: Boolean = false + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - fun validate(): Scheme = apply { - if (validated) { - return@apply + return other is Gain && + absolute == other.absolute && + percentage == other.percentage && + additionalProperties == other.additionalProperties } - additionalInfo().ifPresent { it.validate() } - cost() - gain().ifPresent { it.validate() } - isin() - name() - nav() - nominees() - transactions().ifPresent { it.forEach { it.validate() } } - type().ifPresent { it.validate() } - units() - value() - validated = true - } - - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false + private val hashCode: Int by lazy { + Objects.hash(absolute, percentage, additionalProperties) } - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + - (if (cost.asKnown().isPresent) 1 else 0) + - (gain.asKnown().getOrNull()?.validity() ?: 0) + - (if (isin.asKnown().isPresent) 1 else 0) + - (if (name.asKnown().isPresent) 1 else 0) + - (if (nav.asKnown().isPresent) 1 else 0) + - (nominees.asKnown().getOrNull()?.size ?: 0) + - (transactions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + - (type.asKnown().getOrNull()?.validity() ?: 0) + - (if (units.asKnown().isPresent) 1 else 0) + - (if (value.asKnown().isPresent) 1 else 0) + override fun hashCode(): Int = hashCode + + override fun toString() = + "Gain{absolute=$absolute, percentage=$percentage, additionalProperties=$additionalProperties}" + } - /** Additional information specific to the scheme */ - class AdditionalInfo + /** + * Unified transaction schema for all holding types (MF folios, equities, bonds, etc.) + */ + class Transaction @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val advisor: JsonField, - private val amfi: JsonField, - private val closeUnits: JsonField, - private val openUnits: JsonField, - private val rtaCode: JsonField, + private val additionalInfo: JsonField, + private val amount: JsonField, + private val balance: JsonField, + private val date: JsonField, + private val description: JsonField, + private val dividendRate: JsonField, + private val nav: JsonField, + private val type: JsonField, + private val units: JsonField, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( - @JsonProperty("advisor") + @JsonProperty("additional_info") @ExcludeMissing - advisor: JsonField = JsonMissing.of(), - @JsonProperty("amfi") + additionalInfo: JsonField = JsonMissing.of(), + @JsonProperty("amount") @ExcludeMissing - amfi: JsonField = JsonMissing.of(), - @JsonProperty("close_units") + amount: JsonField = JsonMissing.of(), + @JsonProperty("balance") @ExcludeMissing - closeUnits: JsonField = JsonMissing.of(), - @JsonProperty("open_units") + balance: JsonField = JsonMissing.of(), + @JsonProperty("date") @ExcludeMissing - openUnits: JsonField = JsonMissing.of(), - @JsonProperty("rta_code") + date: JsonField = JsonMissing.of(), + @JsonProperty("description") @ExcludeMissing - rtaCode: JsonField = JsonMissing.of(), - ) : this(advisor, amfi, closeUnits, openUnits, rtaCode, mutableMapOf()) + description: JsonField = JsonMissing.of(), + @JsonProperty("dividend_rate") + @ExcludeMissing + dividendRate: JsonField = JsonMissing.of(), + @JsonProperty("nav") @ExcludeMissing nav: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("units") + @ExcludeMissing + units: JsonField = JsonMissing.of(), + ) : this( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, + mutableMapOf(), + ) /** - * Financial advisor name (CAMS/KFintech) + * Additional transaction-specific fields that vary by source * * @throws CasParserInvalidDataException if the JSON field has an unexpected type * (e.g. if the server responded with an unexpected value). */ - fun advisor(): Optional = advisor.getOptional("advisor") + fun additionalInfo(): Optional = + additionalInfo.getOptional("additional_info") /** - * AMFI code for the scheme (CAMS/KFintech) + * Transaction amount in currency (computed from units × price/NAV) * * @throws CasParserInvalidDataException if the JSON field has an unexpected type * (e.g. if the server responded with an unexpected value). */ - fun amfi(): Optional = amfi.getOptional("amfi") + fun amount(): Optional = amount.getOptional("amount") /** - * Closing balance units (CAMS/KFintech) + * Balance units after transaction * * @throws CasParserInvalidDataException if the JSON field has an unexpected type * (e.g. if the server responded with an unexpected value). */ - fun closeUnits(): Optional = closeUnits.getOptional("close_units") + fun balance(): Optional = balance.getOptional("balance") /** - * Opening balance units (CAMS/KFintech) + * Transaction date (YYYY-MM-DD) * * @throws CasParserInvalidDataException if the JSON field has an unexpected type * (e.g. if the server responded with an unexpected value). */ - fun openUnits(): Optional = openUnits.getOptional("open_units") + fun date(): Optional = date.getOptional("date") /** - * RTA code for the scheme (CAMS/KFintech) + * Transaction description/particulars * * @throws CasParserInvalidDataException if the JSON field has an unexpected type * (e.g. if the server responded with an unexpected value). */ - fun rtaCode(): Optional = rtaCode.getOptional("rta_code") + fun description(): Optional = description.getOptional("description") /** - * Returns the raw JSON value of [advisor]. + * Dividend rate (for DIVIDEND_PAYOUT transactions) * - * Unlike [advisor], this method doesn't throw if the JSON field has an unexpected + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun dividendRate(): Optional = dividendRate.getOptional("dividend_rate") + + /** + * NAV/price per unit on transaction date + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun nav(): Optional = nav.getOptional("nav") + + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, REVERSAL, + * UNKNOWN. + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun type(): Optional = type.getOptional("type") + + /** + * Number of units involved in transaction + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun units(): Optional = units.getOptional("units") + + /** + * Returns the raw JSON value of [additionalInfo]. + * + * Unlike [additionalInfo], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("additional_info") + @ExcludeMissing + fun _additionalInfo(): JsonField = additionalInfo + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected * type. */ - @JsonProperty("advisor") @ExcludeMissing fun _advisor(): JsonField = advisor + @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount /** - * Returns the raw JSON value of [amfi]. + * Returns the raw JSON value of [balance]. * - * Unlike [amfi], this method doesn't throw if the JSON field has an unexpected + * Unlike [balance], this method doesn't throw if the JSON field has an unexpected * type. */ - @JsonProperty("amfi") @ExcludeMissing fun _amfi(): JsonField = amfi + @JsonProperty("balance") @ExcludeMissing fun _balance(): JsonField = balance /** - * Returns the raw JSON value of [closeUnits]. + * Returns the raw JSON value of [date]. * - * Unlike [closeUnits], this method doesn't throw if the JSON field has an + * Unlike [date], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date + + /** + * Returns the raw JSON value of [description]. + * + * Unlike [description], this method doesn't throw if the JSON field has an * unexpected type. */ - @JsonProperty("close_units") + @JsonProperty("description") @ExcludeMissing - fun _closeUnits(): JsonField = closeUnits + fun _description(): JsonField = description /** - * Returns the raw JSON value of [openUnits]. + * Returns the raw JSON value of [dividendRate]. * - * Unlike [openUnits], this method doesn't throw if the JSON field has an unexpected - * type. + * Unlike [dividendRate], this method doesn't throw if the JSON field has an + * unexpected type. */ - @JsonProperty("open_units") + @JsonProperty("dividend_rate") @ExcludeMissing - fun _openUnits(): JsonField = openUnits + fun _dividendRate(): JsonField = dividendRate /** - * Returns the raw JSON value of [rtaCode]. + * Returns the raw JSON value of [nav]. * - * Unlike [rtaCode], this method doesn't throw if the JSON field has an unexpected + * Unlike [nav], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("nav") @ExcludeMissing fun _nav(): JsonField = nav + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected * type. */ - @JsonProperty("rta_code") - @ExcludeMissing - fun _rtaCode(): JsonField = rtaCode + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [units]. + * + * Unlike [units], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { @@ -6472,95 +14752,191 @@ private constructor( companion object { - /** - * Returns a mutable builder for constructing an instance of [AdditionalInfo]. - */ + /** Returns a mutable builder for constructing an instance of [Transaction]. */ @JvmStatic fun builder() = Builder() } - /** A builder for [AdditionalInfo]. */ + /** A builder for [Transaction]. */ class Builder internal constructor() { - private var advisor: JsonField = JsonMissing.of() - private var amfi: JsonField = JsonMissing.of() - private var closeUnits: JsonField = JsonMissing.of() - private var openUnits: JsonField = JsonMissing.of() - private var rtaCode: JsonField = JsonMissing.of() + private var additionalInfo: JsonField = JsonMissing.of() + private var amount: JsonField = JsonMissing.of() + private var balance: JsonField = JsonMissing.of() + private var date: JsonField = JsonMissing.of() + private var description: JsonField = JsonMissing.of() + private var dividendRate: JsonField = JsonMissing.of() + private var nav: JsonField = JsonMissing.of() + private var type: JsonField = JsonMissing.of() + private var units: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(additionalInfo: AdditionalInfo) = apply { - advisor = additionalInfo.advisor - amfi = additionalInfo.amfi - closeUnits = additionalInfo.closeUnits - openUnits = additionalInfo.openUnits - rtaCode = additionalInfo.rtaCode - additionalProperties = additionalInfo.additionalProperties.toMutableMap() + internal fun from(transaction: Transaction) = apply { + additionalInfo = transaction.additionalInfo + amount = transaction.amount + balance = transaction.balance + date = transaction.date + description = transaction.description + dividendRate = transaction.dividendRate + nav = transaction.nav + type = transaction.type + units = transaction.units + additionalProperties = transaction.additionalProperties.toMutableMap() + } + + /** Additional transaction-specific fields that vary by source */ + fun additionalInfo(additionalInfo: AdditionalInfo) = + additionalInfo(JsonField.of(additionalInfo)) + + /** + * Sets [Builder.additionalInfo] to an arbitrary JSON value. + * + * You should usually call [Builder.additionalInfo] with a well-typed + * [AdditionalInfo] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun additionalInfo(additionalInfo: JsonField) = apply { + this.additionalInfo = additionalInfo + } + + /** Transaction amount in currency (computed from units × price/NAV) */ + fun amount(amount: Float?) = amount(JsonField.ofNullable(amount)) + + /** + * Alias for [Builder.amount]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun amount(amount: Float) = amount(amount as Float?) + + /** Alias for calling [Builder.amount] with `amount.orElse(null)`. */ + fun amount(amount: Optional) = amount(amount.getOrNull()) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun amount(amount: JsonField) = apply { this.amount = amount } + + /** Balance units after transaction */ + fun balance(balance: Float) = balance(JsonField.of(balance)) + + /** + * Sets [Builder.balance] to an arbitrary JSON value. + * + * You should usually call [Builder.balance] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun balance(balance: JsonField) = apply { this.balance = balance } + + /** Transaction date (YYYY-MM-DD) */ + fun date(date: LocalDate) = date(JsonField.of(date)) + + /** + * Sets [Builder.date] to an arbitrary JSON value. + * + * You should usually call [Builder.date] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun date(date: JsonField) = apply { this.date = date } + + /** Transaction description/particulars */ + fun description(description: String) = description(JsonField.of(description)) + + /** + * Sets [Builder.description] to an arbitrary JSON value. + * + * You should usually call [Builder.description] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun description(description: JsonField) = apply { + this.description = description } - /** Financial advisor name (CAMS/KFintech) */ - fun advisor(advisor: String) = advisor(JsonField.of(advisor)) + /** Dividend rate (for DIVIDEND_PAYOUT transactions) */ + fun dividendRate(dividendRate: Float?) = + dividendRate(JsonField.ofNullable(dividendRate)) /** - * Sets [Builder.advisor] to an arbitrary JSON value. + * Alias for [Builder.dividendRate]. * - * You should usually call [Builder.advisor] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * This unboxed primitive overload exists for backwards compatibility. */ - fun advisor(advisor: JsonField) = apply { this.advisor = advisor } + fun dividendRate(dividendRate: Float) = dividendRate(dividendRate as Float?) - /** AMFI code for the scheme (CAMS/KFintech) */ - fun amfi(amfi: String) = amfi(JsonField.of(amfi)) + /** + * Alias for calling [Builder.dividendRate] with `dividendRate.orElse(null)`. + */ + fun dividendRate(dividendRate: Optional) = + dividendRate(dividendRate.getOrNull()) /** - * Sets [Builder.amfi] to an arbitrary JSON value. + * Sets [Builder.dividendRate] to an arbitrary JSON value. * - * You should usually call [Builder.amfi] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * You should usually call [Builder.dividendRate] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. */ - fun amfi(amfi: JsonField) = apply { this.amfi = amfi } + fun dividendRate(dividendRate: JsonField) = apply { + this.dividendRate = dividendRate + } - /** Closing balance units (CAMS/KFintech) */ - fun closeUnits(closeUnits: Float) = closeUnits(JsonField.of(closeUnits)) + /** NAV/price per unit on transaction date */ + fun nav(nav: Float?) = nav(JsonField.ofNullable(nav)) /** - * Sets [Builder.closeUnits] to an arbitrary JSON value. + * Alias for [Builder.nav]. * - * You should usually call [Builder.closeUnits] with a well-typed [Float] value + * This unboxed primitive overload exists for backwards compatibility. + */ + fun nav(nav: Float) = nav(nav as Float?) + + /** Alias for calling [Builder.nav] with `nav.orElse(null)`. */ + fun nav(nav: Optional) = nav(nav.getOrNull()) + + /** + * Sets [Builder.nav] to an arbitrary JSON value. + * + * You should usually call [Builder.nav] with a well-typed [Float] value * instead. This method is primarily for setting the field to an undocumented or * not yet supported value. */ - fun closeUnits(closeUnits: JsonField) = apply { - this.closeUnits = closeUnits - } + fun nav(nav: JsonField) = apply { this.nav = nav } - /** Opening balance units (CAMS/KFintech) */ - fun openUnits(openUnits: Float) = openUnits(JsonField.of(openUnits)) + /** + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, + * REVERSAL, UNKNOWN. + */ + fun type(type: Type) = type(JsonField.of(type)) /** - * Sets [Builder.openUnits] to an arbitrary JSON value. + * Sets [Builder.type] to an arbitrary JSON value. * - * You should usually call [Builder.openUnits] with a well-typed [Float] value + * You should usually call [Builder.type] with a well-typed [Type] value * instead. This method is primarily for setting the field to an undocumented or * not yet supported value. */ - fun openUnits(openUnits: JsonField) = apply { - this.openUnits = openUnits - } + fun type(type: JsonField) = apply { this.type = type } - /** RTA code for the scheme (CAMS/KFintech) */ - fun rtaCode(rtaCode: String) = rtaCode(JsonField.of(rtaCode)) + /** Number of units involved in transaction */ + fun units(units: Float) = units(JsonField.of(units)) /** - * Sets [Builder.rtaCode] to an arbitrary JSON value. + * Sets [Builder.units] to an arbitrary JSON value. * - * You should usually call [Builder.rtaCode] with a well-typed [String] value + * You should usually call [Builder.units] with a well-typed [Float] value * instead. This method is primarily for setting the field to an undocumented or * not yet supported value. */ - fun rtaCode(rtaCode: JsonField) = apply { this.rtaCode = rtaCode } + fun units(units: JsonField) = apply { this.units = units } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -6585,33 +14961,41 @@ private constructor( } /** - * Returns an immutable instance of [AdditionalInfo]. + * Returns an immutable instance of [Transaction]. * * Further updates to this [Builder] will not mutate the returned instance. */ - fun build(): AdditionalInfo = - AdditionalInfo( - advisor, - amfi, - closeUnits, - openUnits, - rtaCode, + fun build(): Transaction = + Transaction( + additionalInfo, + amount, + balance, + date, + description, + dividendRate, + nav, + type, + units, additionalProperties.toMutableMap(), ) } private var validated: Boolean = false - fun validate(): AdditionalInfo = apply { + fun validate(): Transaction = apply { if (validated) { return@apply } - advisor() - amfi() - closeUnits() - openUnits() - rtaCode() + additionalInfo().ifPresent { it.validate() } + amount() + balance() + date() + description() + dividendRate() + nav() + type().ifPresent { it.validate() } + units() validated = true } @@ -6631,654 +15015,663 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (if (advisor.asKnown().isPresent) 1 else 0) + - (if (amfi.asKnown().isPresent) 1 else 0) + - (if (closeUnits.asKnown().isPresent) 1 else 0) + - (if (openUnits.asKnown().isPresent) 1 else 0) + - (if (rtaCode.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is AdditionalInfo && - advisor == other.advisor && - amfi == other.amfi && - closeUnits == other.closeUnits && - openUnits == other.openUnits && - rtaCode == other.rtaCode && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash( - advisor, - amfi, - closeUnits, - openUnits, - rtaCode, - additionalProperties, - ) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "AdditionalInfo{advisor=$advisor, amfi=$amfi, closeUnits=$closeUnits, openUnits=$openUnits, rtaCode=$rtaCode, additionalProperties=$additionalProperties}" - } - - class Gain - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val absolute: JsonField, - private val percentage: JsonField, - private val additionalProperties: MutableMap, - ) { + (additionalInfo.asKnown().getOrNull()?.validity() ?: 0) + + (if (amount.asKnown().isPresent) 1 else 0) + + (if (balance.asKnown().isPresent) 1 else 0) + + (if (date.asKnown().isPresent) 1 else 0) + + (if (description.asKnown().isPresent) 1 else 0) + + (if (dividendRate.asKnown().isPresent) 1 else 0) + + (if (nav.asKnown().isPresent) 1 else 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (units.asKnown().isPresent) 1 else 0) - @JsonCreator + /** Additional transaction-specific fields that vary by source */ + class AdditionalInfo + @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - @JsonProperty("absolute") - @ExcludeMissing - absolute: JsonField = JsonMissing.of(), - @JsonProperty("percentage") - @ExcludeMissing - percentage: JsonField = JsonMissing.of(), - ) : this(absolute, percentage, mutableMapOf()) - - /** - * Absolute gain or loss - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun absolute(): Optional = absolute.getOptional("absolute") - - /** - * Percentage gain or loss - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun percentage(): Optional = percentage.getOptional("percentage") + private val capitalWithdrawal: JsonField, + private val credit: JsonField, + private val debit: JsonField, + private val incomeDistribution: JsonField, + private val orderNo: JsonField, + private val price: JsonField, + private val stampDuty: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("capital_withdrawal") + @ExcludeMissing + capitalWithdrawal: JsonField = JsonMissing.of(), + @JsonProperty("credit") + @ExcludeMissing + credit: JsonField = JsonMissing.of(), + @JsonProperty("debit") + @ExcludeMissing + debit: JsonField = JsonMissing.of(), + @JsonProperty("income_distribution") + @ExcludeMissing + incomeDistribution: JsonField = JsonMissing.of(), + @JsonProperty("order_no") + @ExcludeMissing + orderNo: JsonField = JsonMissing.of(), + @JsonProperty("price") + @ExcludeMissing + price: JsonField = JsonMissing.of(), + @JsonProperty("stamp_duty") + @ExcludeMissing + stampDuty: JsonField = JsonMissing.of(), + ) : this( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + mutableMapOf(), + ) - /** - * Returns the raw JSON value of [absolute]. - * - * Unlike [absolute], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("absolute") - @ExcludeMissing - fun _absolute(): JsonField = absolute + /** + * Capital withdrawal amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun capitalWithdrawal(): Optional = + capitalWithdrawal.getOptional("capital_withdrawal") - /** - * Returns the raw JSON value of [percentage]. - * - * Unlike [percentage], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("percentage") - @ExcludeMissing - fun _percentage(): JsonField = percentage + /** + * Units credited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun credit(): Optional = credit.getOptional("credit") - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** + * Units debited (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun debit(): Optional = debit.getOptional("debit") - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + /** + * Income distribution amount (CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun incomeDistribution(): Optional = + incomeDistribution.getOptional("income_distribution") - fun toBuilder() = Builder().from(this) + /** + * Order/transaction reference number (demat transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun orderNo(): Optional = orderNo.getOptional("order_no") - companion object { + /** + * Price per unit (NSDL/CDSL MF transactions) + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun price(): Optional = price.getOptional("price") - /** Returns a mutable builder for constructing an instance of [Gain]. */ - @JvmStatic fun builder() = Builder() - } + /** + * Stamp duty charged + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun stampDuty(): Optional = stampDuty.getOptional("stamp_duty") - /** A builder for [Gain]. */ - class Builder internal constructor() { + /** + * Returns the raw JSON value of [capitalWithdrawal]. + * + * Unlike [capitalWithdrawal], this method doesn't throw if the JSON field has + * an unexpected type. + */ + @JsonProperty("capital_withdrawal") + @ExcludeMissing + fun _capitalWithdrawal(): JsonField = capitalWithdrawal - private var absolute: JsonField = JsonMissing.of() - private var percentage: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + /** + * Returns the raw JSON value of [credit]. + * + * Unlike [credit], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("credit") @ExcludeMissing fun _credit(): JsonField = credit - @JvmSynthetic - internal fun from(gain: Gain) = apply { - absolute = gain.absolute - percentage = gain.percentage - additionalProperties = gain.additionalProperties.toMutableMap() - } + /** + * Returns the raw JSON value of [debit]. + * + * Unlike [debit], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("debit") @ExcludeMissing fun _debit(): JsonField = debit - /** Absolute gain or loss */ - fun absolute(absolute: Float) = absolute(JsonField.of(absolute)) + /** + * Returns the raw JSON value of [incomeDistribution]. + * + * Unlike [incomeDistribution], this method doesn't throw if the JSON field has + * an unexpected type. + */ + @JsonProperty("income_distribution") + @ExcludeMissing + fun _incomeDistribution(): JsonField = incomeDistribution /** - * Sets [Builder.absolute] to an arbitrary JSON value. + * Returns the raw JSON value of [orderNo]. * - * You should usually call [Builder.absolute] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * Unlike [orderNo], this method doesn't throw if the JSON field has an + * unexpected type. */ - fun absolute(absolute: JsonField) = apply { this.absolute = absolute } + @JsonProperty("order_no") + @ExcludeMissing + fun _orderNo(): JsonField = orderNo - /** Percentage gain or loss */ - fun percentage(percentage: Float) = percentage(JsonField.of(percentage)) + /** + * Returns the raw JSON value of [price]. + * + * Unlike [price], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("price") @ExcludeMissing fun _price(): JsonField = price /** - * Sets [Builder.percentage] to an arbitrary JSON value. + * Returns the raw JSON value of [stampDuty]. * - * You should usually call [Builder.percentage] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * Unlike [stampDuty], this method doesn't throw if the JSON field has an + * unexpected type. */ - fun percentage(percentage: JsonField) = apply { - this.percentage = percentage - } + @JsonProperty("stamp_duty") + @ExcludeMissing + fun _stampDuty(): JsonField = stampDuty - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) } - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [AdditionalInfo]. + */ + @JvmStatic fun builder() = Builder() } - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) + /** A builder for [AdditionalInfo]. */ + class Builder internal constructor() { + + private var capitalWithdrawal: JsonField = JsonMissing.of() + private var credit: JsonField = JsonMissing.of() + private var debit: JsonField = JsonMissing.of() + private var incomeDistribution: JsonField = JsonMissing.of() + private var orderNo: JsonField = JsonMissing.of() + private var price: JsonField = JsonMissing.of() + private var stampDuty: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(additionalInfo: AdditionalInfo) = apply { + capitalWithdrawal = additionalInfo.capitalWithdrawal + credit = additionalInfo.credit + debit = additionalInfo.debit + incomeDistribution = additionalInfo.incomeDistribution + orderNo = additionalInfo.orderNo + price = additionalInfo.price + stampDuty = additionalInfo.stampDuty + additionalProperties = + additionalInfo.additionalProperties.toMutableMap() } - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } + /** Capital withdrawal amount (CDSL MF transactions) */ + fun capitalWithdrawal(capitalWithdrawal: Float) = + capitalWithdrawal(JsonField.of(capitalWithdrawal)) - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + /** + * Sets [Builder.capitalWithdrawal] to an arbitrary JSON value. + * + * You should usually call [Builder.capitalWithdrawal] with a well-typed + * [Float] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun capitalWithdrawal(capitalWithdrawal: JsonField) = apply { + this.capitalWithdrawal = capitalWithdrawal + } - /** - * Returns an immutable instance of [Gain]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Gain = - Gain(absolute, percentage, additionalProperties.toMutableMap()) - } + /** Units credited (demat transactions) */ + fun credit(credit: Float) = credit(JsonField.of(credit)) - private var validated: Boolean = false + /** + * Sets [Builder.credit] to an arbitrary JSON value. + * + * You should usually call [Builder.credit] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun credit(credit: JsonField) = apply { this.credit = credit } - fun validate(): Gain = apply { - if (validated) { - return@apply - } + /** Units debited (demat transactions) */ + fun debit(debit: Float) = debit(JsonField.of(debit)) - absolute() - percentage() - validated = true - } + /** + * Sets [Builder.debit] to an arbitrary JSON value. + * + * You should usually call [Builder.debit] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun debit(debit: JsonField) = apply { this.debit = debit } - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + /** Income distribution amount (CDSL MF transactions) */ + fun incomeDistribution(incomeDistribution: Float) = + incomeDistribution(JsonField.of(incomeDistribution)) - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (absolute.asKnown().isPresent) 1 else 0) + - (if (percentage.asKnown().isPresent) 1 else 0) + /** + * Sets [Builder.incomeDistribution] to an arbitrary JSON value. + * + * You should usually call [Builder.incomeDistribution] with a well-typed + * [Float] value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun incomeDistribution(incomeDistribution: JsonField) = apply { + this.incomeDistribution = incomeDistribution + } - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** Order/transaction reference number (demat transactions) */ + fun orderNo(orderNo: String) = orderNo(JsonField.of(orderNo)) - return other is Gain && - absolute == other.absolute && - percentage == other.percentage && - additionalProperties == other.additionalProperties - } + /** + * Sets [Builder.orderNo] to an arbitrary JSON value. + * + * You should usually call [Builder.orderNo] with a well-typed [String] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun orderNo(orderNo: JsonField) = apply { this.orderNo = orderNo } - private val hashCode: Int by lazy { - Objects.hash(absolute, percentage, additionalProperties) - } + /** Price per unit (NSDL/CDSL MF transactions) */ + fun price(price: Float) = price(JsonField.of(price)) - override fun hashCode(): Int = hashCode + /** + * Sets [Builder.price] to an arbitrary JSON value. + * + * You should usually call [Builder.price] with a well-typed [Float] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun price(price: JsonField) = apply { this.price = price } - override fun toString() = - "Gain{absolute=$absolute, percentage=$percentage, additionalProperties=$additionalProperties}" - } + /** Stamp duty charged */ + fun stampDuty(stampDuty: Float) = stampDuty(JsonField.of(stampDuty)) - class Transaction - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val amount: JsonField, - private val balance: JsonField, - private val date: JsonField, - private val description: JsonField, - private val dividendRate: JsonField, - private val nav: JsonField, - private val type: JsonField, - private val units: JsonField, - private val additionalProperties: MutableMap, - ) { + /** + * Sets [Builder.stampDuty] to an arbitrary JSON value. + * + * You should usually call [Builder.stampDuty] with a well-typed [Float] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun stampDuty(stampDuty: JsonField) = apply { + this.stampDuty = stampDuty + } - @JsonCreator - private constructor( - @JsonProperty("amount") - @ExcludeMissing - amount: JsonField = JsonMissing.of(), - @JsonProperty("balance") - @ExcludeMissing - balance: JsonField = JsonMissing.of(), - @JsonProperty("date") - @ExcludeMissing - date: JsonField = JsonMissing.of(), - @JsonProperty("description") - @ExcludeMissing - description: JsonField = JsonMissing.of(), - @JsonProperty("dividend_rate") - @ExcludeMissing - dividendRate: JsonField = JsonMissing.of(), - @JsonProperty("nav") @ExcludeMissing nav: JsonField = JsonMissing.of(), - @JsonProperty("type") - @ExcludeMissing - type: JsonField = JsonMissing.of(), - @JsonProperty("units") - @ExcludeMissing - units: JsonField = JsonMissing.of(), - ) : this( - amount, - balance, - date, - description, - dividendRate, - nav, - type, - units, - mutableMapOf(), - ) + fun additionalProperties(additionalProperties: Map) = + apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } - /** - * Transaction amount - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun amount(): Optional = amount.getOptional("amount") + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } - /** - * Balance units after transaction - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun balance(): Optional = balance.getOptional("balance") + fun putAllAdditionalProperties( + additionalProperties: Map + ) = apply { this.additionalProperties.putAll(additionalProperties) } - /** - * Transaction date - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun date(): Optional = date.getOptional("date") + fun removeAdditionalProperty(key: String) = apply { + additionalProperties.remove(key) + } - /** - * Transaction description - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun description(): Optional = description.getOptional("description") + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } - /** - * Dividend rate (for dividend transactions) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun dividendRate(): Optional = dividendRate.getOptional("dividend_rate") + /** + * Returns an immutable instance of [AdditionalInfo]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): AdditionalInfo = + AdditionalInfo( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties.toMutableMap(), + ) + } - /** - * NAV on transaction date - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun nav(): Optional = nav.getOptional("nav") + private var validated: Boolean = false - /** - * Transaction type detected based on description. Possible values are - * PURCHASE,PURCHASE_SIP,REDEMPTION,SWITCH_IN,SWITCH_IN_MERGER,SWITCH_OUT,SWITCH_OUT_MERGER,DIVIDEND_PAYOUT,DIVIDEND_REINVESTMENT,SEGREGATION,STAMP_DUTY_TAX,TDS_TAX,STT_TAX,MISC. - * If dividend_rate is present, then possible values are dividend_rate is applicable - * only for DIVIDEND_PAYOUT and DIVIDEND_REINVESTMENT. - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun type(): Optional = type.getOptional("type") + fun validate(): AdditionalInfo = apply { + if (validated) { + return@apply + } - /** - * Number of units involved - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type - * (e.g. if the server responded with an unexpected value). - */ - fun units(): Optional = units.getOptional("units") + capitalWithdrawal() + credit() + debit() + incomeDistribution() + orderNo() + price() + stampDuty() + validated = true + } - /** - * Returns the raw JSON value of [amount]. - * - * Unlike [amount], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("amount") @ExcludeMissing fun _amount(): JsonField = amount + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } - /** - * Returns the raw JSON value of [balance]. - * - * Unlike [balance], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("balance") @ExcludeMissing fun _balance(): JsonField = balance + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (capitalWithdrawal.asKnown().isPresent) 1 else 0) + + (if (credit.asKnown().isPresent) 1 else 0) + + (if (debit.asKnown().isPresent) 1 else 0) + + (if (incomeDistribution.asKnown().isPresent) 1 else 0) + + (if (orderNo.asKnown().isPresent) 1 else 0) + + (if (price.asKnown().isPresent) 1 else 0) + + (if (stampDuty.asKnown().isPresent) 1 else 0) - /** - * Returns the raw JSON value of [date]. - * - * Unlike [date], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("date") @ExcludeMissing fun _date(): JsonField = date + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - /** - * Returns the raw JSON value of [description]. - * - * Unlike [description], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("description") - @ExcludeMissing - fun _description(): JsonField = description + return other is AdditionalInfo && + capitalWithdrawal == other.capitalWithdrawal && + credit == other.credit && + debit == other.debit && + incomeDistribution == other.incomeDistribution && + orderNo == other.orderNo && + price == other.price && + stampDuty == other.stampDuty && + additionalProperties == other.additionalProperties + } - /** - * Returns the raw JSON value of [dividendRate]. - * - * Unlike [dividendRate], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("dividend_rate") - @ExcludeMissing - fun _dividendRate(): JsonField = dividendRate + private val hashCode: Int by lazy { + Objects.hash( + capitalWithdrawal, + credit, + debit, + incomeDistribution, + orderNo, + price, + stampDuty, + additionalProperties, + ) + } - /** - * Returns the raw JSON value of [nav]. - * - * Unlike [nav], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("nav") @ExcludeMissing fun _nav(): JsonField = nav + override fun hashCode(): Int = hashCode - /** - * Returns the raw JSON value of [type]. - * - * Unlike [type], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + override fun toString() = + "AdditionalInfo{capitalWithdrawal=$capitalWithdrawal, credit=$credit, debit=$debit, incomeDistribution=$incomeDistribution, orderNo=$orderNo, price=$price, stampDuty=$stampDuty, additionalProperties=$additionalProperties}" + } /** - * Returns the raw JSON value of [units]. - * - * Unlike [units], this method doesn't throw if the JSON field has an unexpected - * type. + * Transaction type. Possible values are PURCHASE, PURCHASE_SIP, REDEMPTION, + * SWITCH_IN, SWITCH_IN_MERGER, SWITCH_OUT, SWITCH_OUT_MERGER, DIVIDEND_PAYOUT, + * DIVIDEND_REINVEST, SEGREGATION, STAMP_DUTY_TAX, TDS_TAX, STT_TAX, MISC, REVERSAL, + * UNKNOWN. */ - @JsonProperty("units") @ExcludeMissing fun _units(): JsonField = units + class Type @JsonCreator private constructor(private val value: JsonField) : + Enum { - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue + fun _value(): JsonField = value - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + companion object { - fun toBuilder() = Builder().from(this) + @JvmField val PURCHASE = of("PURCHASE") - companion object { + @JvmField val PURCHASE_SIP = of("PURCHASE_SIP") - /** Returns a mutable builder for constructing an instance of [Transaction]. */ - @JvmStatic fun builder() = Builder() - } + @JvmField val REDEMPTION = of("REDEMPTION") - /** A builder for [Transaction]. */ - class Builder internal constructor() { + @JvmField val SWITCH_IN = of("SWITCH_IN") - private var amount: JsonField = JsonMissing.of() - private var balance: JsonField = JsonMissing.of() - private var date: JsonField = JsonMissing.of() - private var description: JsonField = JsonMissing.of() - private var dividendRate: JsonField = JsonMissing.of() - private var nav: JsonField = JsonMissing.of() - private var type: JsonField = JsonMissing.of() - private var units: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + @JvmField val SWITCH_IN_MERGER = of("SWITCH_IN_MERGER") - @JvmSynthetic - internal fun from(transaction: Transaction) = apply { - amount = transaction.amount - balance = transaction.balance - date = transaction.date - description = transaction.description - dividendRate = transaction.dividendRate - nav = transaction.nav - type = transaction.type - units = transaction.units - additionalProperties = transaction.additionalProperties.toMutableMap() - } + @JvmField val SWITCH_OUT = of("SWITCH_OUT") - /** Transaction amount */ - fun amount(amount: Float) = amount(JsonField.of(amount)) + @JvmField val SWITCH_OUT_MERGER = of("SWITCH_OUT_MERGER") - /** - * Sets [Builder.amount] to an arbitrary JSON value. - * - * You should usually call [Builder.amount] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun amount(amount: JsonField) = apply { this.amount = amount } + @JvmField val DIVIDEND_PAYOUT = of("DIVIDEND_PAYOUT") - /** Balance units after transaction */ - fun balance(balance: Float) = balance(JsonField.of(balance)) + @JvmField val DIVIDEND_REINVEST = of("DIVIDEND_REINVEST") - /** - * Sets [Builder.balance] to an arbitrary JSON value. - * - * You should usually call [Builder.balance] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun balance(balance: JsonField) = apply { this.balance = balance } + @JvmField val SEGREGATION = of("SEGREGATION") - /** Transaction date */ - fun date(date: LocalDate) = date(JsonField.of(date)) + @JvmField val STAMP_DUTY_TAX = of("STAMP_DUTY_TAX") - /** - * Sets [Builder.date] to an arbitrary JSON value. - * - * You should usually call [Builder.date] with a well-typed [LocalDate] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun date(date: JsonField) = apply { this.date = date } + @JvmField val TDS_TAX = of("TDS_TAX") - /** Transaction description */ - fun description(description: String) = description(JsonField.of(description)) + @JvmField val STT_TAX = of("STT_TAX") - /** - * Sets [Builder.description] to an arbitrary JSON value. - * - * You should usually call [Builder.description] with a well-typed [String] - * value instead. This method is primarily for setting the field to an - * undocumented or not yet supported value. - */ - fun description(description: JsonField) = apply { - this.description = description - } + @JvmField val MISC = of("MISC") - /** Dividend rate (for dividend transactions) */ - fun dividendRate(dividendRate: Float) = dividendRate(JsonField.of(dividendRate)) + @JvmField val REVERSAL = of("REVERSAL") - /** - * Sets [Builder.dividendRate] to an arbitrary JSON value. - * - * You should usually call [Builder.dividendRate] with a well-typed [Float] - * value instead. This method is primarily for setting the field to an - * undocumented or not yet supported value. - */ - fun dividendRate(dividendRate: JsonField) = apply { - this.dividendRate = dividendRate + @JvmField val UNKNOWN = of("UNKNOWN") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) } - /** NAV on transaction date */ - fun nav(nav: Float) = nav(JsonField.of(nav)) + /** An enum containing [Type]'s known values. */ + enum class Known { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + } /** - * Sets [Builder.nav] to an arbitrary JSON value. + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. * - * You should usually call [Builder.nav] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For + * example, if the SDK is on an older version than the API, then the API may + * respond with new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. */ - fun nav(nav: JsonField) = apply { this.nav = nav } + enum class Value { + PURCHASE, + PURCHASE_SIP, + REDEMPTION, + SWITCH_IN, + SWITCH_IN_MERGER, + SWITCH_OUT, + SWITCH_OUT_MERGER, + DIVIDEND_PAYOUT, + DIVIDEND_REINVEST, + SEGREGATION, + STAMP_DUTY_TAX, + TDS_TAX, + STT_TAX, + MISC, + REVERSAL, + UNKNOWN, + /** + * An enum member indicating that [Type] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } /** - * Transaction type detected based on description. Possible values are - * PURCHASE,PURCHASE_SIP,REDEMPTION,SWITCH_IN,SWITCH_IN_MERGER,SWITCH_OUT,SWITCH_OUT_MERGER,DIVIDEND_PAYOUT,DIVIDEND_REINVESTMENT,SEGREGATION,STAMP_DUTY_TAX,TDS_TAX,STT_TAX,MISC. - * If dividend_rate is present, then possible values are dividend_rate is - * applicable only for DIVIDEND_PAYOUT and DIVIDEND_REINVESTMENT. + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or + * if you want to throw for the unknown case. */ - fun type(type: String) = type(JsonField.of(type)) + fun value(): Value = + when (this) { + PURCHASE -> Value.PURCHASE + PURCHASE_SIP -> Value.PURCHASE_SIP + REDEMPTION -> Value.REDEMPTION + SWITCH_IN -> Value.SWITCH_IN + SWITCH_IN_MERGER -> Value.SWITCH_IN_MERGER + SWITCH_OUT -> Value.SWITCH_OUT + SWITCH_OUT_MERGER -> Value.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Value.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Value.DIVIDEND_REINVEST + SEGREGATION -> Value.SEGREGATION + STAMP_DUTY_TAX -> Value.STAMP_DUTY_TAX + TDS_TAX -> Value.TDS_TAX + STT_TAX -> Value.STT_TAX + MISC -> Value.MISC + REVERSAL -> Value.REVERSAL + UNKNOWN -> Value.UNKNOWN + else -> Value._UNKNOWN + } /** - * Sets [Builder.type] to an arbitrary JSON value. + * Returns an enum member corresponding to this class instance's value. * - * You should usually call [Builder.type] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * Use the [value] method instead if you're uncertain the value is always known + * and don't want to throw for the unknown case. + * + * @throws CasParserInvalidDataException if this class instance's value is a not + * a known member. */ - fun type(type: JsonField) = apply { this.type = type } - - /** Number of units involved */ - fun units(units: Float) = units(JsonField.of(units)) + fun known(): Known = + when (this) { + PURCHASE -> Known.PURCHASE + PURCHASE_SIP -> Known.PURCHASE_SIP + REDEMPTION -> Known.REDEMPTION + SWITCH_IN -> Known.SWITCH_IN + SWITCH_IN_MERGER -> Known.SWITCH_IN_MERGER + SWITCH_OUT -> Known.SWITCH_OUT + SWITCH_OUT_MERGER -> Known.SWITCH_OUT_MERGER + DIVIDEND_PAYOUT -> Known.DIVIDEND_PAYOUT + DIVIDEND_REINVEST -> Known.DIVIDEND_REINVEST + SEGREGATION -> Known.SEGREGATION + STAMP_DUTY_TAX -> Known.STAMP_DUTY_TAX + TDS_TAX -> Known.TDS_TAX + STT_TAX -> Known.STT_TAX + MISC -> Known.MISC + REVERSAL -> Known.REVERSAL + UNKNOWN -> Known.UNKNOWN + else -> throw CasParserInvalidDataException("Unknown Type: $value") + } /** - * Sets [Builder.units] to an arbitrary JSON value. + * Returns this class instance's primitive wire representation. * - * You should usually call [Builder.units] with a well-typed [Float] value - * instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws CasParserInvalidDataException if this class instance's value does not + * have the expected primitive type. */ - fun units(units: JsonField) = apply { this.units = units } - - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + fun asString(): String = + _value().asString().orElseThrow { + CasParserInvalidDataException("Value is not a String") + } - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + private var validated: Boolean = false - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) + fun validate(): Type = apply { + if (validated) { + return@apply } - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) + known() + validated = true } - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CasParserInvalidDataException) { + false + } /** - * Returns an immutable instance of [Transaction]. + * Returns a score indicating how many valid values are contained in this object + * recursively. * - * Further updates to this [Builder] will not mutate the returned instance. + * Used for best match union deserialization. */ - fun build(): Transaction = - Transaction( - amount, - balance, - date, - description, - dividendRate, - nav, - type, - units, - additionalProperties.toMutableMap(), - ) - } + @JvmSynthetic + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 - private var validated: Boolean = false + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } - fun validate(): Transaction = apply { - if (validated) { - return@apply + return other is Type && value == other.value } - amount() - balance() - date() - description() - dividendRate() - nav() - type() - units() - validated = true - } - - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } + override fun hashCode() = value.hashCode() - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (amount.asKnown().isPresent) 1 else 0) + - (if (balance.asKnown().isPresent) 1 else 0) + - (if (date.asKnown().isPresent) 1 else 0) + - (if (description.asKnown().isPresent) 1 else 0) + - (if (dividendRate.asKnown().isPresent) 1 else 0) + - (if (nav.asKnown().isPresent) 1 else 0) + - (if (type.asKnown().isPresent) 1 else 0) + - (if (units.asKnown().isPresent) 1 else 0) + override fun toString() = value.toString() + } override fun equals(other: Any?): Boolean { if (this === other) { @@ -7286,6 +15679,7 @@ private constructor( } return other is Transaction && + additionalInfo == other.additionalInfo && amount == other.amount && balance == other.balance && date == other.date && @@ -7299,6 +15693,7 @@ private constructor( private val hashCode: Int by lazy { Objects.hash( + additionalInfo, amount, balance, date, @@ -7314,7 +15709,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Transaction{amount=$amount, balance=$balance, date=$date, description=$description, dividendRate=$dividendRate, nav=$nav, type=$type, units=$units, additionalProperties=$additionalProperties}" + "Transaction{additionalInfo=$additionalInfo, amount=$amount, balance=$balance, date=$date, description=$description, dividendRate=$dividendRate, nav=$nav, type=$type, units=$units, additionalProperties=$additionalProperties}" } /** Type of mutual fund scheme */ diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/UnifiedResponseTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/UnifiedResponseTest.kt index 86f7a31..f0fa2ca 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/UnifiedResponseTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/UnifiedResponseTest.kt @@ -40,36 +40,197 @@ internal class UnifiedResponseTest { UnifiedResponse.DematAccount.Holdings.builder() .addAif( UnifiedResponse.DematAccount.Holdings.Aif.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Aif.AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.Aif.Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Aif + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings.Aif + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addCorporateBond( UnifiedResponse.DematAccount.Holdings.CorporateBond.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.CorporateBond + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.CorporateBond + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .CorporateBond + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .CorporateBond + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addDematMutualFund( UnifiedResponse.DematAccount.Holdings.DematMutualFund.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.DematMutualFund + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.DematMutualFund + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .DematMutualFund + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .DematMutualFund + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addEquity( UnifiedResponse.DematAccount.Holdings.Equity.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Equity + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.Equity.Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Equity + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings.Equity + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() @@ -77,9 +238,51 @@ internal class UnifiedResponseTest { .addGovernmentSecurity( UnifiedResponse.DematAccount.Holdings.GovernmentSecurity .builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.GovernmentSecurity + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.GovernmentSecurity + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .GovernmentSecurity + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .GovernmentSecurity + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() @@ -177,13 +380,29 @@ internal class UnifiedResponseTest { .addNominee("string") .addTransaction( UnifiedResponse.MutualFund.Scheme.Transaction.builder() + .additionalInfo( + UnifiedResponse.MutualFund.Scheme.Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) .amount(0.0f) .balance(0.0f) .date(LocalDate.parse("2019-12-27")) .description("description") .dividendRate(0.0f) .nav(0.0f) - .type("type") + .type( + UnifiedResponse.MutualFund.Scheme.Transaction.Type + .PURCHASE + ) .units(0.0f) .build() ) @@ -283,45 +502,245 @@ internal class UnifiedResponseTest { UnifiedResponse.DematAccount.Holdings.builder() .addAif( UnifiedResponse.DematAccount.Holdings.Aif.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Aif.AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.Aif.Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Aif + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings.Aif + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addCorporateBond( UnifiedResponse.DematAccount.Holdings.CorporateBond.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.CorporateBond + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.CorporateBond + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.CorporateBond + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings.CorporateBond + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addDematMutualFund( UnifiedResponse.DematAccount.Holdings.DematMutualFund.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.DematMutualFund + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.DematMutualFund + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .DematMutualFund + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .DematMutualFund + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addEquity( UnifiedResponse.DematAccount.Holdings.Equity.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Equity.AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.Equity.Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Equity + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings.Equity + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addGovernmentSecurity( UnifiedResponse.DematAccount.Holdings.GovernmentSecurity.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.GovernmentSecurity + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.GovernmentSecurity + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .GovernmentSecurity + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .GovernmentSecurity + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() @@ -423,13 +842,27 @@ internal class UnifiedResponseTest { .addNominee("string") .addTransaction( UnifiedResponse.MutualFund.Scheme.Transaction.builder() + .additionalInfo( + UnifiedResponse.MutualFund.Scheme.Transaction.AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) .amount(0.0f) .balance(0.0f) .date(LocalDate.parse("2019-12-27")) .description("description") .dividendRate(0.0f) .nav(0.0f) - .type("type") + .type( + UnifiedResponse.MutualFund.Scheme.Transaction.Type.PURCHASE + ) .units(0.0f) .build() ) @@ -532,36 +965,197 @@ internal class UnifiedResponseTest { UnifiedResponse.DematAccount.Holdings.builder() .addAif( UnifiedResponse.DematAccount.Holdings.Aif.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Aif.AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.Aif.Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Aif + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings.Aif + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addCorporateBond( UnifiedResponse.DematAccount.Holdings.CorporateBond.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.CorporateBond + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.CorporateBond + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .CorporateBond + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .CorporateBond + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addDematMutualFund( UnifiedResponse.DematAccount.Holdings.DematMutualFund.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.DematMutualFund + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.DematMutualFund + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .DematMutualFund + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .DematMutualFund + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addEquity( UnifiedResponse.DematAccount.Holdings.Equity.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Equity + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.Equity.Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Equity + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings.Equity + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() @@ -569,9 +1163,51 @@ internal class UnifiedResponseTest { .addGovernmentSecurity( UnifiedResponse.DematAccount.Holdings.GovernmentSecurity .builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.GovernmentSecurity + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.GovernmentSecurity + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .GovernmentSecurity + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .GovernmentSecurity + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() @@ -669,13 +1305,29 @@ internal class UnifiedResponseTest { .addNominee("string") .addTransaction( UnifiedResponse.MutualFund.Scheme.Transaction.builder() + .additionalInfo( + UnifiedResponse.MutualFund.Scheme.Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) .amount(0.0f) .balance(0.0f) .date(LocalDate.parse("2019-12-27")) .description("description") .dividendRate(0.0f) .nav(0.0f) - .type("type") + .type( + UnifiedResponse.MutualFund.Scheme.Transaction.Type + .PURCHASE + ) .units(0.0f) .build() ) diff --git a/cas-parser-java-proguard-test/src/test/kotlin/com/cas_parser/api/proguard/ProGuardCompatibilityTest.kt b/cas-parser-java-proguard-test/src/test/kotlin/com/cas_parser/api/proguard/ProGuardCompatibilityTest.kt index e2b76ff..a975237 100644 --- a/cas-parser-java-proguard-test/src/test/kotlin/com/cas_parser/api/proguard/ProGuardCompatibilityTest.kt +++ b/cas-parser-java-proguard-test/src/test/kotlin/com/cas_parser/api/proguard/ProGuardCompatibilityTest.kt @@ -82,36 +82,197 @@ internal class ProGuardCompatibilityTest { UnifiedResponse.DematAccount.Holdings.builder() .addAif( UnifiedResponse.DematAccount.Holdings.Aif.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Aif.AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.Aif.Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Aif + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings.Aif + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addCorporateBond( UnifiedResponse.DematAccount.Holdings.CorporateBond.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.CorporateBond + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.CorporateBond + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .CorporateBond + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .CorporateBond + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addDematMutualFund( UnifiedResponse.DematAccount.Holdings.DematMutualFund.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.DematMutualFund + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.DematMutualFund + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .DematMutualFund + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .DematMutualFund + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() ) .addEquity( UnifiedResponse.DematAccount.Holdings.Equity.builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Equity + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.Equity.Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.Equity + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings.Equity + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() @@ -119,9 +280,51 @@ internal class ProGuardCompatibilityTest { .addGovernmentSecurity( UnifiedResponse.DematAccount.Holdings.GovernmentSecurity .builder() - .additionalInfo(JsonValue.from(mapOf())) + .additionalInfo( + UnifiedResponse.DematAccount.Holdings.GovernmentSecurity + .AdditionalInfo + .builder() + .closeUnits(0.0f) + .openUnits(0.0f) + .build() + ) .isin("isin") .name("name") + .addTransaction( + UnifiedResponse.DematAccount.Holdings.GovernmentSecurity + .Transaction + .builder() + .additionalInfo( + UnifiedResponse.DematAccount.Holdings + .GovernmentSecurity + .Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) + .amount(0.0f) + .balance(0.0f) + .date(LocalDate.parse("2019-12-27")) + .description("description") + .dividendRate(0.0f) + .nav(0.0f) + .type( + UnifiedResponse.DematAccount.Holdings + .GovernmentSecurity + .Transaction + .Type + .PURCHASE + ) + .units(0.0f) + .build() + ) .units(0.0f) .value(0.0f) .build() @@ -219,13 +422,29 @@ internal class ProGuardCompatibilityTest { .addNominee("string") .addTransaction( UnifiedResponse.MutualFund.Scheme.Transaction.builder() + .additionalInfo( + UnifiedResponse.MutualFund.Scheme.Transaction + .AdditionalInfo + .builder() + .capitalWithdrawal(0.0f) + .credit(0.0f) + .debit(0.0f) + .incomeDistribution(0.0f) + .orderNo("order_no") + .price(0.0f) + .stampDuty(0.0f) + .build() + ) .amount(0.0f) .balance(0.0f) .date(LocalDate.parse("2019-12-27")) .description("description") .dividendRate(0.0f) .nav(0.0f) - .type("type") + .type( + UnifiedResponse.MutualFund.Scheme.Transaction.Type + .PURCHASE + ) .units(0.0f) .build() ) From 2e6c34fbe30670c8ae1a74eb7f0f8fc5e8bb1890 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 5 Jan 2026 02:17:20 +0000 Subject: [PATCH 7/9] feat(api): api update --- .stats.yml | 6 +- README.md | 17 - .../CasGeneratorGenerateCasParams.kt | 919 ------------------ .../CasGeneratorGenerateCasResponse.kt | 189 ---- .../async/CasGeneratorServiceAsync.kt | 36 - .../async/CasGeneratorServiceAsyncImpl.kt | 56 -- .../services/blocking/CasGeneratorService.kt | 36 - .../blocking/CasGeneratorServiceImpl.kt | 52 - .../CasGeneratorGenerateCasParamsTest.kt | 62 -- .../CasGeneratorGenerateCasResponseTest.kt | 49 - .../async/CasGeneratorServiceAsyncTest.kt | 40 - .../blocking/CasGeneratorServiceTest.kt | 39 - 12 files changed, 3 insertions(+), 1498 deletions(-) delete mode 100644 cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParams.kt delete mode 100644 cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponse.kt delete mode 100644 cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParamsTest.kt delete mode 100644 cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponseTest.kt delete mode 100644 cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsyncTest.kt delete mode 100644 cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/blocking/CasGeneratorServiceTest.kt diff --git a/.stats.yml b/.stats.yml index 48b33b3..4465de7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 5 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-38618cc5c938e87eeacf4893d6a6ba4e6ef7da390e6283dc7b50b484a7b97165.yml -openapi_spec_hash: b9e439ecee904ded01aa34efdee88856 +configured_endpoints: 4 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-7e6397bddc220d1a59b5e2c7e7c3ff38f1a6eb174f4e383e03bc49cf78c8c44f.yml +openapi_spec_hash: cb852eeb4ce89c80f4246815cbe21f72 config_hash: cb5d75abef6264b5d86448caf7295afa diff --git a/README.md b/README.md index 15ce0f4..878f4b9 100644 --- a/README.md +++ b/README.md @@ -476,23 +476,6 @@ JsonValue complexValue = JsonValue.from(Map.of( )); ``` -Normally a `Builder` class's `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset. - -To forcibly omit a required parameter or property, pass [`JsonMissing`](cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/Values.kt): - -```java -import com.cas_parser.api.core.JsonMissing; -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasParams; -import com.cas_parser.api.models.casparser.CasParserSmartParseParams; - -CasParserSmartParseParams params = CasGeneratorGenerateCasParams.builder() - .fromDate("2023-01-01") - .password("Abcdefghi12$") - .toDate("2023-12-31") - .email(JsonMissing.of()) - .build(); -``` - ### Response properties To access undocumented response properties, call the `_additionalProperties()` method: diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParams.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParams.kt deleted file mode 100644 index 598c6a2..0000000 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParams.kt +++ /dev/null @@ -1,919 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.cas_parser.api.models.casgenerator - -import com.cas_parser.api.core.Enum -import com.cas_parser.api.core.ExcludeMissing -import com.cas_parser.api.core.JsonField -import com.cas_parser.api.core.JsonMissing -import com.cas_parser.api.core.JsonValue -import com.cas_parser.api.core.Params -import com.cas_parser.api.core.checkRequired -import com.cas_parser.api.core.http.Headers -import com.cas_parser.api.core.http.QueryParams -import com.cas_parser.api.errors.CasParserInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import java.util.Collections -import java.util.Objects -import java.util.Optional -import kotlin.jvm.optionals.getOrNull - -/** - * This endpoint generates CAS (Consolidated Account Statement) documents by submitting a mailback - * request to the specified CAS authority. Currently only supports KFintech, with plans to support - * CAMS, CDSL, and NSDL in the future. - */ -class CasGeneratorGenerateCasParams -private constructor( - private val body: Body, - private val additionalHeaders: Headers, - private val additionalQueryParams: QueryParams, -) : Params { - - /** - * Email address to receive the CAS document - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun email(): String = body.email() - - /** - * Start date for the CAS period (format YYYY-MM-DD) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun fromDate(): String = body.fromDate() - - /** - * Password to protect the generated CAS PDF - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun password(): String = body.password() - - /** - * End date for the CAS period (format YYYY-MM-DD) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun toDate(): String = body.toDate() - - /** - * CAS authority to generate the document from (currently only kfintech is supported) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun casAuthority(): Optional = body.casAuthority() - - /** - * PAN number (optional for some CAS authorities) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun panNo(): Optional = body.panNo() - - /** - * Returns the raw JSON value of [email]. - * - * Unlike [email], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _email(): JsonField = body._email() - - /** - * Returns the raw JSON value of [fromDate]. - * - * Unlike [fromDate], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _fromDate(): JsonField = body._fromDate() - - /** - * Returns the raw JSON value of [password]. - * - * Unlike [password], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _password(): JsonField = body._password() - - /** - * Returns the raw JSON value of [toDate]. - * - * Unlike [toDate], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _toDate(): JsonField = body._toDate() - - /** - * Returns the raw JSON value of [casAuthority]. - * - * Unlike [casAuthority], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _casAuthority(): JsonField = body._casAuthority() - - /** - * Returns the raw JSON value of [panNo]. - * - * Unlike [panNo], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _panNo(): JsonField = body._panNo() - - fun _additionalBodyProperties(): Map = body._additionalProperties() - - /** Additional headers to send with the request. */ - fun _additionalHeaders(): Headers = additionalHeaders - - /** Additional query param to send with the request. */ - fun _additionalQueryParams(): QueryParams = additionalQueryParams - - fun toBuilder() = Builder().from(this) - - companion object { - - /** - * Returns a mutable builder for constructing an instance of - * [CasGeneratorGenerateCasParams]. - * - * The following fields are required: - * ```java - * .email() - * .fromDate() - * .password() - * .toDate() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [CasGeneratorGenerateCasParams]. */ - class Builder internal constructor() { - - private var body: Body.Builder = Body.builder() - private var additionalHeaders: Headers.Builder = Headers.builder() - private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() - - @JvmSynthetic - internal fun from(casGeneratorGenerateCasParams: CasGeneratorGenerateCasParams) = apply { - body = casGeneratorGenerateCasParams.body.toBuilder() - additionalHeaders = casGeneratorGenerateCasParams.additionalHeaders.toBuilder() - additionalQueryParams = casGeneratorGenerateCasParams.additionalQueryParams.toBuilder() - } - - /** - * Sets the entire request body. - * - * This is generally only useful if you are already constructing the body separately. - * Otherwise, it's more convenient to use the top-level setters instead: - * - [email] - * - [fromDate] - * - [password] - * - [toDate] - * - [casAuthority] - * - etc. - */ - fun body(body: Body) = apply { this.body = body.toBuilder() } - - /** Email address to receive the CAS document */ - fun email(email: String) = apply { body.email(email) } - - /** - * Sets [Builder.email] to an arbitrary JSON value. - * - * You should usually call [Builder.email] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun email(email: JsonField) = apply { body.email(email) } - - /** Start date for the CAS period (format YYYY-MM-DD) */ - fun fromDate(fromDate: String) = apply { body.fromDate(fromDate) } - - /** - * Sets [Builder.fromDate] to an arbitrary JSON value. - * - * You should usually call [Builder.fromDate] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun fromDate(fromDate: JsonField) = apply { body.fromDate(fromDate) } - - /** Password to protect the generated CAS PDF */ - fun password(password: String) = apply { body.password(password) } - - /** - * Sets [Builder.password] to an arbitrary JSON value. - * - * You should usually call [Builder.password] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun password(password: JsonField) = apply { body.password(password) } - - /** End date for the CAS period (format YYYY-MM-DD) */ - fun toDate(toDate: String) = apply { body.toDate(toDate) } - - /** - * Sets [Builder.toDate] to an arbitrary JSON value. - * - * You should usually call [Builder.toDate] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun toDate(toDate: JsonField) = apply { body.toDate(toDate) } - - /** CAS authority to generate the document from (currently only kfintech is supported) */ - fun casAuthority(casAuthority: CasAuthority) = apply { body.casAuthority(casAuthority) } - - /** - * Sets [Builder.casAuthority] to an arbitrary JSON value. - * - * You should usually call [Builder.casAuthority] with a well-typed [CasAuthority] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun casAuthority(casAuthority: JsonField) = apply { - body.casAuthority(casAuthority) - } - - /** PAN number (optional for some CAS authorities) */ - fun panNo(panNo: String) = apply { body.panNo(panNo) } - - /** - * Sets [Builder.panNo] to an arbitrary JSON value. - * - * You should usually call [Builder.panNo] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun panNo(panNo: JsonField) = apply { body.panNo(panNo) } - - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - - fun additionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun additionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.clear() - putAllAdditionalHeaders(additionalHeaders) - } - - fun putAdditionalHeader(name: String, value: String) = apply { - additionalHeaders.put(name, value) - } - - fun putAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.put(name, values) - } - - fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.putAll(additionalHeaders) - } - - fun replaceAdditionalHeaders(name: String, value: String) = apply { - additionalHeaders.replace(name, value) - } - - fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { - additionalHeaders.replace(name, values) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { - this.additionalHeaders.replaceAll(additionalHeaders) - } - - fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } - - fun removeAllAdditionalHeaders(names: Set) = apply { - additionalHeaders.removeAll(names) - } - - fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun additionalQueryParams(additionalQueryParams: Map>) = apply { - this.additionalQueryParams.clear() - putAllAdditionalQueryParams(additionalQueryParams) - } - - fun putAdditionalQueryParam(key: String, value: String) = apply { - additionalQueryParams.put(key, value) - } - - fun putAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.put(key, values) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.putAll(additionalQueryParams) - } - - fun replaceAdditionalQueryParams(key: String, value: String) = apply { - additionalQueryParams.replace(key, value) - } - - fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { - additionalQueryParams.replace(key, values) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = - apply { - this.additionalQueryParams.replaceAll(additionalQueryParams) - } - - fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } - - fun removeAllAdditionalQueryParams(keys: Set) = apply { - additionalQueryParams.removeAll(keys) - } - - /** - * Returns an immutable instance of [CasGeneratorGenerateCasParams]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .email() - * .fromDate() - * .password() - * .toDate() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): CasGeneratorGenerateCasParams = - CasGeneratorGenerateCasParams( - body.build(), - additionalHeaders.build(), - additionalQueryParams.build(), - ) - } - - fun _body(): Body = body - - override fun _headers(): Headers = additionalHeaders - - override fun _queryParams(): QueryParams = additionalQueryParams - - class Body - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val email: JsonField, - private val fromDate: JsonField, - private val password: JsonField, - private val toDate: JsonField, - private val casAuthority: JsonField, - private val panNo: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("email") @ExcludeMissing email: JsonField = JsonMissing.of(), - @JsonProperty("from_date") - @ExcludeMissing - fromDate: JsonField = JsonMissing.of(), - @JsonProperty("password") - @ExcludeMissing - password: JsonField = JsonMissing.of(), - @JsonProperty("to_date") @ExcludeMissing toDate: JsonField = JsonMissing.of(), - @JsonProperty("cas_authority") - @ExcludeMissing - casAuthority: JsonField = JsonMissing.of(), - @JsonProperty("pan_no") @ExcludeMissing panNo: JsonField = JsonMissing.of(), - ) : this(email, fromDate, password, toDate, casAuthority, panNo, mutableMapOf()) - - /** - * Email address to receive the CAS document - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun email(): String = email.getRequired("email") - - /** - * Start date for the CAS period (format YYYY-MM-DD) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun fromDate(): String = fromDate.getRequired("from_date") - - /** - * Password to protect the generated CAS PDF - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun password(): String = password.getRequired("password") - - /** - * End date for the CAS period (format YYYY-MM-DD) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun toDate(): String = toDate.getRequired("to_date") - - /** - * CAS authority to generate the document from (currently only kfintech is supported) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun casAuthority(): Optional = casAuthority.getOptional("cas_authority") - - /** - * PAN number (optional for some CAS authorities) - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun panNo(): Optional = panNo.getOptional("pan_no") - - /** - * Returns the raw JSON value of [email]. - * - * Unlike [email], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("email") @ExcludeMissing fun _email(): JsonField = email - - /** - * Returns the raw JSON value of [fromDate]. - * - * Unlike [fromDate], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("from_date") @ExcludeMissing fun _fromDate(): JsonField = fromDate - - /** - * Returns the raw JSON value of [password]. - * - * Unlike [password], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("password") @ExcludeMissing fun _password(): JsonField = password - - /** - * Returns the raw JSON value of [toDate]. - * - * Unlike [toDate], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("to_date") @ExcludeMissing fun _toDate(): JsonField = toDate - - /** - * Returns the raw JSON value of [casAuthority]. - * - * Unlike [casAuthority], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("cas_authority") - @ExcludeMissing - fun _casAuthority(): JsonField = casAuthority - - /** - * Returns the raw JSON value of [panNo]. - * - * Unlike [panNo], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("pan_no") @ExcludeMissing fun _panNo(): JsonField = panNo - - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) - - fun toBuilder() = Builder().from(this) - - companion object { - - /** - * Returns a mutable builder for constructing an instance of [Body]. - * - * The following fields are required: - * ```java - * .email() - * .fromDate() - * .password() - * .toDate() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Body]. */ - class Builder internal constructor() { - - private var email: JsonField? = null - private var fromDate: JsonField? = null - private var password: JsonField? = null - private var toDate: JsonField? = null - private var casAuthority: JsonField = JsonMissing.of() - private var panNo: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(body: Body) = apply { - email = body.email - fromDate = body.fromDate - password = body.password - toDate = body.toDate - casAuthority = body.casAuthority - panNo = body.panNo - additionalProperties = body.additionalProperties.toMutableMap() - } - - /** Email address to receive the CAS document */ - fun email(email: String) = email(JsonField.of(email)) - - /** - * Sets [Builder.email] to an arbitrary JSON value. - * - * You should usually call [Builder.email] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun email(email: JsonField) = apply { this.email = email } - - /** Start date for the CAS period (format YYYY-MM-DD) */ - fun fromDate(fromDate: String) = fromDate(JsonField.of(fromDate)) - - /** - * Sets [Builder.fromDate] to an arbitrary JSON value. - * - * You should usually call [Builder.fromDate] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun fromDate(fromDate: JsonField) = apply { this.fromDate = fromDate } - - /** Password to protect the generated CAS PDF */ - fun password(password: String) = password(JsonField.of(password)) - - /** - * Sets [Builder.password] to an arbitrary JSON value. - * - * You should usually call [Builder.password] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun password(password: JsonField) = apply { this.password = password } - - /** End date for the CAS period (format YYYY-MM-DD) */ - fun toDate(toDate: String) = toDate(JsonField.of(toDate)) - - /** - * Sets [Builder.toDate] to an arbitrary JSON value. - * - * You should usually call [Builder.toDate] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun toDate(toDate: JsonField) = apply { this.toDate = toDate } - - /** - * CAS authority to generate the document from (currently only kfintech is supported) - */ - fun casAuthority(casAuthority: CasAuthority) = casAuthority(JsonField.of(casAuthority)) - - /** - * Sets [Builder.casAuthority] to an arbitrary JSON value. - * - * You should usually call [Builder.casAuthority] with a well-typed [CasAuthority] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun casAuthority(casAuthority: JsonField) = apply { - this.casAuthority = casAuthority - } - - /** PAN number (optional for some CAS authorities) */ - fun panNo(panNo: String) = panNo(JsonField.of(panNo)) - - /** - * Sets [Builder.panNo] to an arbitrary JSON value. - * - * You should usually call [Builder.panNo] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun panNo(panNo: JsonField) = apply { this.panNo = panNo } - - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } - - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } - - fun putAllAdditionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.putAll(additionalProperties) - } - - fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } - - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } - - /** - * Returns an immutable instance of [Body]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .email() - * .fromDate() - * .password() - * .toDate() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): Body = - Body( - checkRequired("email", email), - checkRequired("fromDate", fromDate), - checkRequired("password", password), - checkRequired("toDate", toDate), - casAuthority, - panNo, - additionalProperties.toMutableMap(), - ) - } - - private var validated: Boolean = false - - fun validate(): Body = apply { - if (validated) { - return@apply - } - - email() - fromDate() - password() - toDate() - casAuthority().ifPresent { it.validate() } - panNo() - validated = true - } - - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } - - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (email.asKnown().isPresent) 1 else 0) + - (if (fromDate.asKnown().isPresent) 1 else 0) + - (if (password.asKnown().isPresent) 1 else 0) + - (if (toDate.asKnown().isPresent) 1 else 0) + - (casAuthority.asKnown().getOrNull()?.validity() ?: 0) + - (if (panNo.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Body && - email == other.email && - fromDate == other.fromDate && - password == other.password && - toDate == other.toDate && - casAuthority == other.casAuthority && - panNo == other.panNo && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash( - email, - fromDate, - password, - toDate, - casAuthority, - panNo, - additionalProperties, - ) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "Body{email=$email, fromDate=$fromDate, password=$password, toDate=$toDate, casAuthority=$casAuthority, panNo=$panNo, additionalProperties=$additionalProperties}" - } - - /** CAS authority to generate the document from (currently only kfintech is supported) */ - class CasAuthority @JsonCreator private constructor(private val value: JsonField) : - Enum { - - /** - * Returns this class instance's raw value. - * - * This is usually only useful if this instance was deserialized from data that doesn't - * match any known member, and you want to know that value. For example, if the SDK is on an - * older version than the API, then the API may respond with new members that the SDK is - * unaware of. - */ - @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value - - companion object { - - @JvmField val KFINTECH = of("kfintech") - - @JvmField val CAMS = of("cams") - - @JvmField val CDSL = of("cdsl") - - @JvmField val NSDL = of("nsdl") - - @JvmStatic fun of(value: String) = CasAuthority(JsonField.of(value)) - } - - /** An enum containing [CasAuthority]'s known values. */ - enum class Known { - KFINTECH, - CAMS, - CDSL, - NSDL, - } - - /** - * An enum containing [CasAuthority]'s known values, as well as an [_UNKNOWN] member. - * - * An instance of [CasAuthority] can contain an unknown value in a couple of cases: - * - It was deserialized from data that doesn't match any known member. For example, if the - * SDK is on an older version than the API, then the API may respond with new members that - * the SDK is unaware of. - * - It was constructed with an arbitrary value using the [of] method. - */ - enum class Value { - KFINTECH, - CAMS, - CDSL, - NSDL, - /** - * An enum member indicating that [CasAuthority] was instantiated with an unknown value. - */ - _UNKNOWN, - } - - /** - * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] - * if the class was instantiated with an unknown value. - * - * Use the [known] method instead if you're certain the value is always known or if you want - * to throw for the unknown case. - */ - fun value(): Value = - when (this) { - KFINTECH -> Value.KFINTECH - CAMS -> Value.CAMS - CDSL -> Value.CDSL - NSDL -> Value.NSDL - else -> Value._UNKNOWN - } - - /** - * Returns an enum member corresponding to this class instance's value. - * - * Use the [value] method instead if you're uncertain the value is always known and don't - * want to throw for the unknown case. - * - * @throws CasParserInvalidDataException if this class instance's value is a not a known - * member. - */ - fun known(): Known = - when (this) { - KFINTECH -> Known.KFINTECH - CAMS -> Known.CAMS - CDSL -> Known.CDSL - NSDL -> Known.NSDL - else -> throw CasParserInvalidDataException("Unknown CasAuthority: $value") - } - - /** - * Returns this class instance's primitive wire representation. - * - * This differs from the [toString] method because that method is primarily for debugging - * and generally doesn't throw. - * - * @throws CasParserInvalidDataException if this class instance's value does not have the - * expected primitive type. - */ - fun asString(): String = - _value().asString().orElseThrow { - CasParserInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): CasAuthority = apply { - if (validated) { - return@apply - } - - known() - validated = true - } - - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } - - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is CasAuthority && value == other.value - } - - override fun hashCode() = value.hashCode() - - override fun toString() = value.toString() - } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is CasGeneratorGenerateCasParams && - body == other.body && - additionalHeaders == other.additionalHeaders && - additionalQueryParams == other.additionalQueryParams - } - - override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) - - override fun toString() = - "CasGeneratorGenerateCasParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" -} diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponse.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponse.kt deleted file mode 100644 index ad4901d..0000000 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponse.kt +++ /dev/null @@ -1,189 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.cas_parser.api.models.casgenerator - -import com.cas_parser.api.core.ExcludeMissing -import com.cas_parser.api.core.JsonField -import com.cas_parser.api.core.JsonMissing -import com.cas_parser.api.core.JsonValue -import com.cas_parser.api.errors.CasParserInvalidDataException -import com.fasterxml.jackson.annotation.JsonAnyGetter -import com.fasterxml.jackson.annotation.JsonAnySetter -import com.fasterxml.jackson.annotation.JsonCreator -import com.fasterxml.jackson.annotation.JsonProperty -import java.util.Collections -import java.util.Objects -import java.util.Optional - -class CasGeneratorGenerateCasResponse -@JsonCreator(mode = JsonCreator.Mode.DISABLED) -private constructor( - private val msg: JsonField, - private val status: JsonField, - private val additionalProperties: MutableMap, -) { - - @JsonCreator - private constructor( - @JsonProperty("msg") @ExcludeMissing msg: JsonField = JsonMissing.of(), - @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), - ) : this(msg, status, mutableMapOf()) - - /** - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun msg(): Optional = msg.getOptional("msg") - - /** - * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun status(): Optional = status.getOptional("status") - - /** - * Returns the raw JSON value of [msg]. - * - * Unlike [msg], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("msg") @ExcludeMissing fun _msg(): JsonField = msg - - /** - * Returns the raw JSON value of [status]. - * - * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status - - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) - - fun toBuilder() = Builder().from(this) - - companion object { - - /** - * Returns a mutable builder for constructing an instance of - * [CasGeneratorGenerateCasResponse]. - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [CasGeneratorGenerateCasResponse]. */ - class Builder internal constructor() { - - private var msg: JsonField = JsonMissing.of() - private var status: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(casGeneratorGenerateCasResponse: CasGeneratorGenerateCasResponse) = - apply { - msg = casGeneratorGenerateCasResponse.msg - status = casGeneratorGenerateCasResponse.status - additionalProperties = - casGeneratorGenerateCasResponse.additionalProperties.toMutableMap() - } - - fun msg(msg: String) = msg(JsonField.of(msg)) - - /** - * Sets [Builder.msg] to an arbitrary JSON value. - * - * You should usually call [Builder.msg] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun msg(msg: JsonField) = apply { this.msg = msg } - - fun status(status: String) = status(JsonField.of(status)) - - /** - * Sets [Builder.status] to an arbitrary JSON value. - * - * You should usually call [Builder.status] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun status(status: JsonField) = apply { this.status = status } - - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } - - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } - - fun putAllAdditionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.putAll(additionalProperties) - } - - fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } - - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } - - /** - * Returns an immutable instance of [CasGeneratorGenerateCasResponse]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): CasGeneratorGenerateCasResponse = - CasGeneratorGenerateCasResponse(msg, status, additionalProperties.toMutableMap()) - } - - private var validated: Boolean = false - - fun validate(): CasGeneratorGenerateCasResponse = apply { - if (validated) { - return@apply - } - - msg() - status() - validated = true - } - - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CasParserInvalidDataException) { - false - } - - /** - * Returns a score indicating how many valid values are contained in this object recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - (if (msg.asKnown().isPresent) 1 else 0) + (if (status.asKnown().isPresent) 1 else 0) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is CasGeneratorGenerateCasResponse && - msg == other.msg && - status == other.status && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(msg, status, additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "CasGeneratorGenerateCasResponse{msg=$msg, status=$status, additionalProperties=$additionalProperties}" -} diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsync.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsync.kt index 9eee1d4..0e6995d 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsync.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsync.kt @@ -3,11 +3,6 @@ package com.cas_parser.api.services.async import com.cas_parser.api.core.ClientOptions -import com.cas_parser.api.core.RequestOptions -import com.cas_parser.api.core.http.HttpResponseFor -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasParams -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasResponse -import java.util.concurrent.CompletableFuture import java.util.function.Consumer interface CasGeneratorServiceAsync { @@ -24,22 +19,6 @@ interface CasGeneratorServiceAsync { */ fun withOptions(modifier: Consumer): CasGeneratorServiceAsync - /** - * This endpoint generates CAS (Consolidated Account Statement) documents by submitting a - * mailback request to the specified CAS authority. Currently only supports KFintech, with plans - * to support CAMS, CDSL, and NSDL in the future. - */ - fun generateCas( - params: CasGeneratorGenerateCasParams - ): CompletableFuture = - generateCas(params, RequestOptions.none()) - - /** @see generateCas */ - fun generateCas( - params: CasGeneratorGenerateCasParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture - /** * A view of [CasGeneratorServiceAsync] that provides access to raw HTTP responses for each * method. @@ -54,20 +33,5 @@ interface CasGeneratorServiceAsync { fun withOptions( modifier: Consumer ): CasGeneratorServiceAsync.WithRawResponse - - /** - * Returns a raw HTTP response for `post /v4/generate`, but is otherwise the same as - * [CasGeneratorServiceAsync.generateCas]. - */ - fun generateCas( - params: CasGeneratorGenerateCasParams - ): CompletableFuture> = - generateCas(params, RequestOptions.none()) - - /** @see generateCas */ - fun generateCas( - params: CasGeneratorGenerateCasParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> } } diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsyncImpl.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsyncImpl.kt index b0b1ff9..0bbd145 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsyncImpl.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsyncImpl.kt @@ -3,21 +3,6 @@ package com.cas_parser.api.services.async import com.cas_parser.api.core.ClientOptions -import com.cas_parser.api.core.RequestOptions -import com.cas_parser.api.core.handlers.errorBodyHandler -import com.cas_parser.api.core.handlers.errorHandler -import com.cas_parser.api.core.handlers.jsonHandler -import com.cas_parser.api.core.http.HttpMethod -import com.cas_parser.api.core.http.HttpRequest -import com.cas_parser.api.core.http.HttpResponse -import com.cas_parser.api.core.http.HttpResponse.Handler -import com.cas_parser.api.core.http.HttpResponseFor -import com.cas_parser.api.core.http.json -import com.cas_parser.api.core.http.parseable -import com.cas_parser.api.core.prepareAsync -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasParams -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasResponse -import java.util.concurrent.CompletableFuture import java.util.function.Consumer class CasGeneratorServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : @@ -32,55 +17,14 @@ class CasGeneratorServiceAsyncImpl internal constructor(private val clientOption override fun withOptions(modifier: Consumer): CasGeneratorServiceAsync = CasGeneratorServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) - override fun generateCas( - params: CasGeneratorGenerateCasParams, - requestOptions: RequestOptions, - ): CompletableFuture = - // post /v4/generate - withRawResponse().generateCas(params, requestOptions).thenApply { it.parse() } - class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : CasGeneratorServiceAsync.WithRawResponse { - private val errorHandler: Handler = - errorHandler(errorBodyHandler(clientOptions.jsonMapper)) - override fun withOptions( modifier: Consumer ): CasGeneratorServiceAsync.WithRawResponse = CasGeneratorServiceAsyncImpl.WithRawResponseImpl( clientOptions.toBuilder().apply(modifier::accept).build() ) - - private val generateCasHandler: Handler = - jsonHandler(clientOptions.jsonMapper) - - override fun generateCas( - params: CasGeneratorGenerateCasParams, - requestOptions: RequestOptions, - ): CompletableFuture> { - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("v4", "generate") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepareAsync(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - return request - .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } - .thenApply { response -> - errorHandler.handle(response).parseable { - response - .use { generateCasHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.validate() - } - } - } - } - } } } diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/CasGeneratorService.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/CasGeneratorService.kt index b586008..f0ad062 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/CasGeneratorService.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/CasGeneratorService.kt @@ -3,11 +3,6 @@ package com.cas_parser.api.services.blocking import com.cas_parser.api.core.ClientOptions -import com.cas_parser.api.core.RequestOptions -import com.cas_parser.api.core.http.HttpResponseFor -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasParams -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasResponse -import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer interface CasGeneratorService { @@ -24,20 +19,6 @@ interface CasGeneratorService { */ fun withOptions(modifier: Consumer): CasGeneratorService - /** - * This endpoint generates CAS (Consolidated Account Statement) documents by submitting a - * mailback request to the specified CAS authority. Currently only supports KFintech, with plans - * to support CAMS, CDSL, and NSDL in the future. - */ - fun generateCas(params: CasGeneratorGenerateCasParams): CasGeneratorGenerateCasResponse = - generateCas(params, RequestOptions.none()) - - /** @see generateCas */ - fun generateCas( - params: CasGeneratorGenerateCasParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CasGeneratorGenerateCasResponse - /** * A view of [CasGeneratorService] that provides access to raw HTTP responses for each method. */ @@ -51,22 +32,5 @@ interface CasGeneratorService { fun withOptions( modifier: Consumer ): CasGeneratorService.WithRawResponse - - /** - * Returns a raw HTTP response for `post /v4/generate`, but is otherwise the same as - * [CasGeneratorService.generateCas]. - */ - @MustBeClosed - fun generateCas( - params: CasGeneratorGenerateCasParams - ): HttpResponseFor = - generateCas(params, RequestOptions.none()) - - /** @see generateCas */ - @MustBeClosed - fun generateCas( - params: CasGeneratorGenerateCasParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor } } diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/CasGeneratorServiceImpl.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/CasGeneratorServiceImpl.kt index 26bcfb5..1d0054b 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/CasGeneratorServiceImpl.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/CasGeneratorServiceImpl.kt @@ -3,20 +3,6 @@ package com.cas_parser.api.services.blocking import com.cas_parser.api.core.ClientOptions -import com.cas_parser.api.core.RequestOptions -import com.cas_parser.api.core.handlers.errorBodyHandler -import com.cas_parser.api.core.handlers.errorHandler -import com.cas_parser.api.core.handlers.jsonHandler -import com.cas_parser.api.core.http.HttpMethod -import com.cas_parser.api.core.http.HttpRequest -import com.cas_parser.api.core.http.HttpResponse -import com.cas_parser.api.core.http.HttpResponse.Handler -import com.cas_parser.api.core.http.HttpResponseFor -import com.cas_parser.api.core.http.json -import com.cas_parser.api.core.http.parseable -import com.cas_parser.api.core.prepare -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasParams -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasResponse import java.util.function.Consumer class CasGeneratorServiceImpl internal constructor(private val clientOptions: ClientOptions) : @@ -31,52 +17,14 @@ class CasGeneratorServiceImpl internal constructor(private val clientOptions: Cl override fun withOptions(modifier: Consumer): CasGeneratorService = CasGeneratorServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) - override fun generateCas( - params: CasGeneratorGenerateCasParams, - requestOptions: RequestOptions, - ): CasGeneratorGenerateCasResponse = - // post /v4/generate - withRawResponse().generateCas(params, requestOptions).parse() - class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : CasGeneratorService.WithRawResponse { - private val errorHandler: Handler = - errorHandler(errorBodyHandler(clientOptions.jsonMapper)) - override fun withOptions( modifier: Consumer ): CasGeneratorService.WithRawResponse = CasGeneratorServiceImpl.WithRawResponseImpl( clientOptions.toBuilder().apply(modifier::accept).build() ) - - private val generateCasHandler: Handler = - jsonHandler(clientOptions.jsonMapper) - - override fun generateCas( - params: CasGeneratorGenerateCasParams, - requestOptions: RequestOptions, - ): HttpResponseFor { - val request = - HttpRequest.builder() - .method(HttpMethod.POST) - .baseUrl(clientOptions.baseUrl()) - .addPathSegments("v4", "generate") - .body(json(clientOptions.jsonMapper, params._body())) - .build() - .prepare(clientOptions, params) - val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) - val response = clientOptions.httpClient.execute(request, requestOptions) - return errorHandler.handle(response).parseable { - response - .use { generateCasHandler.handle(it) } - .also { - if (requestOptions.responseValidation!!) { - it.validate() - } - } - } - } } } diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParamsTest.kt deleted file mode 100644 index 24f18c9..0000000 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasParamsTest.kt +++ /dev/null @@ -1,62 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.cas_parser.api.models.casgenerator - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class CasGeneratorGenerateCasParamsTest { - - @Test - fun create() { - CasGeneratorGenerateCasParams.builder() - .email("user@example.com") - .fromDate("2023-01-01") - .password("Abcdefghi12\$") - .toDate("2023-12-31") - .casAuthority(CasGeneratorGenerateCasParams.CasAuthority.KFINTECH) - .panNo("ABCDE1234F") - .build() - } - - @Test - fun body() { - val params = - CasGeneratorGenerateCasParams.builder() - .email("user@example.com") - .fromDate("2023-01-01") - .password("Abcdefghi12\$") - .toDate("2023-12-31") - .casAuthority(CasGeneratorGenerateCasParams.CasAuthority.KFINTECH) - .panNo("ABCDE1234F") - .build() - - val body = params._body() - - assertThat(body.email()).isEqualTo("user@example.com") - assertThat(body.fromDate()).isEqualTo("2023-01-01") - assertThat(body.password()).isEqualTo("Abcdefghi12\$") - assertThat(body.toDate()).isEqualTo("2023-12-31") - assertThat(body.casAuthority()) - .contains(CasGeneratorGenerateCasParams.CasAuthority.KFINTECH) - assertThat(body.panNo()).contains("ABCDE1234F") - } - - @Test - fun bodyWithoutOptionalFields() { - val params = - CasGeneratorGenerateCasParams.builder() - .email("user@example.com") - .fromDate("2023-01-01") - .password("Abcdefghi12\$") - .toDate("2023-12-31") - .build() - - val body = params._body() - - assertThat(body.email()).isEqualTo("user@example.com") - assertThat(body.fromDate()).isEqualTo("2023-01-01") - assertThat(body.password()).isEqualTo("Abcdefghi12\$") - assertThat(body.toDate()).isEqualTo("2023-12-31") - } -} diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponseTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponseTest.kt deleted file mode 100644 index c225afa..0000000 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casgenerator/CasGeneratorGenerateCasResponseTest.kt +++ /dev/null @@ -1,49 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.cas_parser.api.models.casgenerator - -import com.cas_parser.api.core.jsonMapper -import com.fasterxml.jackson.module.kotlin.jacksonTypeRef -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -internal class CasGeneratorGenerateCasResponseTest { - - @Test - fun create() { - val casGeneratorGenerateCasResponse = - CasGeneratorGenerateCasResponse.builder() - .msg( - "CAS generation request submitted successfully. The investor will receive the CAS file via email shortly." - ) - .status("success") - .build() - - assertThat(casGeneratorGenerateCasResponse.msg()) - .contains( - "CAS generation request submitted successfully. The investor will receive the CAS file via email shortly." - ) - assertThat(casGeneratorGenerateCasResponse.status()).contains("success") - } - - @Test - fun roundtrip() { - val jsonMapper = jsonMapper() - val casGeneratorGenerateCasResponse = - CasGeneratorGenerateCasResponse.builder() - .msg( - "CAS generation request submitted successfully. The investor will receive the CAS file via email shortly." - ) - .status("success") - .build() - - val roundtrippedCasGeneratorGenerateCasResponse = - jsonMapper.readValue( - jsonMapper.writeValueAsString(casGeneratorGenerateCasResponse), - jacksonTypeRef(), - ) - - assertThat(roundtrippedCasGeneratorGenerateCasResponse) - .isEqualTo(casGeneratorGenerateCasResponse) - } -} diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsyncTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsyncTest.kt deleted file mode 100644 index c74ed37..0000000 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/async/CasGeneratorServiceAsyncTest.kt +++ /dev/null @@ -1,40 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.cas_parser.api.services.async - -import com.cas_parser.api.TestServerExtension -import com.cas_parser.api.client.okhttp.CasParserOkHttpClientAsync -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasParams -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith - -@ExtendWith(TestServerExtension::class) -internal class CasGeneratorServiceAsyncTest { - - @Disabled("Prism tests are disabled") - @Test - fun generateCas() { - val client = - CasParserOkHttpClientAsync.builder() - .baseUrl(TestServerExtension.BASE_URL) - .apiKey("My API Key") - .build() - val casGeneratorServiceAsync = client.casGenerator() - - val responseFuture = - casGeneratorServiceAsync.generateCas( - CasGeneratorGenerateCasParams.builder() - .email("user@example.com") - .fromDate("2023-01-01") - .password("Abcdefghi12\$") - .toDate("2023-12-31") - .casAuthority(CasGeneratorGenerateCasParams.CasAuthority.KFINTECH) - .panNo("ABCDE1234F") - .build() - ) - - val response = responseFuture.get() - response.validate() - } -} diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/blocking/CasGeneratorServiceTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/blocking/CasGeneratorServiceTest.kt deleted file mode 100644 index e66dcfb..0000000 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/blocking/CasGeneratorServiceTest.kt +++ /dev/null @@ -1,39 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. - -package com.cas_parser.api.services.blocking - -import com.cas_parser.api.TestServerExtension -import com.cas_parser.api.client.okhttp.CasParserOkHttpClient -import com.cas_parser.api.models.casgenerator.CasGeneratorGenerateCasParams -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith - -@ExtendWith(TestServerExtension::class) -internal class CasGeneratorServiceTest { - - @Disabled("Prism tests are disabled") - @Test - fun generateCas() { - val client = - CasParserOkHttpClient.builder() - .baseUrl(TestServerExtension.BASE_URL) - .apiKey("My API Key") - .build() - val casGeneratorService = client.casGenerator() - - val response = - casGeneratorService.generateCas( - CasGeneratorGenerateCasParams.builder() - .email("user@example.com") - .fromDate("2023-01-01") - .password("Abcdefghi12\$") - .toDate("2023-12-31") - .casAuthority(CasGeneratorGenerateCasParams.CasAuthority.KFINTECH) - .panNo("ABCDE1234F") - .build() - ) - - response.validate() - } -} From 1c7a4f1eebb4b336dc85f73a0319b48d568bf06c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 02:17:26 +0000 Subject: [PATCH 8/9] feat(api): api update --- .github/workflows/ci.yml | 30 +++- .github/workflows/publish-sonatype.yml | 4 +- .github/workflows/release-doctor.yml | 2 +- .stats.yml | 4 +- README.md | 11 ++ .../main/kotlin/cas-parser.publish.gradle.kts | 8 + .../client/okhttp/CasParserOkHttpClient.kt | 22 +++ .../okhttp/CasParserOkHttpClientAsync.kt | 22 +++ .../api/client/okhttp/OkHttpClient.kt | 11 ++ cas-parser-java-core/build.gradle.kts | 18 ++- .../com/cas_parser/api/core/ObjectMappers.kt | 34 +++-- .../cas_parser/api/core/http/HttpRequest.kt | 30 ++++ .../api/core/http/RetryingHttpClient.kt | 20 +-- .../cas_parser/api/core/ObjectMappersTest.kt | 20 +-- .../api/core/http/HttpRequestTest.kt | 110 ++++++++++++++ .../build.gradle.kts | 2 +- scripts/upload-artifacts | 139 ++++++++++++++++++ 17 files changed, 429 insertions(+), 58 deletions(-) create mode 100644 cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/http/HttpRequestTest.kt create mode 100755 scripts/upload-artifacts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eedd0cf..30ff679 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,10 +20,10 @@ jobs: if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | @@ -40,14 +40,17 @@ jobs: build: timeout-minutes: 15 name: build + permissions: + contents: read + id-token: write runs-on: ${{ github.repository == 'stainless-sdks/cas-parser-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | @@ -61,16 +64,31 @@ jobs: - name: Build SDK run: ./scripts/build + - name: Get GitHub OIDC Token + if: github.repository == 'stainless-sdks/cas-parser-java' + id: github-oidc + uses: actions/github-script@v6 + with: + script: core.setOutput('github_token', await core.getIDToken()); + + - name: Build and upload Maven artifacts + if: github.repository == 'stainless-sdks/cas-parser-java' + env: + URL: https://pkg.stainless.com/s + AUTH: ${{ steps.github-oidc.outputs.github_token }} + SHA: ${{ github.sha }} + PROJECT: cas-parser-java + run: ./scripts/upload-artifacts test: timeout-minutes: 15 name: test runs-on: ${{ github.repository == 'stainless-sdks/cas-parser-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml index 1b11f45..2bfe3c5 100644 --- a/.github/workflows/publish-sonatype.yml +++ b/.github/workflows/publish-sonatype.yml @@ -14,10 +14,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 87d49ed..a636804 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'CASParser/cas-parser-java' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Check release environment run: | diff --git a/.stats.yml b/.stats.yml index 4465de7..968a0a4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 4 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-7e6397bddc220d1a59b5e2c7e7c3ff38f1a6eb174f4e383e03bc49cf78c8c44f.yml -openapi_spec_hash: cb852eeb4ce89c80f4246815cbe21f72 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-ce2296c4b14d27c141bb2745607d2456c923fdca3ae0a0a0800c26e564333850.yml +openapi_spec_hash: 8eb586ccf16b534c0c15ff6a22274c7d config_hash: cb5d75abef6264b5d86448caf7295afa diff --git a/README.md b/README.md index 878f4b9..3aed94e 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,15 @@ The Cas Parser Java SDK provides convenient access to the [Cas Parser REST API]( It is generated with [Stainless](https://www.stainless.com/). +## MCP Server + +Use the Cas Parser MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. + +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=cas-parser-node-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsImNhcy1wYXJzZXItbm9kZS1tY3AiXX0) +[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22cas-parser-node-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22cas-parser-node-mcp%22%5D%7D) + +> Note: You may need to set environment variables in your MCP client. + The REST API documentation can be found on [docs.casparser.in](https://docs.casparser.in/reference). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.4). @@ -274,6 +283,8 @@ If the SDK threw an exception, but you're _certain_ the version is compatible, t > [!CAUTION] > We make no guarantee that the SDK works correctly when the Jackson version check is disabled. +Also note that there are bugs in older Jackson versions that can affect the SDK. We don't work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead. + ## Network options ### Retries diff --git a/buildSrc/src/main/kotlin/cas-parser.publish.gradle.kts b/buildSrc/src/main/kotlin/cas-parser.publish.gradle.kts index ef287d8..26aec10 100644 --- a/buildSrc/src/main/kotlin/cas-parser.publish.gradle.kts +++ b/buildSrc/src/main/kotlin/cas-parser.publish.gradle.kts @@ -40,6 +40,14 @@ configure { } } } + repositories { + if (project.hasProperty("publishLocal")) { + maven { + name = "LocalFileSystem" + url = uri("${rootProject.layout.buildDirectory.get()}/local-maven-repo") + } + } + } } signing { diff --git a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClient.kt b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClient.kt index f75536a..93a7aeb 100644 --- a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClient.kt +++ b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClient.kt @@ -16,6 +16,7 @@ import java.net.Proxy import java.time.Clock import java.time.Duration import java.util.Optional +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager @@ -44,11 +45,31 @@ class CasParserOkHttpClient private constructor() { class Builder internal constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null + /** + * The executor service to use for running HTTP requests. + * + * Defaults to OkHttp's + * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104). + * + * This class takes ownership of the executor service and shuts it down when closed. + */ + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + + /** + * Alias for calling [Builder.dispatcherExecutorService] with + * `dispatcherExecutorService.orElse(null)`. + */ + fun dispatcherExecutorService(dispatcherExecutorService: Optional) = + dispatcherExecutorService(dispatcherExecutorService.getOrNull()) + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */ @@ -297,6 +318,7 @@ class CasParserOkHttpClient private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .dispatcherExecutorService(dispatcherExecutorService) .sslSocketFactory(sslSocketFactory) .trustManager(trustManager) .hostnameVerifier(hostnameVerifier) diff --git a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClientAsync.kt b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClientAsync.kt index 4142acc..f4858a0 100644 --- a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClientAsync.kt +++ b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/CasParserOkHttpClientAsync.kt @@ -16,6 +16,7 @@ import java.net.Proxy import java.time.Clock import java.time.Duration import java.util.Optional +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager @@ -44,11 +45,31 @@ class CasParserOkHttpClientAsync private constructor() { class Builder internal constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null + /** + * The executor service to use for running HTTP requests. + * + * Defaults to OkHttp's + * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104). + * + * This class takes ownership of the executor service and shuts it down when closed. + */ + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + + /** + * Alias for calling [Builder.dispatcherExecutorService] with + * `dispatcherExecutorService.orElse(null)`. + */ + fun dispatcherExecutorService(dispatcherExecutorService: Optional) = + dispatcherExecutorService(dispatcherExecutorService.getOrNull()) + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */ @@ -297,6 +318,7 @@ class CasParserOkHttpClientAsync private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .dispatcherExecutorService(dispatcherExecutorService) .sslSocketFactory(sslSocketFactory) .trustManager(trustManager) .hostnameVerifier(hostnameVerifier) diff --git a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/OkHttpClient.kt b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/OkHttpClient.kt index eee1317..7079d3c 100644 --- a/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/OkHttpClient.kt +++ b/cas-parser-java-client-okhttp/src/main/kotlin/com/cas_parser/api/client/okhttp/OkHttpClient.kt @@ -15,11 +15,13 @@ import java.net.Proxy import java.time.Duration import java.util.concurrent.CancellationException import java.util.concurrent.CompletableFuture +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager import okhttp3.Call import okhttp3.Callback +import okhttp3.Dispatcher import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaType @@ -198,6 +200,7 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien private var timeout: Timeout = Timeout.default() private var proxy: Proxy? = null + private var dispatcherExecutorService: ExecutorService? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null @@ -208,6 +211,10 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply { this.sslSocketFactory = sslSocketFactory } @@ -223,12 +230,16 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien fun build(): OkHttpClient = OkHttpClient( okhttp3.OkHttpClient.Builder() + // `RetryingHttpClient` handles retries if the user enabled them. + .retryOnConnectionFailure(false) .connectTimeout(timeout.connect()) .readTimeout(timeout.read()) .writeTimeout(timeout.write()) .callTimeout(timeout.request()) .proxy(proxy) .apply { + dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) } + val sslSocketFactory = sslSocketFactory val trustManager = trustManager if (sslSocketFactory != null && trustManager != null) { diff --git a/cas-parser-java-core/build.gradle.kts b/cas-parser-java-core/build.gradle.kts index 9861d5b..7d1eeed 100644 --- a/cas-parser-java-core/build.gradle.kts +++ b/cas-parser-java-core/build.gradle.kts @@ -5,14 +5,16 @@ plugins { configurations.all { resolutionStrategy { - // Compile and test against a lower Jackson version to ensure we're compatible with it. - // We publish with a higher version (see below) to ensure users depend on a secure version by default. - force("com.fasterxml.jackson.core:jackson-core:2.13.4") - force("com.fasterxml.jackson.core:jackson-databind:2.13.4") - force("com.fasterxml.jackson.core:jackson-annotations:2.13.4") - force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.4") - force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4") - force("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4") + // Compile and test against a lower Jackson version to ensure we're compatible with it. Note that + // we generally support 2.13.4, but test against 2.14.0 because 2.13.4 has some annoying (but + // niche) bugs (users should upgrade if they encounter them). We publish with a higher version + // (see below) to ensure users depend on a secure version by default. + force("com.fasterxml.jackson.core:jackson-core:2.14.0") + force("com.fasterxml.jackson.core:jackson-databind:2.14.0") + force("com.fasterxml.jackson.core:jackson-annotations:2.14.0") + force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.0") + force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.0") + force("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") } } diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ObjectMappers.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ObjectMappers.kt index 85d0b7e..9096f88 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ObjectMappers.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ObjectMappers.kt @@ -24,6 +24,7 @@ import java.io.InputStream import java.time.DateTimeException import java.time.LocalDate import java.time.LocalDateTime +import java.time.OffsetDateTime import java.time.ZonedDateTime import java.time.format.DateTimeFormatter import java.time.temporal.ChronoField @@ -36,7 +37,7 @@ fun jsonMapper(): JsonMapper = .addModule( SimpleModule() .addSerializer(InputStreamSerializer) - .addDeserializer(LocalDateTime::class.java, LenientLocalDateTimeDeserializer()) + .addDeserializer(OffsetDateTime::class.java, LenientOffsetDateTimeDeserializer()) ) .withCoercionConfig(LogicalType.Boolean) { it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) @@ -47,6 +48,7 @@ fun jsonMapper(): JsonMapper = } .withCoercionConfig(LogicalType.Integer) { it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) .setCoercion(CoercionInputShape.String, CoercionAction.Fail) .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) @@ -64,6 +66,12 @@ fun jsonMapper(): JsonMapper = .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) } + .withCoercionConfig(LogicalType.DateTime) { + it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } .withCoercionConfig(LogicalType.Array) { it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) @@ -124,10 +132,10 @@ private object InputStreamSerializer : BaseSerializer(InputStream:: } /** - * A deserializer that can deserialize [LocalDateTime] from datetimes, dates, and zoned datetimes. + * A deserializer that can deserialize [OffsetDateTime] from datetimes, dates, and zoned datetimes. */ -private class LenientLocalDateTimeDeserializer : - StdDeserializer(LocalDateTime::class.java) { +private class LenientOffsetDateTimeDeserializer : + StdDeserializer(OffsetDateTime::class.java) { companion object { @@ -141,7 +149,7 @@ private class LenientLocalDateTimeDeserializer : override fun logicalType(): LogicalType = LogicalType.DateTime - override fun deserialize(p: JsonParser, context: DeserializationContext?): LocalDateTime { + override fun deserialize(p: JsonParser, context: DeserializationContext): OffsetDateTime { val exceptions = mutableListOf() for (formatter in DATE_TIME_FORMATTERS) { @@ -149,18 +157,20 @@ private class LenientLocalDateTimeDeserializer : val temporal = formatter.parse(p.text) return when { - !temporal.isSupported(ChronoField.HOUR_OF_DAY) -> - LocalDate.from(temporal).atStartOfDay() - !temporal.isSupported(ChronoField.OFFSET_SECONDS) -> - LocalDateTime.from(temporal) - else -> ZonedDateTime.from(temporal).toLocalDateTime() - } + !temporal.isSupported(ChronoField.HOUR_OF_DAY) -> + LocalDate.from(temporal).atStartOfDay() + !temporal.isSupported(ChronoField.OFFSET_SECONDS) -> + LocalDateTime.from(temporal) + else -> ZonedDateTime.from(temporal).toLocalDateTime() + } + .atZone(context.timeZone.toZoneId()) + .toOffsetDateTime() } catch (e: DateTimeException) { exceptions.add(e) } } - throw JsonParseException(p, "Cannot parse `LocalDateTime` from value: ${p.text}").apply { + throw JsonParseException(p, "Cannot parse `OffsetDateTime` from value: ${p.text}").apply { exceptions.forEach { addSuppressed(it) } } } diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/HttpRequest.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/HttpRequest.kt index 7301769..9679caa 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/HttpRequest.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/HttpRequest.kt @@ -2,6 +2,7 @@ package com.cas_parser.api.core.http import com.cas_parser.api.core.checkRequired import com.cas_parser.api.core.toImmutable +import java.net.URLEncoder class HttpRequest private constructor( @@ -13,6 +14,35 @@ private constructor( @get:JvmName("body") val body: HttpRequestBody?, ) { + fun url(): String = buildString { + append(baseUrl) + + pathSegments.forEach { segment -> + if (!endsWith("/")) { + append("/") + } + append(URLEncoder.encode(segment, "UTF-8")) + } + + if (queryParams.isEmpty()) { + return@buildString + } + + append("?") + var isFirst = true + queryParams.keys().forEach { key -> + queryParams.values(key).forEach { value -> + if (!isFirst) { + append("&") + } + append(URLEncoder.encode(key, "UTF-8")) + append("=") + append(URLEncoder.encode(value, "UTF-8")) + isFirst = false + } + } + } + fun toBuilder(): Builder = Builder().from(this) override fun toString(): String = diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/RetryingHttpClient.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/RetryingHttpClient.kt index 2bf9815..3f34f6e 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/RetryingHttpClient.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/http/RetryingHttpClient.kt @@ -31,10 +31,6 @@ private constructor( ) : HttpClient { override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { - if (!isRetryable(request) || maxRetries <= 0) { - return httpClient.execute(request, requestOptions) - } - var modifiedRequest = maybeAddIdempotencyHeader(request) // Don't send the current retry count in the headers if the caller set their own value. @@ -48,6 +44,10 @@ private constructor( modifiedRequest = setRetryCountHeader(modifiedRequest, retries) } + if (!isRetryable(modifiedRequest)) { + return httpClient.execute(modifiedRequest, requestOptions) + } + val response = try { val response = httpClient.execute(modifiedRequest, requestOptions) @@ -75,10 +75,6 @@ private constructor( request: HttpRequest, requestOptions: RequestOptions, ): CompletableFuture { - if (!isRetryable(request) || maxRetries <= 0) { - return httpClient.executeAsync(request, requestOptions) - } - val modifiedRequest = maybeAddIdempotencyHeader(request) // Don't send the current retry count in the headers if the caller set their own value. @@ -94,8 +90,12 @@ private constructor( val requestWithRetryCount = if (shouldSendRetryCount) setRetryCountHeader(request, retries) else request - return httpClient - .executeAsync(requestWithRetryCount, requestOptions) + val responseFuture = httpClient.executeAsync(requestWithRetryCount, requestOptions) + if (!isRetryable(requestWithRetryCount)) { + return responseFuture + } + + return responseFuture .handleAsync( fun( response: HttpResponse?, diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/ObjectMappersTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/ObjectMappersTest.kt index c338d17..93a6a00 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/ObjectMappersTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/ObjectMappersTest.kt @@ -3,7 +3,7 @@ package com.cas_parser.api.core import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.exc.MismatchedInputException import com.fasterxml.jackson.module.kotlin.readValue -import java.time.LocalDateTime +import java.time.OffsetDateTime import kotlin.reflect.KClass import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.catchThrowable @@ -46,11 +46,7 @@ internal class ObjectMappersTest { val VALID_CONVERSIONS = listOf( FLOAT to DOUBLE, - FLOAT to INTEGER, - FLOAT to LONG, DOUBLE to FLOAT, - DOUBLE to INTEGER, - DOUBLE to LONG, INTEGER to FLOAT, INTEGER to DOUBLE, INTEGER to LONG, @@ -58,14 +54,6 @@ internal class ObjectMappersTest { LONG to DOUBLE, LONG to INTEGER, CLASS to MAP, - // These aren't actually valid, but coercion configs don't work for String until - // v2.14.0: https://github.com/FasterXML/jackson-databind/issues/3240 - // We currently test on v2.13.4. - BOOLEAN to STRING, - FLOAT to STRING, - DOUBLE to STRING, - INTEGER to STRING, - LONG to STRING, ) } } @@ -84,7 +72,7 @@ internal class ObjectMappersTest { } } - enum class LenientLocalDateTimeTestCase(val string: String) { + enum class LenientOffsetDateTimeTestCase(val string: String) { DATE("1998-04-21"), DATE_TIME("1998-04-21T04:00:00"), ZONED_DATE_TIME_1("1998-04-21T04:00:00+03:00"), @@ -93,10 +81,10 @@ internal class ObjectMappersTest { @ParameterizedTest @EnumSource - fun readLocalDateTime_lenient(testCase: LenientLocalDateTimeTestCase) { + fun readOffsetDateTime_lenient(testCase: LenientOffsetDateTimeTestCase) { val jsonMapper = jsonMapper() val json = jsonMapper.writeValueAsString(testCase.string) - assertDoesNotThrow { jsonMapper().readValue(json) } + assertDoesNotThrow { jsonMapper().readValue(json) } } } diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/http/HttpRequestTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/http/HttpRequestTest.kt new file mode 100644 index 0000000..06e315d --- /dev/null +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/core/http/HttpRequestTest.kt @@ -0,0 +1,110 @@ +package com.cas_parser.api.core.http + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class HttpRequestTest { + + enum class UrlTestCase(val request: HttpRequest, val expectedUrl: String) { + BASE_URL_ONLY( + HttpRequest.builder().method(HttpMethod.GET).baseUrl("https://api.example.com").build(), + expectedUrl = "https://api.example.com", + ), + BASE_URL_WITH_TRAILING_SLASH( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com/") + .build(), + expectedUrl = "https://api.example.com/", + ), + SINGLE_PATH_SEGMENT( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .build(), + expectedUrl = "https://api.example.com/users", + ), + MULTIPLE_PATH_SEGMENTS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegments("users", "123", "profile") + .build(), + expectedUrl = "https://api.example.com/users/123/profile", + ), + PATH_SEGMENT_WITH_SPECIAL_CHARS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("user name") + .build(), + expectedUrl = "https://api.example.com/user+name", + ), + SINGLE_QUERY_PARAM( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParam("limit", "10") + .build(), + expectedUrl = "https://api.example.com/users?limit=10", + ), + MULTIPLE_QUERY_PARAMS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParam("limit", "10") + .putQueryParam("offset", "20") + .build(), + expectedUrl = "https://api.example.com/users?limit=10&offset=20", + ), + QUERY_PARAM_WITH_SPECIAL_CHARS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("search") + .putQueryParam("q", "hello world") + .build(), + expectedUrl = "https://api.example.com/search?q=hello+world", + ), + MULTIPLE_VALUES_SAME_PARAM( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParams("tags", listOf("admin", "user")) + .build(), + expectedUrl = "https://api.example.com/users?tags=admin&tags=user", + ), + BASE_URL_WITH_TRAILING_SLASH_AND_PATH( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com/") + .addPathSegment("users") + .build(), + expectedUrl = "https://api.example.com/users", + ), + COMPLEX_URL( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl("https://api.example.com") + .addPathSegments("v1", "users", "123") + .putQueryParams("include", listOf("profile", "settings")) + .putQueryParam("format", "json") + .build(), + expectedUrl = + "https://api.example.com/v1/users/123?include=profile&include=settings&format=json", + ), + } + + @ParameterizedTest + @EnumSource + fun url(testCase: UrlTestCase) { + val actualUrl = testCase.request.url() + + assertThat(actualUrl).isEqualTo(testCase.expectedUrl) + } +} diff --git a/cas-parser-java-proguard-test/build.gradle.kts b/cas-parser-java-proguard-test/build.gradle.kts index de62f9c..bc6de2d 100644 --- a/cas-parser-java-proguard-test/build.gradle.kts +++ b/cas-parser-java-proguard-test/build.gradle.kts @@ -19,7 +19,7 @@ dependencies { testImplementation(kotlin("test")) testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") testImplementation("org.assertj:assertj-core:3.25.3") - testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4") + testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") } tasks.shadowJar { diff --git a/scripts/upload-artifacts b/scripts/upload-artifacts new file mode 100755 index 0000000..548d152 --- /dev/null +++ b/scripts/upload-artifacts @@ -0,0 +1,139 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# ANSI Color Codes +GREEN='\033[32m' +RED='\033[31m' +NC='\033[0m' # No Color + +MAVEN_REPO_PATH="./build/local-maven-repo" + +log_error() { + local msg="$1" + local headers="$2" + local body="$3" + echo -e "${RED}${msg}${NC}" + [[ -f "$headers" ]] && echo -e "${RED}Headers:$(cat "$headers")${NC}" + echo -e "${RED}Body: ${body}${NC}" + exit 1 +} + +upload_file() { + local file_name="$1" + local tmp_headers + tmp_headers=$(mktemp) + + if [ -f "$file_name" ]; then + echo -e "${GREEN}Processing file: $file_name${NC}" + pkg_file_name="mvn${file_name#"${MAVEN_REPO_PATH}"}" + + # Get signed URL for uploading artifact file + signed_url_response=$(curl -X POST -G "$URL" \ + -sS --retry 5 \ + -D "$tmp_headers" \ + --data-urlencode "filename=$pkg_file_name" \ + -H "Authorization: Bearer $AUTH" \ + -H "Content-Type: application/json") + + # Validate JSON and extract URL + if ! signed_url=$(echo "$signed_url_response" | jq -e -r '.url' 2>/dev/null) || [[ "$signed_url" == "null" ]]; then + log_error "Failed to get valid signed URL" "$tmp_headers" "$signed_url_response" + fi + + # Set content-type based on file extension + local extension="${file_name##*.}" + local content_type + case "$extension" in + jar) content_type="application/java-archive" ;; + md5|sha1|sha256|sha512) content_type="text/plain" ;; + module) content_type="application/json" ;; + pom|xml) content_type="application/xml" ;; + html) content_type="text/html" ;; + *) content_type="application/octet-stream" ;; + esac + + # Upload file + upload_response=$(curl -v -X PUT \ + --retry 5 \ + --retry-all-errors \ + -D "$tmp_headers" \ + -H "Content-Type: $content_type" \ + --data-binary "@${file_name}" "$signed_url" 2>&1) + + if ! echo "$upload_response" | grep -q "HTTP/[0-9.]* 200"; then + log_error "Failed to upload artifact file" "$tmp_headers" "$upload_response" + fi + + # Insert small throttle to reduce rate limiting risk + sleep 0.1 + fi +} + +walk_tree() { + local current_dir="$1" + + for entry in "$current_dir"/*; do + # Check that entry is valid + [ -e "$entry" ] || [ -h "$entry" ] || continue + + if [ -d "$entry" ]; then + walk_tree "$entry" + else + upload_file "$entry" + fi + done +} + +generate_instructions() { + cat << EOF > "$MAVEN_REPO_PATH/index.html" + + + + Maven Repo + + +

Stainless SDK Maven Repository

+

This is the Maven repository for your Stainless Java SDK build.

+ +

Directions

+

To use the uploaded Maven repository, add the following to your project's pom.xml:

+
<repositories>
+    <repository>
+        <id>stainless-sdk-repo</id>
+        <url>https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn</url>
+    </repository>
+</repositories>
+ +

If you're using Gradle, add the following to your build.gradle file:

+
repositories {
+    maven {
+        url 'https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn'
+    }
+}
+ +

Once you've added the repository, you can include dependencies from it as usual. See your + project README + for more details.

+ + +EOF + upload_file "${MAVEN_REPO_PATH}/index.html" + + echo "Configure maven or gradle to use the repo located at 'https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn'" + echo "For more details, see the directions in https://pkg.stainless.com/s/${PROJECT}/${SHA}/mvn/index.html" +} + +cd "$(dirname "$0")/.." + +echo "::group::Creating local Maven content" +./gradlew publishMavenPublicationToLocalFileSystemRepository -PpublishLocal +echo "::endgroup::" + +echo "::group::Uploading to pkg.stainless.com" +walk_tree "$MAVEN_REPO_PATH" +echo "::endgroup::" + +echo "::group::Generating instructions" +generate_instructions +echo "::endgroup::" From 0d9a0227c03fc57ad4c81821e450ff06d7833112 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 20 Jan 2026 02:17:43 +0000 Subject: [PATCH 9/9] release: 0.1.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 24 ++++++++++++++++++++++++ README.md | 10 +++++----- build.gradle.kts | 2 +- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2ed3b71..3d2ac0b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.4" + ".": "0.1.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index f21b326..2b43336 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## 0.1.0 (2026-01-20) + +Full Changelog: [v0.0.4...v0.1.0](https://github.com/CASParser/cas-parser-java/compare/v0.0.4...v0.1.0) + +### Features + +* **api:** api update ([1c7a4f1](https://github.com/CASParser/cas-parser-java/commit/1c7a4f1eebb4b336dc85f73a0319b48d568bf06c)) +* **api:** api update ([2e6c34f](https://github.com/CASParser/cas-parser-java/commit/2e6c34fbe30670c8ae1a74eb7f0f8fc5e8bb1890)) +* **api:** api update ([91a54b7](https://github.com/CASParser/cas-parser-java/commit/91a54b7acbf164ad459293fe697a4b0c9a795758)) +* **api:** api update ([557721f](https://github.com/CASParser/cas-parser-java/commit/557721f0775228db057005e912d8f820f512fcca)) +* **client:** expose sleeper option ([482319f](https://github.com/CASParser/cas-parser-java/commit/482319f0e19023df4e3ba5414e38914f6ad037fa)) + + +### Bug Fixes + +* **client:** deserialization of empty objects ([ce29632](https://github.com/CASParser/cas-parser-java/commit/ce29632f7f03c172ad042bbaa68e431ab2fd7fa7)) +* **client:** ensure single timer is created per client ([482319f](https://github.com/CASParser/cas-parser-java/commit/482319f0e19023df4e3ba5414e38914f6ad037fa)) +* **client:** incorrect `getPackageVersion` impl ([6772c5e](https://github.com/CASParser/cas-parser-java/commit/6772c5eeb5557a1e494852713cc55ec722b75145)) + + +### Chores + +* improve formatter performance ([692db64](https://github.com/CASParser/cas-parser-java/commit/692db64a36ef927e9c0ea23bd57192af99aaaf02)) + ## 0.0.4 (2025-09-13) Full Changelog: [v0.0.3...v0.0.4](https://github.com/CASParser/cas-parser-java/compare/v0.0.3...v0.0.4) diff --git a/README.md b/README.md index 3aed94e..bea2ccb 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.cas_parser.api/cas-parser-java)](https://central.sonatype.com/artifact/com.cas_parser.api/cas-parser-java/0.0.4) -[![javadoc](https://javadoc.io/badge2/com.cas_parser.api/cas-parser-java/0.0.4/javadoc.svg)](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.4) +[![Maven Central](https://img.shields.io/maven-central/v/com.cas_parser.api/cas-parser-java)](https://central.sonatype.com/artifact/com.cas_parser.api/cas-parser-java/0.1.0) +[![javadoc](https://javadoc.io/badge2/com.cas_parser.api/cas-parser-java/0.1.0/javadoc.svg)](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.1.0) @@ -22,7 +22,7 @@ Use the Cas Parser MCP Server to enable AI assistants to interact with this API, -The REST API documentation can be found on [docs.casparser.in](https://docs.casparser.in/reference). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.4). +The REST API documentation can be found on [docs.casparser.in](https://docs.casparser.in/reference). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.1.0). @@ -33,7 +33,7 @@ The REST API documentation can be found on [docs.casparser.in](https://docs.casp ### Gradle ```kotlin -implementation("com.cas_parser.api:cas-parser-java:0.0.4") +implementation("com.cas_parser.api:cas-parser-java:0.1.0") ``` ### Maven @@ -42,7 +42,7 @@ implementation("com.cas_parser.api:cas-parser-java:0.0.4") com.cas_parser.api cas-parser-java - 0.0.4 + 0.1.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index d58d78e..30b3cae 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ repositories { allprojects { group = "com.cas_parser.api" - version = "0.0.4" // x-release-please-version + version = "0.1.0" // x-release-please-version } subprojects {