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/7] 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/7] 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/7] 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/7] 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/7] 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/7] 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 edace6969619dd1c1f684086c1522e765f7fe821 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:55 +0000 Subject: [PATCH 7/7] release: 0.1.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 22 ++++++++++++++++++++++ README.md | 10 +++++----- build.gradle.kts | 2 +- 4 files changed, 29 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..e027a9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 0.1.0 (2026-01-01) + +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 ([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 15ce0f4..93ea651 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) @@ -13,7 +13,7 @@ It is generated with [Stainless](https://www.stainless.com/). -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). @@ -24,7 +24,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 @@ -33,7 +33,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 {