From e333879612c488e74effb36cca27da4fe9ed134f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 18:41:05 +0000 Subject: [PATCH 01/10] feat(api): add EARLY_DIRECT_DEPOSIT_FLOAT type to financial account --- .stats.yml | 8 +- .../com/lithic/api/client/LithicClient.kt | 5 + .../lithic/api/client/LithicClientAsync.kt | 5 + .../api/client/LithicClientAsyncImpl.kt | 12 + .../com/lithic/api/client/LithicClientImpl.kt | 12 + .../api/models/AccountActivityListPage.kt | 6 + .../models/AccountActivityListPageAsync.kt | 6 + .../models/AccountActivityListPageResponse.kt | 3 + .../api/models/AccountActivityListParams.kt | 6 + .../api/models/AccountActivityListResponse.kt | 60 +- ...ountActivityRetrieveTransactionResponse.kt | 60 +- .../com/lithic/api/models/FinancialAccount.kt | 6 + .../api/models/FinancialAccountListParams.kt | 6 + .../main/kotlin/com/lithic/api/models/Hold.kt | 1066 +++++++++++++++++ .../com/lithic/api/models/HoldCreateParams.kt | 742 ++++++++++++ .../kotlin/com/lithic/api/models/HoldEvent.kt | 892 ++++++++++++++ .../com/lithic/api/models/HoldListPage.kt | 131 ++ .../lithic/api/models/HoldListPageAsync.kt | 145 +++ .../lithic/api/models/HoldListPageResponse.kt | 223 ++++ .../com/lithic/api/models/HoldListParams.kt | 483 ++++++++ .../lithic/api/models/HoldRetrieveParams.kt | 189 +++ .../com/lithic/api/models/HoldVoidParams.kt | 419 +++++++ .../models/InstanceFinancialAccountType.kt | 6 + .../kotlin/com/lithic/api/models/Payment.kt | 6 + .../lithic/api/models/StatementLineItems.kt | 6 + .../api/services/async/HoldServiceAsync.kt | 330 +++++ .../services/async/HoldServiceAsyncImpl.kt | 222 ++++ .../api/services/blocking/HoldService.kt | 321 +++++ .../api/services/blocking/HoldServiceImpl.kt | 195 +++ .../models/AccountActivityListResponseTest.kt | 87 ++ ...ActivityRetrieveTransactionResponseTest.kt | 89 ++ .../lithic/api/models/HoldCreateParamsTest.kt | 70 ++ .../com/lithic/api/models/HoldEventTest.kt | 61 + .../api/models/HoldListPageResponseTest.kt | 121 ++ .../lithic/api/models/HoldListParamsTest.kt | 76 ++ .../api/models/HoldRetrieveParamsTest.kt | 24 + .../kotlin/com/lithic/api/models/HoldTest.kt | 105 ++ .../lithic/api/models/HoldVoidParamsTest.kt | 48 + .../services/async/HoldServiceAsyncTest.kt | 91 ++ .../api/services/blocking/HoldServiceTest.kt | 87 ++ .../api/proguard/ProGuardCompatibilityTest.kt | 1 + 41 files changed, 6419 insertions(+), 12 deletions(-) create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/Hold.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldCreateParams.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldEvent.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPage.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPageAsync.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPageResponse.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListParams.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldRetrieveParams.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldVoidParams.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/async/HoldServiceAsync.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/async/HoldServiceAsyncImpl.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/HoldService.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/HoldServiceImpl.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldCreateParamsTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldEventTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldListPageResponseTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldListParamsTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldRetrieveParamsTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldVoidParamsTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/services/async/HoldServiceAsyncTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/HoldServiceTest.kt diff --git a/.stats.yml b/.stats.yml index 4f6a4f90..b95d916a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 185 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-ee8607f0a2cdcaee420935050334a439db8dd097be83023fccdaf1d6f9a7de14.yml -openapi_spec_hash: 0f21c68cdddb7c5bd99f42356d507393 -config_hash: fb5070d41fcabdedbc084b83964b592a +configured_endpoints: 189 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-ee2b9f00d3a9e0000e25abc0774615d6ad3300ce17b2f094e71b0229a907760f.yml +openapi_spec_hash: 01d2cbf4ac692dba2f3831462db929e4 +config_hash: a45e6da4e7b46db4ff6819d1dba5d815 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClient.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClient.kt index 5c62db05..6dd840a3 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClient.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClient.kt @@ -28,6 +28,7 @@ import com.lithic.api.services.blocking.ExternalPaymentService import com.lithic.api.services.blocking.FinancialAccountService import com.lithic.api.services.blocking.FraudService import com.lithic.api.services.blocking.FundingEventService +import com.lithic.api.services.blocking.HoldService import com.lithic.api.services.blocking.InternalTransactionService import com.lithic.api.services.blocking.ManagementOperationService import com.lithic.api.services.blocking.NetworkProgramService @@ -139,6 +140,8 @@ interface LithicClient { fun networkPrograms(): NetworkProgramService + fun holds(): HoldService + fun accountActivity(): AccountActivityService fun transferLimits(): TransferLimitService @@ -245,6 +248,8 @@ interface LithicClient { fun networkPrograms(): NetworkProgramService.WithRawResponse + fun holds(): HoldService.WithRawResponse + fun accountActivity(): AccountActivityService.WithRawResponse fun transferLimits(): TransferLimitService.WithRawResponse diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientAsync.kt index 720abfe6..d5ee8d11 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientAsync.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientAsync.kt @@ -27,6 +27,7 @@ import com.lithic.api.services.async.ExternalPaymentServiceAsync import com.lithic.api.services.async.FinancialAccountServiceAsync import com.lithic.api.services.async.FraudServiceAsync import com.lithic.api.services.async.FundingEventServiceAsync +import com.lithic.api.services.async.HoldServiceAsync import com.lithic.api.services.async.InternalTransactionServiceAsync import com.lithic.api.services.async.ManagementOperationServiceAsync import com.lithic.api.services.async.NetworkProgramServiceAsync @@ -139,6 +140,8 @@ interface LithicClientAsync { fun networkPrograms(): NetworkProgramServiceAsync + fun holds(): HoldServiceAsync + fun accountActivity(): AccountActivityServiceAsync fun transferLimits(): TransferLimitServiceAsync @@ -248,6 +251,8 @@ interface LithicClientAsync { fun networkPrograms(): NetworkProgramServiceAsync.WithRawResponse + fun holds(): HoldServiceAsync.WithRawResponse + fun accountActivity(): AccountActivityServiceAsync.WithRawResponse fun transferLimits(): TransferLimitServiceAsync.WithRawResponse diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientAsyncImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientAsyncImpl.kt index 10e87732..97d63df6 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientAsyncImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientAsyncImpl.kt @@ -57,6 +57,8 @@ import com.lithic.api.services.async.FraudServiceAsync import com.lithic.api.services.async.FraudServiceAsyncImpl import com.lithic.api.services.async.FundingEventServiceAsync import com.lithic.api.services.async.FundingEventServiceAsyncImpl +import com.lithic.api.services.async.HoldServiceAsync +import com.lithic.api.services.async.HoldServiceAsyncImpl import com.lithic.api.services.async.InternalTransactionServiceAsync import com.lithic.api.services.async.InternalTransactionServiceAsyncImpl import com.lithic.api.services.async.ManagementOperationServiceAsync @@ -221,6 +223,8 @@ class LithicClientAsyncImpl(private val clientOptions: ClientOptions) : LithicCl NetworkProgramServiceAsyncImpl(clientOptionsWithUserAgent) } + private val holds: HoldServiceAsync by lazy { HoldServiceAsyncImpl(clientOptionsWithUserAgent) } + private val accountActivity: AccountActivityServiceAsync by lazy { AccountActivityServiceAsyncImpl(clientOptionsWithUserAgent) } @@ -301,6 +305,8 @@ class LithicClientAsyncImpl(private val clientOptions: ClientOptions) : LithicCl override fun networkPrograms(): NetworkProgramServiceAsync = networkPrograms + override fun holds(): HoldServiceAsync = holds + override fun accountActivity(): AccountActivityServiceAsync = accountActivity override fun transferLimits(): TransferLimitServiceAsync = transferLimits @@ -443,6 +449,10 @@ class LithicClientAsyncImpl(private val clientOptions: ClientOptions) : LithicCl NetworkProgramServiceAsyncImpl.WithRawResponseImpl(clientOptions) } + private val holds: HoldServiceAsync.WithRawResponse by lazy { + HoldServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + private val accountActivity: AccountActivityServiceAsync.WithRawResponse by lazy { AccountActivityServiceAsyncImpl.WithRawResponseImpl(clientOptions) } @@ -530,6 +540,8 @@ class LithicClientAsyncImpl(private val clientOptions: ClientOptions) : LithicCl override fun networkPrograms(): NetworkProgramServiceAsync.WithRawResponse = networkPrograms + override fun holds(): HoldServiceAsync.WithRawResponse = holds + override fun accountActivity(): AccountActivityServiceAsync.WithRawResponse = accountActivity diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientImpl.kt index 411eeb78..f9808009 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientImpl.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/client/LithicClientImpl.kt @@ -57,6 +57,8 @@ import com.lithic.api.services.blocking.FraudService import com.lithic.api.services.blocking.FraudServiceImpl import com.lithic.api.services.blocking.FundingEventService import com.lithic.api.services.blocking.FundingEventServiceImpl +import com.lithic.api.services.blocking.HoldService +import com.lithic.api.services.blocking.HoldServiceImpl import com.lithic.api.services.blocking.InternalTransactionService import com.lithic.api.services.blocking.InternalTransactionServiceImpl import com.lithic.api.services.blocking.ManagementOperationService @@ -204,6 +206,8 @@ class LithicClientImpl(private val clientOptions: ClientOptions) : LithicClient NetworkProgramServiceImpl(clientOptionsWithUserAgent) } + private val holds: HoldService by lazy { HoldServiceImpl(clientOptionsWithUserAgent) } + private val accountActivity: AccountActivityService by lazy { AccountActivityServiceImpl(clientOptionsWithUserAgent) } @@ -281,6 +285,8 @@ class LithicClientImpl(private val clientOptions: ClientOptions) : LithicClient override fun networkPrograms(): NetworkProgramService = networkPrograms + override fun holds(): HoldService = holds + override fun accountActivity(): AccountActivityService = accountActivity override fun transferLimits(): TransferLimitService = transferLimits @@ -423,6 +429,10 @@ class LithicClientImpl(private val clientOptions: ClientOptions) : LithicClient NetworkProgramServiceImpl.WithRawResponseImpl(clientOptions) } + private val holds: HoldService.WithRawResponse by lazy { + HoldServiceImpl.WithRawResponseImpl(clientOptions) + } + private val accountActivity: AccountActivityService.WithRawResponse by lazy { AccountActivityServiceImpl.WithRawResponseImpl(clientOptions) } @@ -509,6 +519,8 @@ class LithicClientImpl(private val clientOptions: ClientOptions) : LithicClient override fun networkPrograms(): NetworkProgramService.WithRawResponse = networkPrograms + override fun holds(): HoldService.WithRawResponse = holds + override fun accountActivity(): AccountActivityService.WithRawResponse = accountActivity override fun transferLimits(): TransferLimitService.WithRawResponse = transferLimits diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPage.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPage.kt index 68f30828..798daf0c 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPage.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPage.kt @@ -69,6 +69,9 @@ private constructor( managementOperation: ManagementOperationTransaction ): Optional = managementOperation._token().getOptional("token") + + override fun visitHold(hold: Hold): Optional = + hold._token().getOptional("token") } ) ) @@ -104,6 +107,9 @@ private constructor( managementOperation: ManagementOperationTransaction ): Optional = managementOperation._token().getOptional("token") + + override fun visitHold(hold: Hold): Optional = + hold._token().getOptional("token") } ) ) diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPageAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPageAsync.kt index cc509dfd..1f14a7e6 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPageAsync.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPageAsync.kt @@ -72,6 +72,9 @@ private constructor( managementOperation: ManagementOperationTransaction ): Optional = managementOperation._token().getOptional("token") + + override fun visitHold(hold: Hold): Optional = + hold._token().getOptional("token") } ) ) @@ -107,6 +110,9 @@ private constructor( managementOperation: ManagementOperationTransaction ): Optional = managementOperation._token().getOptional("token") + + override fun visitHold(hold: Hold): Optional = + hold._token().getOptional("token") } ) ) diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPageResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPageResponse.kt index 29731923..ccf10fd8 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPageResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListPageResponse.kt @@ -156,6 +156,9 @@ private constructor( fun addData(managementOperation: ManagementOperationTransaction) = addData(AccountActivityListResponse.ofManagementOperation(managementOperation)) + /** Alias for calling [addData] with `AccountActivityListResponse.ofHold(hold)`. */ + fun addData(hold: Hold) = addData(AccountActivityListResponse.ofHold(hold)) + /** Indicates if there are more transactions available for pagination */ fun hasMore(hasMore: Boolean) = hasMore(JsonField.of(hasMore)) diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListParams.kt index eb2aa72b..efe50186 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListParams.kt @@ -424,6 +424,8 @@ private constructor( @JvmField val MANAGEMENT_DISBURSEMENT = of("MANAGEMENT_DISBURSEMENT") + @JvmField val HOLD = of("HOLD") + @JvmField val PROGRAM_FUNDING = of("PROGRAM_FUNDING") @JvmStatic fun of(value: String) = TransactionCategory(JsonField.of(value)) @@ -450,6 +452,7 @@ private constructor( MANAGEMENT_FEE, MANAGEMENT_REWARD, MANAGEMENT_DISBURSEMENT, + HOLD, PROGRAM_FUNDING, } @@ -482,6 +485,7 @@ private constructor( MANAGEMENT_FEE, MANAGEMENT_REWARD, MANAGEMENT_DISBURSEMENT, + HOLD, PROGRAM_FUNDING, /** * An enum member indicating that [TransactionCategory] was instantiated with an unknown @@ -518,6 +522,7 @@ private constructor( MANAGEMENT_FEE -> Value.MANAGEMENT_FEE MANAGEMENT_REWARD -> Value.MANAGEMENT_REWARD MANAGEMENT_DISBURSEMENT -> Value.MANAGEMENT_DISBURSEMENT + HOLD -> Value.HOLD PROGRAM_FUNDING -> Value.PROGRAM_FUNDING else -> Value._UNKNOWN } @@ -552,6 +557,7 @@ private constructor( MANAGEMENT_FEE -> Known.MANAGEMENT_FEE MANAGEMENT_REWARD -> Known.MANAGEMENT_REWARD MANAGEMENT_DISBURSEMENT -> Known.MANAGEMENT_DISBURSEMENT + HOLD -> Known.HOLD PROGRAM_FUNDING -> Known.PROGRAM_FUNDING else -> throw LithicInvalidDataException("Unknown TransactionCategory: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListResponse.kt index 93a1516f..c69e9261 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityListResponse.kt @@ -35,8 +35,8 @@ import kotlin.jvm.optionals.getOrNull * Response containing multiple transaction types. The `family` field determines which transaction * type is returned: INTERNAL returns FinancialTransaction, TRANSFER returns * BookTransferTransaction, CARD returns CardTransaction, PAYMENT returns PaymentTransaction, - * EXTERNAL_PAYMENT returns ExternalPaymentResponse, and MANAGEMENT_OPERATION returns - * ManagementOperationTransaction + * EXTERNAL_PAYMENT returns ExternalPaymentResponse, MANAGEMENT_OPERATION returns + * ManagementOperationTransaction, and HOLD returns HoldTransaction */ @JsonDeserialize(using = AccountActivityListResponse.Deserializer::class) @JsonSerialize(using = AccountActivityListResponse.Serializer::class) @@ -48,6 +48,7 @@ private constructor( private val payment: Payment? = null, private val externalPayment: ExternalPayment? = null, private val managementOperation: ManagementOperationTransaction? = null, + private val hold: Hold? = null, private val _json: JsonValue? = null, ) { @@ -68,6 +69,13 @@ private constructor( fun managementOperation(): Optional = Optional.ofNullable(managementOperation) + /** + * A hold transaction representing reserved funds on a financial account. Holds move funds from + * available to pending balance in anticipation of future payments. They can be resolved via + * settlement (linked to payment), manual release, or expiration. + */ + fun hold(): Optional = Optional.ofNullable(hold) + fun isInternal(): Boolean = internal_ != null fun isTransfer(): Boolean = transfer != null @@ -80,6 +88,8 @@ private constructor( fun isManagementOperation(): Boolean = managementOperation != null + fun isHold(): Boolean = hold != null + /** Financial transaction with inheritance from unified base transaction */ fun asInternal(): FinancialTransaction = internal_.getOrThrow("internal_") @@ -97,6 +107,13 @@ private constructor( fun asManagementOperation(): ManagementOperationTransaction = managementOperation.getOrThrow("managementOperation") + /** + * A hold transaction representing reserved funds on a financial account. Holds move funds from + * available to pending balance in anticipation of future payments. They can be resolved via + * settlement (linked to payment), manual release, or expiration. + */ + fun asHold(): Hold = hold.getOrThrow("hold") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -107,6 +124,7 @@ private constructor( payment != null -> visitor.visitPayment(payment) externalPayment != null -> visitor.visitExternalPayment(externalPayment) managementOperation != null -> visitor.visitManagementOperation(managementOperation) + hold != null -> visitor.visitHold(hold) else -> visitor.unknown(_json) } @@ -144,6 +162,10 @@ private constructor( ) { managementOperation.validate() } + + override fun visitHold(hold: Hold) { + hold.validate() + } } ) validated = true @@ -181,6 +203,8 @@ private constructor( managementOperation: ManagementOperationTransaction ) = managementOperation.validity() + override fun visitHold(hold: Hold) = hold.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -196,11 +220,12 @@ private constructor( card == other.card && payment == other.payment && externalPayment == other.externalPayment && - managementOperation == other.managementOperation + managementOperation == other.managementOperation && + hold == other.hold } override fun hashCode(): Int = - Objects.hash(internal_, transfer, card, payment, externalPayment, managementOperation) + Objects.hash(internal_, transfer, card, payment, externalPayment, managementOperation, hold) override fun toString(): String = when { @@ -212,6 +237,7 @@ private constructor( "AccountActivityListResponse{externalPayment=$externalPayment}" managementOperation != null -> "AccountActivityListResponse{managementOperation=$managementOperation}" + hold != null -> "AccountActivityListResponse{hold=$hold}" _json != null -> "AccountActivityListResponse{_unknown=$_json}" else -> throw IllegalStateException("Invalid AccountActivityListResponse") } @@ -241,6 +267,13 @@ private constructor( @JvmStatic fun ofManagementOperation(managementOperation: ManagementOperationTransaction) = AccountActivityListResponse(managementOperation = managementOperation) + + /** + * A hold transaction representing reserved funds on a financial account. Holds move funds + * from available to pending balance in anticipation of future payments. They can be + * resolved via settlement (linked to payment), manual release, or expiration. + */ + @JvmStatic fun ofHold(hold: Hold) = AccountActivityListResponse(hold = hold) } /** @@ -265,6 +298,13 @@ private constructor( fun visitManagementOperation(managementOperation: ManagementOperationTransaction): T + /** + * A hold transaction representing reserved funds on a financial account. Holds move funds + * from available to pending balance in anticipation of future payments. They can be + * resolved via settlement (linked to payment), manual release, or expiration. + */ + fun visitHold(hold: Hold): T + /** * Maps an unknown variant of [AccountActivityListResponse] to a value of type [T]. * @@ -319,6 +359,11 @@ private constructor( AccountActivityListResponse(managementOperation = it, _json = json) } ?: AccountActivityListResponse(_json = json) } + "HOLD" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + AccountActivityListResponse(hold = it, _json = json) + } ?: AccountActivityListResponse(_json = json) + } } return AccountActivityListResponse(_json = json) @@ -341,6 +386,7 @@ private constructor( value.externalPayment != null -> generator.writeObject(value.externalPayment) value.managementOperation != null -> generator.writeObject(value.managementOperation) + value.hold != null -> generator.writeObject(value.hold) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid AccountActivityListResponse") } @@ -1054,6 +1100,8 @@ private constructor( @JvmField val MANAGEMENT_DISBURSEMENT = of("MANAGEMENT_DISBURSEMENT") + @JvmField val HOLD = of("HOLD") + @JvmField val PROGRAM_FUNDING = of("PROGRAM_FUNDING") @JvmStatic fun of(value: String) = TransactionCategory(JsonField.of(value)) @@ -1080,6 +1128,7 @@ private constructor( MANAGEMENT_FEE, MANAGEMENT_REWARD, MANAGEMENT_DISBURSEMENT, + HOLD, PROGRAM_FUNDING, } @@ -1114,6 +1163,7 @@ private constructor( MANAGEMENT_FEE, MANAGEMENT_REWARD, MANAGEMENT_DISBURSEMENT, + HOLD, PROGRAM_FUNDING, /** * An enum member indicating that [TransactionCategory] was instantiated with an @@ -1150,6 +1200,7 @@ private constructor( MANAGEMENT_FEE -> Value.MANAGEMENT_FEE MANAGEMENT_REWARD -> Value.MANAGEMENT_REWARD MANAGEMENT_DISBURSEMENT -> Value.MANAGEMENT_DISBURSEMENT + HOLD -> Value.HOLD PROGRAM_FUNDING -> Value.PROGRAM_FUNDING else -> Value._UNKNOWN } @@ -1184,6 +1235,7 @@ private constructor( MANAGEMENT_FEE -> Known.MANAGEMENT_FEE MANAGEMENT_REWARD -> Known.MANAGEMENT_REWARD MANAGEMENT_DISBURSEMENT -> Known.MANAGEMENT_DISBURSEMENT + HOLD -> Known.HOLD PROGRAM_FUNDING -> Known.PROGRAM_FUNDING else -> throw LithicInvalidDataException("Unknown TransactionCategory: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponse.kt index 8691ebef..1d2928e2 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponse.kt @@ -35,8 +35,8 @@ import kotlin.jvm.optionals.getOrNull * Response containing multiple transaction types. The `family` field determines which transaction * type is returned: INTERNAL returns FinancialTransaction, TRANSFER returns * BookTransferTransaction, CARD returns CardTransaction, PAYMENT returns PaymentTransaction, - * EXTERNAL_PAYMENT returns ExternalPaymentResponse, and MANAGEMENT_OPERATION returns - * ManagementOperationTransaction + * EXTERNAL_PAYMENT returns ExternalPaymentResponse, MANAGEMENT_OPERATION returns + * ManagementOperationTransaction, and HOLD returns HoldTransaction */ @JsonDeserialize(using = AccountActivityRetrieveTransactionResponse.Deserializer::class) @JsonSerialize(using = AccountActivityRetrieveTransactionResponse.Serializer::class) @@ -48,6 +48,7 @@ private constructor( private val payment: Payment? = null, private val externalPayment: ExternalPayment? = null, private val managementOperation: ManagementOperationTransaction? = null, + private val hold: Hold? = null, private val _json: JsonValue? = null, ) { @@ -68,6 +69,13 @@ private constructor( fun managementOperation(): Optional = Optional.ofNullable(managementOperation) + /** + * A hold transaction representing reserved funds on a financial account. Holds move funds from + * available to pending balance in anticipation of future payments. They can be resolved via + * settlement (linked to payment), manual release, or expiration. + */ + fun hold(): Optional = Optional.ofNullable(hold) + fun isInternal(): Boolean = internal_ != null fun isTransfer(): Boolean = transfer != null @@ -80,6 +88,8 @@ private constructor( fun isManagementOperation(): Boolean = managementOperation != null + fun isHold(): Boolean = hold != null + /** Financial transaction with inheritance from unified base transaction */ fun asInternal(): FinancialTransaction = internal_.getOrThrow("internal_") @@ -97,6 +107,13 @@ private constructor( fun asManagementOperation(): ManagementOperationTransaction = managementOperation.getOrThrow("managementOperation") + /** + * A hold transaction representing reserved funds on a financial account. Holds move funds from + * available to pending balance in anticipation of future payments. They can be resolved via + * settlement (linked to payment), manual release, or expiration. + */ + fun asHold(): Hold = hold.getOrThrow("hold") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -107,6 +124,7 @@ private constructor( payment != null -> visitor.visitPayment(payment) externalPayment != null -> visitor.visitExternalPayment(externalPayment) managementOperation != null -> visitor.visitManagementOperation(managementOperation) + hold != null -> visitor.visitHold(hold) else -> visitor.unknown(_json) } @@ -144,6 +162,10 @@ private constructor( ) { managementOperation.validate() } + + override fun visitHold(hold: Hold) { + hold.validate() + } } ) validated = true @@ -181,6 +203,8 @@ private constructor( managementOperation: ManagementOperationTransaction ) = managementOperation.validity() + override fun visitHold(hold: Hold) = hold.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -196,11 +220,12 @@ private constructor( card == other.card && payment == other.payment && externalPayment == other.externalPayment && - managementOperation == other.managementOperation + managementOperation == other.managementOperation && + hold == other.hold } override fun hashCode(): Int = - Objects.hash(internal_, transfer, card, payment, externalPayment, managementOperation) + Objects.hash(internal_, transfer, card, payment, externalPayment, managementOperation, hold) override fun toString(): String = when { @@ -212,6 +237,7 @@ private constructor( "AccountActivityRetrieveTransactionResponse{externalPayment=$externalPayment}" managementOperation != null -> "AccountActivityRetrieveTransactionResponse{managementOperation=$managementOperation}" + hold != null -> "AccountActivityRetrieveTransactionResponse{hold=$hold}" _json != null -> "AccountActivityRetrieveTransactionResponse{_unknown=$_json}" else -> throw IllegalStateException("Invalid AccountActivityRetrieveTransactionResponse") @@ -245,6 +271,13 @@ private constructor( @JvmStatic fun ofManagementOperation(managementOperation: ManagementOperationTransaction) = AccountActivityRetrieveTransactionResponse(managementOperation = managementOperation) + + /** + * A hold transaction representing reserved funds on a financial account. Holds move funds + * from available to pending balance in anticipation of future payments. They can be + * resolved via settlement (linked to payment), manual release, or expiration. + */ + @JvmStatic fun ofHold(hold: Hold) = AccountActivityRetrieveTransactionResponse(hold = hold) } /** @@ -269,6 +302,13 @@ private constructor( fun visitManagementOperation(managementOperation: ManagementOperationTransaction): T + /** + * A hold transaction representing reserved funds on a financial account. Holds move funds + * from available to pending balance in anticipation of future payments. They can be + * resolved via settlement (linked to payment), manual release, or expiration. + */ + fun visitHold(hold: Hold): T + /** * Maps an unknown variant of [AccountActivityRetrieveTransactionResponse] to a value of * type [T]. @@ -336,6 +376,11 @@ private constructor( ) } ?: AccountActivityRetrieveTransactionResponse(_json = json) } + "HOLD" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + AccountActivityRetrieveTransactionResponse(hold = it, _json = json) + } ?: AccountActivityRetrieveTransactionResponse(_json = json) + } } return AccountActivityRetrieveTransactionResponse(_json = json) @@ -360,6 +405,7 @@ private constructor( value.externalPayment != null -> generator.writeObject(value.externalPayment) value.managementOperation != null -> generator.writeObject(value.managementOperation) + value.hold != null -> generator.writeObject(value.hold) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException( @@ -1076,6 +1122,8 @@ private constructor( @JvmField val MANAGEMENT_DISBURSEMENT = of("MANAGEMENT_DISBURSEMENT") + @JvmField val HOLD = of("HOLD") + @JvmField val PROGRAM_FUNDING = of("PROGRAM_FUNDING") @JvmStatic fun of(value: String) = TransactionCategory(JsonField.of(value)) @@ -1102,6 +1150,7 @@ private constructor( MANAGEMENT_FEE, MANAGEMENT_REWARD, MANAGEMENT_DISBURSEMENT, + HOLD, PROGRAM_FUNDING, } @@ -1136,6 +1185,7 @@ private constructor( MANAGEMENT_FEE, MANAGEMENT_REWARD, MANAGEMENT_DISBURSEMENT, + HOLD, PROGRAM_FUNDING, /** * An enum member indicating that [TransactionCategory] was instantiated with an @@ -1172,6 +1222,7 @@ private constructor( MANAGEMENT_FEE -> Value.MANAGEMENT_FEE MANAGEMENT_REWARD -> Value.MANAGEMENT_REWARD MANAGEMENT_DISBURSEMENT -> Value.MANAGEMENT_DISBURSEMENT + HOLD -> Value.HOLD PROGRAM_FUNDING -> Value.PROGRAM_FUNDING else -> Value._UNKNOWN } @@ -1206,6 +1257,7 @@ private constructor( MANAGEMENT_FEE -> Known.MANAGEMENT_FEE MANAGEMENT_REWARD -> Known.MANAGEMENT_REWARD MANAGEMENT_DISBURSEMENT -> Known.MANAGEMENT_DISBURSEMENT + HOLD -> Known.HOLD PROGRAM_FUNDING -> Known.PROGRAM_FUNDING else -> throw LithicInvalidDataException("Unknown TransactionCategory: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccount.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccount.kt index 1980c5a5..cc76be9c 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccount.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccount.kt @@ -1571,6 +1571,8 @@ private constructor( @JvmField val PROGRAM_BANK_ACCOUNTS_PAYABLE = of("PROGRAM_BANK_ACCOUNTS_PAYABLE") + @JvmField val EARLY_DIRECT_DEPOSIT_FLOAT = of("EARLY_DIRECT_DEPOSIT_FLOAT") + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) } @@ -1586,6 +1588,7 @@ private constructor( PROGRAM_RECEIVABLES, COLLECTION, PROGRAM_BANK_ACCOUNTS_PAYABLE, + EARLY_DIRECT_DEPOSIT_FLOAT, } /** @@ -1608,6 +1611,7 @@ private constructor( PROGRAM_RECEIVABLES, COLLECTION, PROGRAM_BANK_ACCOUNTS_PAYABLE, + EARLY_DIRECT_DEPOSIT_FLOAT, /** An enum member indicating that [Type] was instantiated with an unknown value. */ _UNKNOWN, } @@ -1631,6 +1635,7 @@ private constructor( PROGRAM_RECEIVABLES -> Value.PROGRAM_RECEIVABLES COLLECTION -> Value.COLLECTION PROGRAM_BANK_ACCOUNTS_PAYABLE -> Value.PROGRAM_BANK_ACCOUNTS_PAYABLE + EARLY_DIRECT_DEPOSIT_FLOAT -> Value.EARLY_DIRECT_DEPOSIT_FLOAT else -> Value._UNKNOWN } @@ -1655,6 +1660,7 @@ private constructor( PROGRAM_RECEIVABLES -> Known.PROGRAM_RECEIVABLES COLLECTION -> Known.COLLECTION PROGRAM_BANK_ACCOUNTS_PAYABLE -> Known.PROGRAM_BANK_ACCOUNTS_PAYABLE + EARLY_DIRECT_DEPOSIT_FLOAT -> Known.EARLY_DIRECT_DEPOSIT_FLOAT else -> throw LithicInvalidDataException("Unknown Type: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountListParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountListParams.kt index e82603d1..fb45c625 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountListParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/FinancialAccountListParams.kt @@ -240,6 +240,8 @@ private constructor( @JvmField val SECURITY = of("SECURITY") + @JvmField val EARLY_DIRECT_DEPOSIT_FLOAT = of("EARLY_DIRECT_DEPOSIT_FLOAT") + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) } @@ -249,6 +251,7 @@ private constructor( OPERATING, RESERVE, SECURITY, + EARLY_DIRECT_DEPOSIT_FLOAT, } /** @@ -265,6 +268,7 @@ private constructor( OPERATING, RESERVE, SECURITY, + EARLY_DIRECT_DEPOSIT_FLOAT, /** An enum member indicating that [Type] was instantiated with an unknown value. */ _UNKNOWN, } @@ -282,6 +286,7 @@ private constructor( OPERATING -> Value.OPERATING RESERVE -> Value.RESERVE SECURITY -> Value.SECURITY + EARLY_DIRECT_DEPOSIT_FLOAT -> Value.EARLY_DIRECT_DEPOSIT_FLOAT else -> Value._UNKNOWN } @@ -300,6 +305,7 @@ private constructor( OPERATING -> Known.OPERATING RESERVE -> Known.RESERVE SECURITY -> Known.SECURITY + EARLY_DIRECT_DEPOSIT_FLOAT -> Known.EARLY_DIRECT_DEPOSIT_FLOAT else -> throw LithicInvalidDataException("Unknown Type: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Hold.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Hold.kt new file mode 100644 index 00000000..44b397dc --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Hold.kt @@ -0,0 +1,1066 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.Enum +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkKnown +import com.lithic.api.core.checkRequired +import com.lithic.api.core.toImmutable +import com.lithic.api.errors.LithicInvalidDataException +import java.time.OffsetDateTime +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * A hold transaction representing reserved funds on a financial account. Holds move funds from + * available to pending balance in anticipation of future payments. They can be resolved via + * settlement (linked to payment), manual release, or expiration. + */ +class Hold +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val token: JsonField, + private val created: JsonField, + private val status: JsonField, + private val updated: JsonField, + private val currency: JsonField, + private val events: JsonField>, + private val expirationDatetime: JsonField, + private val family: JsonField, + private val financialAccountToken: JsonField, + private val pendingAmount: JsonField, + private val result: JsonField, + private val userDefinedId: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("token") @ExcludeMissing token: JsonField = JsonMissing.of(), + @JsonProperty("created") + @ExcludeMissing + created: JsonField = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("updated") + @ExcludeMissing + updated: JsonField = JsonMissing.of(), + @JsonProperty("currency") @ExcludeMissing currency: JsonField = JsonMissing.of(), + @JsonProperty("events") + @ExcludeMissing + events: JsonField> = JsonMissing.of(), + @JsonProperty("expiration_datetime") + @ExcludeMissing + expirationDatetime: JsonField = JsonMissing.of(), + @JsonProperty("family") @ExcludeMissing family: JsonField = JsonMissing.of(), + @JsonProperty("financial_account_token") + @ExcludeMissing + financialAccountToken: JsonField = JsonMissing.of(), + @JsonProperty("pending_amount") + @ExcludeMissing + pendingAmount: JsonField = JsonMissing.of(), + @JsonProperty("result") + @ExcludeMissing + result: JsonField = JsonMissing.of(), + @JsonProperty("user_defined_id") + @ExcludeMissing + userDefinedId: JsonField = JsonMissing.of(), + ) : this( + token, + created, + status, + updated, + currency, + events, + expirationDatetime, + family, + financialAccountToken, + pendingAmount, + result, + userDefinedId, + mutableMapOf(), + ) + + /** + * Unique identifier for the transaction + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun token(): String = token.getRequired("token") + + /** + * ISO 8601 timestamp of when the transaction was created + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun created(): OffsetDateTime = created.getRequired("created") + + /** + * Status of a hold transaction + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun status(): HoldStatus = status.getRequired("status") + + /** + * ISO 8601 timestamp of when the transaction was last updated + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun updated(): OffsetDateTime = updated.getRequired("updated") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun currency(): Optional = currency.getOptional("currency") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun events(): Optional> = events.getOptional("events") + + /** + * When the hold will auto-expire if not resolved + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun expirationDatetime(): Optional = + expirationDatetime.getOptional("expiration_datetime") + + /** + * HOLD - Hold Transaction + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun family(): Optional = family.getOptional("family") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun financialAccountToken(): Optional = + financialAccountToken.getOptional("financial_account_token") + + /** + * Current pending amount (0 when resolved) + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun pendingAmount(): Optional = pendingAmount.getOptional("pending_amount") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun result(): Optional = result.getOptional("result") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun userDefinedId(): Optional = userDefinedId.getOptional("user_defined_id") + + /** + * Returns the raw JSON value of [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("token") @ExcludeMissing fun _token(): JsonField = token + + /** + * Returns the raw JSON value of [created]. + * + * Unlike [created], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created") @ExcludeMissing fun _created(): JsonField = created + + /** + * 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 [updated]. + * + * Unlike [updated], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("updated") @ExcludeMissing fun _updated(): JsonField = updated + + /** + * Returns the raw JSON value of [currency]. + * + * Unlike [currency], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("currency") @ExcludeMissing fun _currency(): JsonField = currency + + /** + * Returns the raw JSON value of [events]. + * + * Unlike [events], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("events") @ExcludeMissing fun _events(): JsonField> = events + + /** + * Returns the raw JSON value of [expirationDatetime]. + * + * Unlike [expirationDatetime], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("expiration_datetime") + @ExcludeMissing + fun _expirationDatetime(): JsonField = expirationDatetime + + /** + * Returns the raw JSON value of [family]. + * + * Unlike [family], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("family") @ExcludeMissing fun _family(): JsonField = family + + /** + * Returns the raw JSON value of [financialAccountToken]. + * + * Unlike [financialAccountToken], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("financial_account_token") + @ExcludeMissing + fun _financialAccountToken(): JsonField = financialAccountToken + + /** + * Returns the raw JSON value of [pendingAmount]. + * + * Unlike [pendingAmount], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("pending_amount") + @ExcludeMissing + fun _pendingAmount(): JsonField = pendingAmount + + /** + * Returns the raw JSON value of [result]. + * + * Unlike [result], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("result") @ExcludeMissing fun _result(): JsonField = result + + /** + * Returns the raw JSON value of [userDefinedId]. + * + * Unlike [userDefinedId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("user_defined_id") + @ExcludeMissing + fun _userDefinedId(): JsonField = userDefinedId + + @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 [Hold]. + * + * The following fields are required: + * ```java + * .token() + * .created() + * .status() + * .updated() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Hold]. */ + class Builder internal constructor() { + + private var token: JsonField? = null + private var created: JsonField? = null + private var status: JsonField? = null + private var updated: JsonField? = null + private var currency: JsonField = JsonMissing.of() + private var events: JsonField>? = null + private var expirationDatetime: JsonField = JsonMissing.of() + private var family: JsonField = JsonMissing.of() + private var financialAccountToken: JsonField = JsonMissing.of() + private var pendingAmount: JsonField = JsonMissing.of() + private var result: JsonField = JsonMissing.of() + private var userDefinedId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(hold: Hold) = apply { + token = hold.token + created = hold.created + status = hold.status + updated = hold.updated + currency = hold.currency + events = hold.events.map { it.toMutableList() } + expirationDatetime = hold.expirationDatetime + family = hold.family + financialAccountToken = hold.financialAccountToken + pendingAmount = hold.pendingAmount + result = hold.result + userDefinedId = hold.userDefinedId + additionalProperties = hold.additionalProperties.toMutableMap() + } + + /** Unique identifier for the transaction */ + fun token(token: String) = token(JsonField.of(token)) + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun token(token: JsonField) = apply { this.token = token } + + /** ISO 8601 timestamp of when the transaction was created */ + fun created(created: OffsetDateTime) = created(JsonField.of(created)) + + /** + * Sets [Builder.created] to an arbitrary JSON value. + * + * You should usually call [Builder.created] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun created(created: JsonField) = apply { this.created = created } + + /** Status of a hold transaction */ + fun status(status: HoldStatus) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [HoldStatus] 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 } + + /** ISO 8601 timestamp of when the transaction was last updated */ + fun updated(updated: OffsetDateTime) = updated(JsonField.of(updated)) + + /** + * Sets [Builder.updated] to an arbitrary JSON value. + * + * You should usually call [Builder.updated] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun updated(updated: JsonField) = apply { this.updated = updated } + + fun currency(currency: String) = currency(JsonField.of(currency)) + + /** + * Sets [Builder.currency] to an arbitrary JSON value. + * + * You should usually call [Builder.currency] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun currency(currency: JsonField) = apply { this.currency = currency } + + fun events(events: List) = events(JsonField.of(events)) + + /** + * Sets [Builder.events] to an arbitrary JSON value. + * + * You should usually call [Builder.events] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun events(events: JsonField>) = apply { + this.events = events.map { it.toMutableList() } + } + + /** + * Adds a single [HoldEvent] to [events]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addEvent(event: HoldEvent) = apply { + events = + (events ?: JsonField.of(mutableListOf())).also { + checkKnown("events", it).add(event) + } + } + + /** When the hold will auto-expire if not resolved */ + fun expirationDatetime(expirationDatetime: OffsetDateTime?) = + expirationDatetime(JsonField.ofNullable(expirationDatetime)) + + /** + * Alias for calling [Builder.expirationDatetime] with `expirationDatetime.orElse(null)`. + */ + fun expirationDatetime(expirationDatetime: Optional) = + expirationDatetime(expirationDatetime.getOrNull()) + + /** + * Sets [Builder.expirationDatetime] to an arbitrary JSON value. + * + * You should usually call [Builder.expirationDatetime] with a well-typed [OffsetDateTime] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun expirationDatetime(expirationDatetime: JsonField) = apply { + this.expirationDatetime = expirationDatetime + } + + /** HOLD - Hold Transaction */ + fun family(family: Family) = family(JsonField.of(family)) + + /** + * Sets [Builder.family] to an arbitrary JSON value. + * + * You should usually call [Builder.family] with a well-typed [Family] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun family(family: JsonField) = apply { this.family = family } + + fun financialAccountToken(financialAccountToken: String) = + financialAccountToken(JsonField.of(financialAccountToken)) + + /** + * Sets [Builder.financialAccountToken] to an arbitrary JSON value. + * + * You should usually call [Builder.financialAccountToken] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun financialAccountToken(financialAccountToken: JsonField) = apply { + this.financialAccountToken = financialAccountToken + } + + /** Current pending amount (0 when resolved) */ + fun pendingAmount(pendingAmount: Long) = pendingAmount(JsonField.of(pendingAmount)) + + /** + * Sets [Builder.pendingAmount] to an arbitrary JSON value. + * + * You should usually call [Builder.pendingAmount] with a well-typed [Long] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun pendingAmount(pendingAmount: JsonField) = apply { + this.pendingAmount = pendingAmount + } + + fun result(result: TransactionResult) = result(JsonField.of(result)) + + /** + * Sets [Builder.result] to an arbitrary JSON value. + * + * You should usually call [Builder.result] with a well-typed [TransactionResult] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun result(result: JsonField) = apply { this.result = result } + + fun userDefinedId(userDefinedId: String?) = + userDefinedId(JsonField.ofNullable(userDefinedId)) + + /** Alias for calling [Builder.userDefinedId] with `userDefinedId.orElse(null)`. */ + fun userDefinedId(userDefinedId: Optional) = + userDefinedId(userDefinedId.getOrNull()) + + /** + * Sets [Builder.userDefinedId] to an arbitrary JSON value. + * + * You should usually call [Builder.userDefinedId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun userDefinedId(userDefinedId: JsonField) = apply { + this.userDefinedId = userDefinedId + } + + 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 [Hold]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .token() + * .created() + * .status() + * .updated() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Hold = + Hold( + checkRequired("token", token), + checkRequired("created", created), + checkRequired("status", status), + checkRequired("updated", updated), + currency, + (events ?: JsonMissing.of()).map { it.toImmutable() }, + expirationDatetime, + family, + financialAccountToken, + pendingAmount, + result, + userDefinedId, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Hold = apply { + if (validated) { + return@apply + } + + token() + created() + status().validate() + updated() + currency() + events().ifPresent { it.forEach { it.validate() } } + expirationDatetime() + family().ifPresent { it.validate() } + financialAccountToken() + pendingAmount() + result().ifPresent { it.validate() } + userDefinedId() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 (token.asKnown().isPresent) 1 else 0) + + (if (created.asKnown().isPresent) 1 else 0) + + (status.asKnown().getOrNull()?.validity() ?: 0) + + (if (updated.asKnown().isPresent) 1 else 0) + + (if (currency.asKnown().isPresent) 1 else 0) + + (events.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (expirationDatetime.asKnown().isPresent) 1 else 0) + + (family.asKnown().getOrNull()?.validity() ?: 0) + + (if (financialAccountToken.asKnown().isPresent) 1 else 0) + + (if (pendingAmount.asKnown().isPresent) 1 else 0) + + (result.asKnown().getOrNull()?.validity() ?: 0) + + (if (userDefinedId.asKnown().isPresent) 1 else 0) + + /** Status of a hold transaction */ + class HoldStatus @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 PENDING = of("PENDING") + + @JvmField val SETTLED = of("SETTLED") + + @JvmField val EXPIRED = of("EXPIRED") + + @JvmField val VOIDED = of("VOIDED") + + @JvmField val DECLINED = of("DECLINED") + + @JvmField val REVERSED = of("REVERSED") + + @JvmField val CANCELED = of("CANCELED") + + @JvmField val RETURNED = of("RETURNED") + + @JvmStatic fun of(value: String) = HoldStatus(JsonField.of(value)) + } + + /** An enum containing [HoldStatus]'s known values. */ + enum class Known { + PENDING, + SETTLED, + EXPIRED, + VOIDED, + DECLINED, + REVERSED, + CANCELED, + RETURNED, + } + + /** + * An enum containing [HoldStatus]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [HoldStatus] 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 { + PENDING, + SETTLED, + EXPIRED, + VOIDED, + DECLINED, + REVERSED, + CANCELED, + RETURNED, + /** + * An enum member indicating that [HoldStatus] 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) { + PENDING -> Value.PENDING + SETTLED -> Value.SETTLED + EXPIRED -> Value.EXPIRED + VOIDED -> Value.VOIDED + DECLINED -> Value.DECLINED + REVERSED -> Value.REVERSED + CANCELED -> Value.CANCELED + RETURNED -> Value.RETURNED + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + PENDING -> Known.PENDING + SETTLED -> Known.SETTLED + EXPIRED -> Known.EXPIRED + VOIDED -> Known.VOIDED + DECLINED -> Known.DECLINED + REVERSED -> Known.REVERSED + CANCELED -> Known.CANCELED + RETURNED -> Known.RETURNED + else -> throw LithicInvalidDataException("Unknown HoldStatus: $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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + fun validate(): HoldStatus = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 HoldStatus && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** HOLD - Hold Transaction */ + class Family @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 HOLD = of("HOLD") + + @JvmStatic fun of(value: String) = Family(JsonField.of(value)) + } + + /** An enum containing [Family]'s known values. */ + enum class Known { + HOLD + } + + /** + * An enum containing [Family]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Family] 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 { + HOLD, + /** An enum member indicating that [Family] 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) { + HOLD -> Value.HOLD + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + HOLD -> Known.HOLD + else -> throw LithicInvalidDataException("Unknown Family: $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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + fun validate(): Family = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 Family && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class TransactionResult @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 APPROVED = of("APPROVED") + + @JvmField val DECLINED = of("DECLINED") + + @JvmStatic fun of(value: String) = TransactionResult(JsonField.of(value)) + } + + /** An enum containing [TransactionResult]'s known values. */ + enum class Known { + APPROVED, + DECLINED, + } + + /** + * An enum containing [TransactionResult]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TransactionResult] 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 { + APPROVED, + DECLINED, + /** + * An enum member indicating that [TransactionResult] 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) { + APPROVED -> Value.APPROVED + DECLINED -> Value.DECLINED + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + APPROVED -> Known.APPROVED + DECLINED -> Known.DECLINED + else -> throw LithicInvalidDataException("Unknown TransactionResult: $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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + fun validate(): TransactionResult = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 TransactionResult && 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 Hold && + token == other.token && + created == other.created && + status == other.status && + updated == other.updated && + currency == other.currency && + events == other.events && + expirationDatetime == other.expirationDatetime && + family == other.family && + financialAccountToken == other.financialAccountToken && + pendingAmount == other.pendingAmount && + result == other.result && + userDefinedId == other.userDefinedId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + token, + created, + status, + updated, + currency, + events, + expirationDatetime, + family, + financialAccountToken, + pendingAmount, + result, + userDefinedId, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Hold{token=$token, created=$created, status=$status, updated=$updated, currency=$currency, events=$events, expirationDatetime=$expirationDatetime, family=$family, financialAccountToken=$financialAccountToken, pendingAmount=$pendingAmount, result=$result, userDefinedId=$userDefinedId, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldCreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldCreateParams.kt new file mode 100644 index 00000000..8ff7ac50 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldCreateParams.kt @@ -0,0 +1,742 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.Params +import com.lithic.api.core.checkRequired +import com.lithic.api.core.http.Headers +import com.lithic.api.core.http.QueryParams +import com.lithic.api.errors.LithicInvalidDataException +import java.time.OffsetDateTime +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Create a hold on a financial account. Holds reserve funds by moving them from available to + * pending balance. They can be resolved via settlement (linked to a payment or book transfer), + * voiding, or expiration. + */ +class HoldCreateParams +private constructor( + private val financialAccountToken: String?, + private val body: CreateHoldRequest, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun financialAccountToken(): Optional = Optional.ofNullable(financialAccountToken) + + /** + * Amount to hold in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amount(): Long = body.amount() + + /** + * Customer-provided token for idempotency. Becomes the hold token. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun token(): Optional = body.token() + + /** + * When the hold should auto-expire + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun expirationDatetime(): Optional = body.expirationDatetime() + + /** + * Reason for the hold + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun memo(): Optional = body.memo() + + /** + * User-provided identifier for the hold + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun userDefinedId(): Optional = body.userDefinedId() + + /** + * Returns the raw JSON value of [amount]. + * + * Unlike [amount], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _amount(): JsonField = body._amount() + + /** + * Returns the raw JSON value of [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _token(): JsonField = body._token() + + /** + * Returns the raw JSON value of [expirationDatetime]. + * + * Unlike [expirationDatetime], this method doesn't throw if the JSON field has an unexpected + * type. + */ + fun _expirationDatetime(): JsonField = body._expirationDatetime() + + /** + * Returns the raw JSON value of [memo]. + * + * Unlike [memo], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _memo(): JsonField = body._memo() + + /** + * Returns the raw JSON value of [userDefinedId]. + * + * Unlike [userDefinedId], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _userDefinedId(): JsonField = body._userDefinedId() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [HoldCreateParams]. + * + * The following fields are required: + * ```java + * .amount() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [HoldCreateParams]. */ + class Builder internal constructor() { + + private var financialAccountToken: String? = null + private var body: CreateHoldRequest.Builder = CreateHoldRequest.builder() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(holdCreateParams: HoldCreateParams) = apply { + financialAccountToken = holdCreateParams.financialAccountToken + body = holdCreateParams.body.toBuilder() + additionalHeaders = holdCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = holdCreateParams.additionalQueryParams.toBuilder() + } + + fun financialAccountToken(financialAccountToken: String?) = apply { + this.financialAccountToken = financialAccountToken + } + + /** + * Alias for calling [Builder.financialAccountToken] with + * `financialAccountToken.orElse(null)`. + */ + fun financialAccountToken(financialAccountToken: Optional) = + financialAccountToken(financialAccountToken.getOrNull()) + + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [amount] + * - [token] + * - [expirationDatetime] + * - [memo] + * - [userDefinedId] + * - etc. + */ + fun body(body: CreateHoldRequest) = apply { this.body = body.toBuilder() } + + /** Amount to hold in cents */ + fun amount(amount: Long) = apply { body.amount(amount) } + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun amount(amount: JsonField) = apply { body.amount(amount) } + + /** Customer-provided token for idempotency. Becomes the hold token. */ + fun token(token: String) = apply { body.token(token) } + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun token(token: JsonField) = apply { body.token(token) } + + /** When the hold should auto-expire */ + fun expirationDatetime(expirationDatetime: OffsetDateTime) = apply { + body.expirationDatetime(expirationDatetime) + } + + /** + * Sets [Builder.expirationDatetime] to an arbitrary JSON value. + * + * You should usually call [Builder.expirationDatetime] with a well-typed [OffsetDateTime] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun expirationDatetime(expirationDatetime: JsonField) = apply { + body.expirationDatetime(expirationDatetime) + } + + /** Reason for the hold */ + fun memo(memo: String?) = apply { body.memo(memo) } + + /** Alias for calling [Builder.memo] with `memo.orElse(null)`. */ + fun memo(memo: Optional) = memo(memo.getOrNull()) + + /** + * Sets [Builder.memo] to an arbitrary JSON value. + * + * You should usually call [Builder.memo] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun memo(memo: JsonField) = apply { body.memo(memo) } + + /** User-provided identifier for the hold */ + fun userDefinedId(userDefinedId: String) = apply { body.userDefinedId(userDefinedId) } + + /** + * Sets [Builder.userDefinedId] to an arbitrary JSON value. + * + * You should usually call [Builder.userDefinedId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun userDefinedId(userDefinedId: JsonField) = apply { + body.userDefinedId(userDefinedId) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [HoldCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .amount() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): HoldCreateParams = + HoldCreateParams( + financialAccountToken, + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): CreateHoldRequest = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> financialAccountToken ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + /** Request to create a new hold on a financial account */ + class CreateHoldRequest + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val amount: JsonField, + private val token: JsonField, + private val expirationDatetime: JsonField, + private val memo: JsonField, + private val userDefinedId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("token") @ExcludeMissing token: JsonField = JsonMissing.of(), + @JsonProperty("expiration_datetime") + @ExcludeMissing + expirationDatetime: JsonField = JsonMissing.of(), + @JsonProperty("memo") @ExcludeMissing memo: JsonField = JsonMissing.of(), + @JsonProperty("user_defined_id") + @ExcludeMissing + userDefinedId: JsonField = JsonMissing.of(), + ) : this(amount, token, expirationDatetime, memo, userDefinedId, mutableMapOf()) + + /** + * Amount to hold in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amount(): Long = amount.getRequired("amount") + + /** + * Customer-provided token for idempotency. Becomes the hold token. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun token(): Optional = token.getOptional("token") + + /** + * When the hold should auto-expire + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun expirationDatetime(): Optional = + expirationDatetime.getOptional("expiration_datetime") + + /** + * Reason for the hold + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun memo(): Optional = memo.getOptional("memo") + + /** + * User-provided identifier for the hold + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun userDefinedId(): Optional = userDefinedId.getOptional("user_defined_id") + + /** + * 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 [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("token") @ExcludeMissing fun _token(): JsonField = token + + /** + * Returns the raw JSON value of [expirationDatetime]. + * + * Unlike [expirationDatetime], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("expiration_datetime") + @ExcludeMissing + fun _expirationDatetime(): JsonField = expirationDatetime + + /** + * Returns the raw JSON value of [memo]. + * + * Unlike [memo], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("memo") @ExcludeMissing fun _memo(): JsonField = memo + + /** + * Returns the raw JSON value of [userDefinedId]. + * + * Unlike [userDefinedId], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("user_defined_id") + @ExcludeMissing + fun _userDefinedId(): JsonField = userDefinedId + + @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 [CreateHoldRequest]. + * + * The following fields are required: + * ```java + * .amount() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CreateHoldRequest]. */ + class Builder internal constructor() { + + private var amount: JsonField? = null + private var token: JsonField = JsonMissing.of() + private var expirationDatetime: JsonField = JsonMissing.of() + private var memo: JsonField = JsonMissing.of() + private var userDefinedId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(createHoldRequest: CreateHoldRequest) = apply { + amount = createHoldRequest.amount + token = createHoldRequest.token + expirationDatetime = createHoldRequest.expirationDatetime + memo = createHoldRequest.memo + userDefinedId = createHoldRequest.userDefinedId + additionalProperties = createHoldRequest.additionalProperties.toMutableMap() + } + + /** Amount to hold in cents */ + fun amount(amount: Long) = amount(JsonField.of(amount)) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Long] 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 } + + /** Customer-provided token for idempotency. Becomes the hold token. */ + fun token(token: String) = token(JsonField.of(token)) + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun token(token: JsonField) = apply { this.token = token } + + /** When the hold should auto-expire */ + fun expirationDatetime(expirationDatetime: OffsetDateTime) = + expirationDatetime(JsonField.of(expirationDatetime)) + + /** + * Sets [Builder.expirationDatetime] to an arbitrary JSON value. + * + * You should usually call [Builder.expirationDatetime] with a well-typed + * [OffsetDateTime] value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun expirationDatetime(expirationDatetime: JsonField) = apply { + this.expirationDatetime = expirationDatetime + } + + /** Reason for the hold */ + fun memo(memo: String?) = memo(JsonField.ofNullable(memo)) + + /** Alias for calling [Builder.memo] with `memo.orElse(null)`. */ + fun memo(memo: Optional) = memo(memo.getOrNull()) + + /** + * Sets [Builder.memo] to an arbitrary JSON value. + * + * You should usually call [Builder.memo] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun memo(memo: JsonField) = apply { this.memo = memo } + + /** User-provided identifier for the hold */ + fun userDefinedId(userDefinedId: String) = userDefinedId(JsonField.of(userDefinedId)) + + /** + * Sets [Builder.userDefinedId] to an arbitrary JSON value. + * + * You should usually call [Builder.userDefinedId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun userDefinedId(userDefinedId: JsonField) = apply { + this.userDefinedId = userDefinedId + } + + 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 [CreateHoldRequest]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .amount() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): CreateHoldRequest = + CreateHoldRequest( + checkRequired("amount", amount), + token, + expirationDatetime, + memo, + userDefinedId, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): CreateHoldRequest = apply { + if (validated) { + return@apply + } + + amount() + token() + expirationDatetime() + memo() + userDefinedId() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 (amount.asKnown().isPresent) 1 else 0) + + (if (token.asKnown().isPresent) 1 else 0) + + (if (expirationDatetime.asKnown().isPresent) 1 else 0) + + (if (memo.asKnown().isPresent) 1 else 0) + + (if (userDefinedId.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CreateHoldRequest && + amount == other.amount && + token == other.token && + expirationDatetime == other.expirationDatetime && + memo == other.memo && + userDefinedId == other.userDefinedId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + amount, + token, + expirationDatetime, + memo, + userDefinedId, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CreateHoldRequest{amount=$amount, token=$token, expirationDatetime=$expirationDatetime, memo=$memo, userDefinedId=$userDefinedId, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is HoldCreateParams && + financialAccountToken == other.financialAccountToken && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(financialAccountToken, body, additionalHeaders, additionalQueryParams) + + override fun toString() = + "HoldCreateParams{financialAccountToken=$financialAccountToken, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldEvent.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldEvent.kt new file mode 100644 index 00000000..0c877899 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldEvent.kt @@ -0,0 +1,892 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.Enum +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkKnown +import com.lithic.api.core.checkRequired +import com.lithic.api.core.toImmutable +import com.lithic.api.errors.LithicInvalidDataException +import java.time.OffsetDateTime +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Event representing a lifecycle change to a hold */ +class HoldEvent +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val token: JsonField, + private val amount: JsonField, + private val created: JsonField, + private val detailedResults: JsonField>, + private val memo: JsonField, + private val result: JsonField, + private val settlingTransactionToken: JsonField, + private val type: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("token") @ExcludeMissing token: JsonField = JsonMissing.of(), + @JsonProperty("amount") @ExcludeMissing amount: JsonField = JsonMissing.of(), + @JsonProperty("created") + @ExcludeMissing + created: JsonField = JsonMissing.of(), + @JsonProperty("detailed_results") + @ExcludeMissing + detailedResults: JsonField> = JsonMissing.of(), + @JsonProperty("memo") @ExcludeMissing memo: JsonField = JsonMissing.of(), + @JsonProperty("result") + @ExcludeMissing + result: JsonField = JsonMissing.of(), + @JsonProperty("settling_transaction_token") + @ExcludeMissing + settlingTransactionToken: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + ) : this( + token, + amount, + created, + detailedResults, + memo, + result, + settlingTransactionToken, + type, + mutableMapOf(), + ) + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun token(): String = token.getRequired("token") + + /** + * Amount in cents + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun amount(): Long = amount.getRequired("amount") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun created(): OffsetDateTime = created.getRequired("created") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun detailedResults(): List = detailedResults.getRequired("detailed_results") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun memo(): Optional = memo.getOptional("memo") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun result(): TransactionResult = result.getRequired("result") + + /** + * Transaction token of the payment that settled this hold (only populated for HOLD_SETTLED + * events) + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun settlingTransactionToken(): Optional = + settlingTransactionToken.getOptional("settling_transaction_token") + + /** + * Type of hold lifecycle event + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): HoldEventType = type.getRequired("type") + + /** + * Returns the raw JSON value of [token]. + * + * Unlike [token], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("token") @ExcludeMissing fun _token(): JsonField = token + + /** + * 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 [created]. + * + * Unlike [created], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created") @ExcludeMissing fun _created(): JsonField = created + + /** + * Returns the raw JSON value of [detailedResults]. + * + * Unlike [detailedResults], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("detailed_results") + @ExcludeMissing + fun _detailedResults(): JsonField> = detailedResults + + /** + * Returns the raw JSON value of [memo]. + * + * Unlike [memo], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("memo") @ExcludeMissing fun _memo(): JsonField = memo + + /** + * Returns the raw JSON value of [result]. + * + * Unlike [result], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("result") @ExcludeMissing fun _result(): JsonField = result + + /** + * Returns the raw JSON value of [settlingTransactionToken]. + * + * Unlike [settlingTransactionToken], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("settling_transaction_token") + @ExcludeMissing + fun _settlingTransactionToken(): JsonField = settlingTransactionToken + + /** + * 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 + + @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 [HoldEvent]. + * + * The following fields are required: + * ```java + * .token() + * .amount() + * .created() + * .detailedResults() + * .memo() + * .result() + * .settlingTransactionToken() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [HoldEvent]. */ + class Builder internal constructor() { + + private var token: JsonField? = null + private var amount: JsonField? = null + private var created: JsonField? = null + private var detailedResults: JsonField>? = null + private var memo: JsonField? = null + private var result: JsonField? = null + private var settlingTransactionToken: JsonField? = null + private var type: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(holdEvent: HoldEvent) = apply { + token = holdEvent.token + amount = holdEvent.amount + created = holdEvent.created + detailedResults = holdEvent.detailedResults.map { it.toMutableList() } + memo = holdEvent.memo + result = holdEvent.result + settlingTransactionToken = holdEvent.settlingTransactionToken + type = holdEvent.type + additionalProperties = holdEvent.additionalProperties.toMutableMap() + } + + fun token(token: String) = token(JsonField.of(token)) + + /** + * Sets [Builder.token] to an arbitrary JSON value. + * + * You should usually call [Builder.token] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun token(token: JsonField) = apply { this.token = token } + + /** Amount in cents */ + fun amount(amount: Long) = amount(JsonField.of(amount)) + + /** + * Sets [Builder.amount] to an arbitrary JSON value. + * + * You should usually call [Builder.amount] with a well-typed [Long] 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 created(created: OffsetDateTime) = created(JsonField.of(created)) + + /** + * Sets [Builder.created] to an arbitrary JSON value. + * + * You should usually call [Builder.created] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun created(created: JsonField) = apply { this.created = created } + + fun detailedResults(detailedResults: List) = + detailedResults(JsonField.of(detailedResults)) + + /** + * Sets [Builder.detailedResults] to an arbitrary JSON value. + * + * You should usually call [Builder.detailedResults] with a well-typed + * `List` value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun detailedResults(detailedResults: JsonField>) = apply { + this.detailedResults = detailedResults.map { it.toMutableList() } + } + + /** + * Adds a single [DetailedResults] to [detailedResults]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addDetailedResult(detailedResult: DetailedResults) = apply { + detailedResults = + (detailedResults ?: JsonField.of(mutableListOf())).also { + checkKnown("detailedResults", it).add(detailedResult) + } + } + + fun memo(memo: String?) = memo(JsonField.ofNullable(memo)) + + /** Alias for calling [Builder.memo] with `memo.orElse(null)`. */ + fun memo(memo: Optional) = memo(memo.getOrNull()) + + /** + * Sets [Builder.memo] to an arbitrary JSON value. + * + * You should usually call [Builder.memo] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun memo(memo: JsonField) = apply { this.memo = memo } + + fun result(result: TransactionResult) = result(JsonField.of(result)) + + /** + * Sets [Builder.result] to an arbitrary JSON value. + * + * You should usually call [Builder.result] with a well-typed [TransactionResult] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun result(result: JsonField) = apply { this.result = result } + + /** + * Transaction token of the payment that settled this hold (only populated for HOLD_SETTLED + * events) + */ + fun settlingTransactionToken(settlingTransactionToken: String?) = + settlingTransactionToken(JsonField.ofNullable(settlingTransactionToken)) + + /** + * Alias for calling [Builder.settlingTransactionToken] with + * `settlingTransactionToken.orElse(null)`. + */ + fun settlingTransactionToken(settlingTransactionToken: Optional) = + settlingTransactionToken(settlingTransactionToken.getOrNull()) + + /** + * Sets [Builder.settlingTransactionToken] to an arbitrary JSON value. + * + * You should usually call [Builder.settlingTransactionToken] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun settlingTransactionToken(settlingTransactionToken: JsonField) = apply { + this.settlingTransactionToken = settlingTransactionToken + } + + /** Type of hold lifecycle event */ + fun type(type: HoldEventType) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [HoldEventType] 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 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 [HoldEvent]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .token() + * .amount() + * .created() + * .detailedResults() + * .memo() + * .result() + * .settlingTransactionToken() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): HoldEvent = + HoldEvent( + checkRequired("token", token), + checkRequired("amount", amount), + checkRequired("created", created), + checkRequired("detailedResults", detailedResults).map { it.toImmutable() }, + checkRequired("memo", memo), + checkRequired("result", result), + checkRequired("settlingTransactionToken", settlingTransactionToken), + checkRequired("type", type), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): HoldEvent = apply { + if (validated) { + return@apply + } + + token() + amount() + created() + detailedResults().forEach { it.validate() } + memo() + result().validate() + settlingTransactionToken() + type().validate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 (token.asKnown().isPresent) 1 else 0) + + (if (amount.asKnown().isPresent) 1 else 0) + + (if (created.asKnown().isPresent) 1 else 0) + + (detailedResults.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (memo.asKnown().isPresent) 1 else 0) + + (result.asKnown().getOrNull()?.validity() ?: 0) + + (if (settlingTransactionToken.asKnown().isPresent) 1 else 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + class DetailedResults @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 APPROVED = of("APPROVED") + + @JvmField val INSUFFICIENT_FUNDS = of("INSUFFICIENT_FUNDS") + + @JvmStatic fun of(value: String) = DetailedResults(JsonField.of(value)) + } + + /** An enum containing [DetailedResults]'s known values. */ + enum class Known { + APPROVED, + INSUFFICIENT_FUNDS, + } + + /** + * An enum containing [DetailedResults]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [DetailedResults] 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 { + APPROVED, + INSUFFICIENT_FUNDS, + /** + * An enum member indicating that [DetailedResults] 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) { + APPROVED -> Value.APPROVED + INSUFFICIENT_FUNDS -> Value.INSUFFICIENT_FUNDS + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + APPROVED -> Known.APPROVED + INSUFFICIENT_FUNDS -> Known.INSUFFICIENT_FUNDS + else -> throw LithicInvalidDataException("Unknown DetailedResults: $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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + fun validate(): DetailedResults = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 DetailedResults && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class TransactionResult @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 APPROVED = of("APPROVED") + + @JvmField val DECLINED = of("DECLINED") + + @JvmStatic fun of(value: String) = TransactionResult(JsonField.of(value)) + } + + /** An enum containing [TransactionResult]'s known values. */ + enum class Known { + APPROVED, + DECLINED, + } + + /** + * An enum containing [TransactionResult]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TransactionResult] 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 { + APPROVED, + DECLINED, + /** + * An enum member indicating that [TransactionResult] 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) { + APPROVED -> Value.APPROVED + DECLINED -> Value.DECLINED + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + APPROVED -> Known.APPROVED + DECLINED -> Known.DECLINED + else -> throw LithicInvalidDataException("Unknown TransactionResult: $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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + fun validate(): TransactionResult = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 TransactionResult && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Type of hold lifecycle event */ + class HoldEventType @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 HOLD_INITIATED = of("HOLD_INITIATED") + + @JvmField val HOLD_VOIDED = of("HOLD_VOIDED") + + @JvmField val HOLD_EXPIRED = of("HOLD_EXPIRED") + + @JvmField val HOLD_SETTLED = of("HOLD_SETTLED") + + @JvmStatic fun of(value: String) = HoldEventType(JsonField.of(value)) + } + + /** An enum containing [HoldEventType]'s known values. */ + enum class Known { + HOLD_INITIATED, + HOLD_VOIDED, + HOLD_EXPIRED, + HOLD_SETTLED, + } + + /** + * An enum containing [HoldEventType]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [HoldEventType] 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 { + HOLD_INITIATED, + HOLD_VOIDED, + HOLD_EXPIRED, + HOLD_SETTLED, + /** + * An enum member indicating that [HoldEventType] 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) { + HOLD_INITIATED -> Value.HOLD_INITIATED + HOLD_VOIDED -> Value.HOLD_VOIDED + HOLD_EXPIRED -> Value.HOLD_EXPIRED + HOLD_SETTLED -> Value.HOLD_SETTLED + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + HOLD_INITIATED -> Known.HOLD_INITIATED + HOLD_VOIDED -> Known.HOLD_VOIDED + HOLD_EXPIRED -> Known.HOLD_EXPIRED + HOLD_SETTLED -> Known.HOLD_SETTLED + else -> throw LithicInvalidDataException("Unknown HoldEventType: $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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + fun validate(): HoldEventType = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 HoldEventType && 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 HoldEvent && + token == other.token && + amount == other.amount && + created == other.created && + detailedResults == other.detailedResults && + memo == other.memo && + result == other.result && + settlingTransactionToken == other.settlingTransactionToken && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + token, + amount, + created, + detailedResults, + memo, + result, + settlingTransactionToken, + type, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "HoldEvent{token=$token, amount=$amount, created=$created, detailedResults=$detailedResults, memo=$memo, result=$result, settlingTransactionToken=$settlingTransactionToken, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPage.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPage.kt new file mode 100644 index 00000000..cee46a2a --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPage.kt @@ -0,0 +1,131 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.lithic.api.core.AutoPager +import com.lithic.api.core.Page +import com.lithic.api.core.checkRequired +import com.lithic.api.services.blocking.HoldService +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** @see HoldService.list */ +class HoldListPage +private constructor( + private val service: HoldService, + private val params: HoldListParams, + private val response: HoldListPageResponse, +) : Page { + + /** + * Delegates to [HoldListPageResponse], but gracefully handles missing data. + * + * @see HoldListPageResponse.data + */ + fun data(): List = response._data().getOptional("data").getOrNull() ?: emptyList() + + /** + * Delegates to [HoldListPageResponse], but gracefully handles missing data. + * + * @see HoldListPageResponse.hasMore + */ + fun hasMore(): Optional = response._hasMore().getOptional("has_more") + + override fun items(): List = data() + + override fun hasNextPage(): Boolean = items().isNotEmpty() + + fun nextPageParams(): HoldListParams = + if (params.endingBefore().isPresent) { + params.toBuilder().endingBefore(items().first()._token().getOptional("token")).build() + } else { + params.toBuilder().startingAfter(items().last()._token().getOptional("token")).build() + } + + override fun nextPage(): HoldListPage = service.list(nextPageParams()) + + fun autoPager(): AutoPager = AutoPager.from(this) + + /** The parameters that were used to request this page. */ + fun params(): HoldListParams = params + + /** The response that this page was parsed from. */ + fun response(): HoldListPageResponse = response + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [HoldListPage]. + * + * The following fields are required: + * ```java + * .service() + * .params() + * .response() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [HoldListPage]. */ + class Builder internal constructor() { + + private var service: HoldService? = null + private var params: HoldListParams? = null + private var response: HoldListPageResponse? = null + + @JvmSynthetic + internal fun from(holdListPage: HoldListPage) = apply { + service = holdListPage.service + params = holdListPage.params + response = holdListPage.response + } + + fun service(service: HoldService) = apply { this.service = service } + + /** The parameters that were used to request this page. */ + fun params(params: HoldListParams) = apply { this.params = params } + + /** The response that this page was parsed from. */ + fun response(response: HoldListPageResponse) = apply { this.response = response } + + /** + * Returns an immutable instance of [HoldListPage]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .service() + * .params() + * .response() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): HoldListPage = + HoldListPage( + checkRequired("service", service), + checkRequired("params", params), + checkRequired("response", response), + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is HoldListPage && + service == other.service && + params == other.params && + response == other.response + } + + override fun hashCode(): Int = Objects.hash(service, params, response) + + override fun toString() = "HoldListPage{service=$service, params=$params, response=$response}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPageAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPageAsync.kt new file mode 100644 index 00000000..4bbac0a4 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPageAsync.kt @@ -0,0 +1,145 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.lithic.api.core.AutoPagerAsync +import com.lithic.api.core.PageAsync +import com.lithic.api.core.checkRequired +import com.lithic.api.services.async.HoldServiceAsync +import java.util.Objects +import java.util.Optional +import java.util.concurrent.CompletableFuture +import java.util.concurrent.Executor +import kotlin.jvm.optionals.getOrNull + +/** @see HoldServiceAsync.list */ +class HoldListPageAsync +private constructor( + private val service: HoldServiceAsync, + private val streamHandlerExecutor: Executor, + private val params: HoldListParams, + private val response: HoldListPageResponse, +) : PageAsync { + + /** + * Delegates to [HoldListPageResponse], but gracefully handles missing data. + * + * @see HoldListPageResponse.data + */ + fun data(): List = response._data().getOptional("data").getOrNull() ?: emptyList() + + /** + * Delegates to [HoldListPageResponse], but gracefully handles missing data. + * + * @see HoldListPageResponse.hasMore + */ + fun hasMore(): Optional = response._hasMore().getOptional("has_more") + + override fun items(): List = data() + + override fun hasNextPage(): Boolean = items().isNotEmpty() + + fun nextPageParams(): HoldListParams = + if (params.endingBefore().isPresent) { + params.toBuilder().endingBefore(items().first()._token().getOptional("token")).build() + } else { + params.toBuilder().startingAfter(items().last()._token().getOptional("token")).build() + } + + override fun nextPage(): CompletableFuture = service.list(nextPageParams()) + + fun autoPager(): AutoPagerAsync = AutoPagerAsync.from(this, streamHandlerExecutor) + + /** The parameters that were used to request this page. */ + fun params(): HoldListParams = params + + /** The response that this page was parsed from. */ + fun response(): HoldListPageResponse = response + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [HoldListPageAsync]. + * + * The following fields are required: + * ```java + * .service() + * .streamHandlerExecutor() + * .params() + * .response() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [HoldListPageAsync]. */ + class Builder internal constructor() { + + private var service: HoldServiceAsync? = null + private var streamHandlerExecutor: Executor? = null + private var params: HoldListParams? = null + private var response: HoldListPageResponse? = null + + @JvmSynthetic + internal fun from(holdListPageAsync: HoldListPageAsync) = apply { + service = holdListPageAsync.service + streamHandlerExecutor = holdListPageAsync.streamHandlerExecutor + params = holdListPageAsync.params + response = holdListPageAsync.response + } + + fun service(service: HoldServiceAsync) = apply { this.service = service } + + fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { + this.streamHandlerExecutor = streamHandlerExecutor + } + + /** The parameters that were used to request this page. */ + fun params(params: HoldListParams) = apply { this.params = params } + + /** The response that this page was parsed from. */ + fun response(response: HoldListPageResponse) = apply { this.response = response } + + /** + * Returns an immutable instance of [HoldListPageAsync]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .service() + * .streamHandlerExecutor() + * .params() + * .response() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): HoldListPageAsync = + HoldListPageAsync( + checkRequired("service", service), + checkRequired("streamHandlerExecutor", streamHandlerExecutor), + checkRequired("params", params), + checkRequired("response", response), + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is HoldListPageAsync && + service == other.service && + streamHandlerExecutor == other.streamHandlerExecutor && + params == other.params && + response == other.response + } + + override fun hashCode(): Int = Objects.hash(service, streamHandlerExecutor, params, response) + + override fun toString() = + "HoldListPageAsync{service=$service, streamHandlerExecutor=$streamHandlerExecutor, params=$params, response=$response}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPageResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPageResponse.kt new file mode 100644 index 00000000..71ebf38a --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListPageResponse.kt @@ -0,0 +1,223 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkKnown +import com.lithic.api.core.checkRequired +import com.lithic.api.core.toImmutable +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +/** Paginated response containing hold transactions */ +class HoldListPageResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val data: JsonField>, + private val hasMore: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("data") @ExcludeMissing data: JsonField> = JsonMissing.of(), + @JsonProperty("has_more") @ExcludeMissing hasMore: JsonField = JsonMissing.of(), + ) : this(data, hasMore, mutableMapOf()) + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun data(): List = data.getRequired("data") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun hasMore(): Boolean = hasMore.getRequired("has_more") + + /** + * Returns the raw JSON value of [data]. + * + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField> = data + + /** + * Returns the raw JSON value of [hasMore]. + * + * Unlike [hasMore], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("has_more") @ExcludeMissing fun _hasMore(): JsonField = hasMore + + @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 [HoldListPageResponse]. + * + * The following fields are required: + * ```java + * .data() + * .hasMore() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [HoldListPageResponse]. */ + class Builder internal constructor() { + + private var data: JsonField>? = null + private var hasMore: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(holdListPageResponse: HoldListPageResponse) = apply { + data = holdListPageResponse.data.map { it.toMutableList() } + hasMore = holdListPageResponse.hasMore + additionalProperties = holdListPageResponse.additionalProperties.toMutableMap() + } + + fun data(data: List) = data(JsonField.of(data)) + + /** + * Sets [Builder.data] to an arbitrary JSON value. + * + * You should usually call [Builder.data] with a well-typed `List` value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun data(data: JsonField>) = apply { + this.data = data.map { it.toMutableList() } + } + + /** + * Adds a single [Hold] to [Builder.data]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addData(data: Hold) = apply { + this.data = + (this.data ?: JsonField.of(mutableListOf())).also { + checkKnown("data", it).add(data) + } + } + + fun hasMore(hasMore: Boolean) = hasMore(JsonField.of(hasMore)) + + /** + * Sets [Builder.hasMore] to an arbitrary JSON value. + * + * You should usually call [Builder.hasMore] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun hasMore(hasMore: JsonField) = apply { this.hasMore = hasMore } + + 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 [HoldListPageResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .data() + * .hasMore() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): HoldListPageResponse = + HoldListPageResponse( + checkRequired("data", data).map { it.toImmutable() }, + checkRequired("hasMore", hasMore), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): HoldListPageResponse = apply { + if (validated) { + return@apply + } + + data().forEach { it.validate() } + hasMore() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + (data.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (hasMore.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is HoldListPageResponse && + data == other.data && + hasMore == other.hasMore && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(data, hasMore, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "HoldListPageResponse{data=$data, hasMore=$hasMore, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListParams.kt new file mode 100644 index 00000000..50ff2995 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldListParams.kt @@ -0,0 +1,483 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonCreator +import com.lithic.api.core.Enum +import com.lithic.api.core.JsonField +import com.lithic.api.core.Params +import com.lithic.api.core.http.Headers +import com.lithic.api.core.http.QueryParams +import com.lithic.api.errors.LithicInvalidDataException +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** List holds for a financial account. */ +class HoldListParams +private constructor( + private val financialAccountToken: String?, + private val begin: OffsetDateTime?, + private val end: OffsetDateTime?, + private val endingBefore: String?, + private val pageSize: Long?, + private val startingAfter: String?, + private val status: HoldStatus?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun financialAccountToken(): Optional = Optional.ofNullable(financialAccountToken) + + /** + * Date string in RFC 3339 format. Only entries created after the specified time will be + * included. UTC time zone. + */ + fun begin(): Optional = Optional.ofNullable(begin) + + /** + * Date string in RFC 3339 format. Only entries created before the specified time will be + * included. UTC time zone. + */ + fun end(): Optional = Optional.ofNullable(end) + + /** + * A cursor representing an item's token before which a page of results should end. Used to + * retrieve the previous page of results before this item. + */ + fun endingBefore(): Optional = Optional.ofNullable(endingBefore) + + /** Page size (for pagination). */ + fun pageSize(): Optional = Optional.ofNullable(pageSize) + + /** + * A cursor representing an item's token after which a page of results should begin. Used to + * retrieve the next page of results after this item. + */ + fun startingAfter(): Optional = Optional.ofNullable(startingAfter) + + /** Hold status to filter by. */ + fun status(): Optional = Optional.ofNullable(status) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): HoldListParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [HoldListParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [HoldListParams]. */ + class Builder internal constructor() { + + private var financialAccountToken: String? = null + private var begin: OffsetDateTime? = null + private var end: OffsetDateTime? = null + private var endingBefore: String? = null + private var pageSize: Long? = null + private var startingAfter: String? = null + private var status: HoldStatus? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(holdListParams: HoldListParams) = apply { + financialAccountToken = holdListParams.financialAccountToken + begin = holdListParams.begin + end = holdListParams.end + endingBefore = holdListParams.endingBefore + pageSize = holdListParams.pageSize + startingAfter = holdListParams.startingAfter + status = holdListParams.status + additionalHeaders = holdListParams.additionalHeaders.toBuilder() + additionalQueryParams = holdListParams.additionalQueryParams.toBuilder() + } + + fun financialAccountToken(financialAccountToken: String?) = apply { + this.financialAccountToken = financialAccountToken + } + + /** + * Alias for calling [Builder.financialAccountToken] with + * `financialAccountToken.orElse(null)`. + */ + fun financialAccountToken(financialAccountToken: Optional) = + financialAccountToken(financialAccountToken.getOrNull()) + + /** + * Date string in RFC 3339 format. Only entries created after the specified time will be + * included. UTC time zone. + */ + fun begin(begin: OffsetDateTime?) = apply { this.begin = begin } + + /** Alias for calling [Builder.begin] with `begin.orElse(null)`. */ + fun begin(begin: Optional) = begin(begin.getOrNull()) + + /** + * Date string in RFC 3339 format. Only entries created before the specified time will be + * included. UTC time zone. + */ + fun end(end: OffsetDateTime?) = apply { this.end = end } + + /** Alias for calling [Builder.end] with `end.orElse(null)`. */ + fun end(end: Optional) = end(end.getOrNull()) + + /** + * A cursor representing an item's token before which a page of results should end. Used to + * retrieve the previous page of results before this item. + */ + fun endingBefore(endingBefore: String?) = apply { this.endingBefore = endingBefore } + + /** Alias for calling [Builder.endingBefore] with `endingBefore.orElse(null)`. */ + fun endingBefore(endingBefore: Optional) = endingBefore(endingBefore.getOrNull()) + + /** Page size (for pagination). */ + fun pageSize(pageSize: Long?) = apply { this.pageSize = pageSize } + + /** + * Alias for [Builder.pageSize]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun pageSize(pageSize: Long) = pageSize(pageSize as Long?) + + /** Alias for calling [Builder.pageSize] with `pageSize.orElse(null)`. */ + fun pageSize(pageSize: Optional) = pageSize(pageSize.getOrNull()) + + /** + * A cursor representing an item's token after which a page of results should begin. Used to + * retrieve the next page of results after this item. + */ + fun startingAfter(startingAfter: String?) = apply { this.startingAfter = startingAfter } + + /** Alias for calling [Builder.startingAfter] with `startingAfter.orElse(null)`. */ + fun startingAfter(startingAfter: Optional) = + startingAfter(startingAfter.getOrNull()) + + /** Hold status to filter by. */ + fun status(status: HoldStatus?) = apply { this.status = status } + + /** Alias for calling [Builder.status] with `status.orElse(null)`. */ + fun status(status: Optional) = status(status.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [HoldListParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): HoldListParams = + HoldListParams( + financialAccountToken, + begin, + end, + endingBefore, + pageSize, + startingAfter, + status, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> financialAccountToken ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + begin?.let { put("begin", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(it)) } + end?.let { put("end", DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(it)) } + endingBefore?.let { put("ending_before", it) } + pageSize?.let { put("page_size", it.toString()) } + startingAfter?.let { put("starting_after", it) } + status?.let { put("status", it.toString()) } + putAll(additionalQueryParams) + } + .build() + + /** Hold status to filter by. */ + class HoldStatus @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 PENDING = of("PENDING") + + @JvmField val SETTLED = of("SETTLED") + + @JvmField val EXPIRED = of("EXPIRED") + + @JvmField val VOIDED = of("VOIDED") + + @JvmStatic fun of(value: String) = HoldStatus(JsonField.of(value)) + } + + /** An enum containing [HoldStatus]'s known values. */ + enum class Known { + PENDING, + SETTLED, + EXPIRED, + VOIDED, + } + + /** + * An enum containing [HoldStatus]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [HoldStatus] 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 { + PENDING, + SETTLED, + EXPIRED, + VOIDED, + /** + * An enum member indicating that [HoldStatus] 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) { + PENDING -> Value.PENDING + SETTLED -> Value.SETTLED + EXPIRED -> Value.EXPIRED + VOIDED -> Value.VOIDED + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + PENDING -> Known.PENDING + SETTLED -> Known.SETTLED + EXPIRED -> Known.EXPIRED + VOIDED -> Known.VOIDED + else -> throw LithicInvalidDataException("Unknown HoldStatus: $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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + fun validate(): HoldStatus = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 HoldStatus && 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 HoldListParams && + financialAccountToken == other.financialAccountToken && + begin == other.begin && + end == other.end && + endingBefore == other.endingBefore && + pageSize == other.pageSize && + startingAfter == other.startingAfter && + status == other.status && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + financialAccountToken, + begin, + end, + endingBefore, + pageSize, + startingAfter, + status, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "HoldListParams{financialAccountToken=$financialAccountToken, begin=$begin, end=$end, endingBefore=$endingBefore, pageSize=$pageSize, startingAfter=$startingAfter, status=$status, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldRetrieveParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldRetrieveParams.kt new file mode 100644 index 00000000..abd5a906 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldRetrieveParams.kt @@ -0,0 +1,189 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.lithic.api.core.Params +import com.lithic.api.core.http.Headers +import com.lithic.api.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Get hold by token. */ +class HoldRetrieveParams +private constructor( + private val holdToken: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun holdToken(): Optional = Optional.ofNullable(holdToken) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): HoldRetrieveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [HoldRetrieveParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [HoldRetrieveParams]. */ + class Builder internal constructor() { + + private var holdToken: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(holdRetrieveParams: HoldRetrieveParams) = apply { + holdToken = holdRetrieveParams.holdToken + additionalHeaders = holdRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = holdRetrieveParams.additionalQueryParams.toBuilder() + } + + fun holdToken(holdToken: String?) = apply { this.holdToken = holdToken } + + /** Alias for calling [Builder.holdToken] with `holdToken.orElse(null)`. */ + fun holdToken(holdToken: Optional) = holdToken(holdToken.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [HoldRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): HoldRetrieveParams = + HoldRetrieveParams(holdToken, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> holdToken ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is HoldRetrieveParams && + holdToken == other.holdToken && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(holdToken, additionalHeaders, additionalQueryParams) + + override fun toString() = + "HoldRetrieveParams{holdToken=$holdToken, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldVoidParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldVoidParams.kt new file mode 100644 index 00000000..656c3ec4 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/HoldVoidParams.kt @@ -0,0 +1,419 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.Params +import com.lithic.api.core.http.Headers +import com.lithic.api.core.http.QueryParams +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Void an active hold. This returns the held funds from pending back to available balance. Only + * holds in PENDING status can be voided. + */ +class HoldVoidParams +private constructor( + private val holdToken: String?, + private val body: VoidHoldRequest, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun holdToken(): Optional = Optional.ofNullable(holdToken) + + /** + * Reason for voiding the hold + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun memo(): Optional = body.memo() + + /** + * Returns the raw JSON value of [memo]. + * + * Unlike [memo], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _memo(): JsonField = body._memo() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): HoldVoidParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [HoldVoidParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [HoldVoidParams]. */ + class Builder internal constructor() { + + private var holdToken: String? = null + private var body: VoidHoldRequest.Builder = VoidHoldRequest.builder() + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(holdVoidParams: HoldVoidParams) = apply { + holdToken = holdVoidParams.holdToken + body = holdVoidParams.body.toBuilder() + additionalHeaders = holdVoidParams.additionalHeaders.toBuilder() + additionalQueryParams = holdVoidParams.additionalQueryParams.toBuilder() + } + + fun holdToken(holdToken: String?) = apply { this.holdToken = holdToken } + + /** Alias for calling [Builder.holdToken] with `holdToken.orElse(null)`. */ + fun holdToken(holdToken: Optional) = holdToken(holdToken.getOrNull()) + + /** + * Sets the entire request body. + * + * This is generally only useful if you are already constructing the body separately. + * Otherwise, it's more convenient to use the top-level setters instead: + * - [memo] + */ + fun body(body: VoidHoldRequest) = apply { this.body = body.toBuilder() } + + /** Reason for voiding the hold */ + fun memo(memo: String?) = apply { body.memo(memo) } + + /** Alias for calling [Builder.memo] with `memo.orElse(null)`. */ + fun memo(memo: Optional) = memo(memo.getOrNull()) + + /** + * Sets [Builder.memo] to an arbitrary JSON value. + * + * You should usually call [Builder.memo] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun memo(memo: JsonField) = apply { body.memo(memo) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [HoldVoidParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): HoldVoidParams = + HoldVoidParams( + holdToken, + body.build(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): VoidHoldRequest = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> holdToken ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + /** Request to void an active hold */ + class VoidHoldRequest + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val memo: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("memo") @ExcludeMissing memo: JsonField = JsonMissing.of() + ) : this(memo, mutableMapOf()) + + /** + * Reason for voiding the hold + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun memo(): Optional = memo.getOptional("memo") + + /** + * Returns the raw JSON value of [memo]. + * + * Unlike [memo], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("memo") @ExcludeMissing fun _memo(): JsonField = memo + + @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 [VoidHoldRequest]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [VoidHoldRequest]. */ + class Builder internal constructor() { + + private var memo: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(voidHoldRequest: VoidHoldRequest) = apply { + memo = voidHoldRequest.memo + additionalProperties = voidHoldRequest.additionalProperties.toMutableMap() + } + + /** Reason for voiding the hold */ + fun memo(memo: String?) = memo(JsonField.ofNullable(memo)) + + /** Alias for calling [Builder.memo] with `memo.orElse(null)`. */ + fun memo(memo: Optional) = memo(memo.getOrNull()) + + /** + * Sets [Builder.memo] to an arbitrary JSON value. + * + * You should usually call [Builder.memo] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun memo(memo: JsonField) = apply { this.memo = memo } + + 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 [VoidHoldRequest]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): VoidHoldRequest = + VoidHoldRequest(memo, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): VoidHoldRequest = apply { + if (validated) { + return@apply + } + + memo() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 (memo.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is VoidHoldRequest && + memo == other.memo && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(memo, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "VoidHoldRequest{memo=$memo, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is HoldVoidParams && + holdToken == other.holdToken && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(holdToken, body, additionalHeaders, additionalQueryParams) + + override fun toString() = + "HoldVoidParams{holdToken=$holdToken, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/InstanceFinancialAccountType.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/InstanceFinancialAccountType.kt index 09dcc011..25988529 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/InstanceFinancialAccountType.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/InstanceFinancialAccountType.kt @@ -43,6 +43,8 @@ private constructor(private val value: JsonField) : Enum { @JvmField val PROGRAM_BANK_ACCOUNTS_PAYABLE = of("PROGRAM_BANK_ACCOUNTS_PAYABLE") + @JvmField val EARLY_DIRECT_DEPOSIT_FLOAT = of("EARLY_DIRECT_DEPOSIT_FLOAT") + @JvmStatic fun of(value: String) = InstanceFinancialAccountType(JsonField.of(value)) } @@ -58,6 +60,7 @@ private constructor(private val value: JsonField) : Enum { PROGRAM_RECEIVABLES, COLLECTION, PROGRAM_BANK_ACCOUNTS_PAYABLE, + EARLY_DIRECT_DEPOSIT_FLOAT, } /** @@ -82,6 +85,7 @@ private constructor(private val value: JsonField) : Enum { PROGRAM_RECEIVABLES, COLLECTION, PROGRAM_BANK_ACCOUNTS_PAYABLE, + EARLY_DIRECT_DEPOSIT_FLOAT, /** * An enum member indicating that [InstanceFinancialAccountType] was instantiated with an * unknown value. @@ -108,6 +112,7 @@ private constructor(private val value: JsonField) : Enum { PROGRAM_RECEIVABLES -> Value.PROGRAM_RECEIVABLES COLLECTION -> Value.COLLECTION PROGRAM_BANK_ACCOUNTS_PAYABLE -> Value.PROGRAM_BANK_ACCOUNTS_PAYABLE + EARLY_DIRECT_DEPOSIT_FLOAT -> Value.EARLY_DIRECT_DEPOSIT_FLOAT else -> Value._UNKNOWN } @@ -131,6 +136,7 @@ private constructor(private val value: JsonField) : Enum { PROGRAM_RECEIVABLES -> Known.PROGRAM_RECEIVABLES COLLECTION -> Known.COLLECTION PROGRAM_BANK_ACCOUNTS_PAYABLE -> Known.PROGRAM_BANK_ACCOUNTS_PAYABLE + EARLY_DIRECT_DEPOSIT_FLOAT -> Known.EARLY_DIRECT_DEPOSIT_FLOAT else -> throw LithicInvalidDataException("Unknown InstanceFinancialAccountType: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt index f1079776..558ed9ec 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt @@ -1120,6 +1120,8 @@ private constructor( @JvmField val MANAGEMENT_DISBURSEMENT = of("MANAGEMENT_DISBURSEMENT") + @JvmField val HOLD = of("HOLD") + @JvmField val PROGRAM_FUNDING = of("PROGRAM_FUNDING") @JvmStatic fun of(value: String) = TransactionCategory(JsonField.of(value)) @@ -1146,6 +1148,7 @@ private constructor( MANAGEMENT_FEE, MANAGEMENT_REWARD, MANAGEMENT_DISBURSEMENT, + HOLD, PROGRAM_FUNDING, } @@ -1178,6 +1181,7 @@ private constructor( MANAGEMENT_FEE, MANAGEMENT_REWARD, MANAGEMENT_DISBURSEMENT, + HOLD, PROGRAM_FUNDING, /** * An enum member indicating that [TransactionCategory] was instantiated with an unknown @@ -1214,6 +1218,7 @@ private constructor( MANAGEMENT_FEE -> Value.MANAGEMENT_FEE MANAGEMENT_REWARD -> Value.MANAGEMENT_REWARD MANAGEMENT_DISBURSEMENT -> Value.MANAGEMENT_DISBURSEMENT + HOLD -> Value.HOLD PROGRAM_FUNDING -> Value.PROGRAM_FUNDING else -> Value._UNKNOWN } @@ -1248,6 +1253,7 @@ private constructor( MANAGEMENT_FEE -> Known.MANAGEMENT_FEE MANAGEMENT_REWARD -> Known.MANAGEMENT_REWARD MANAGEMENT_DISBURSEMENT -> Known.MANAGEMENT_DISBURSEMENT + HOLD -> Known.HOLD PROGRAM_FUNDING -> Known.PROGRAM_FUNDING else -> throw LithicInvalidDataException("Unknown TransactionCategory: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt index e06eb4e3..c9207b7d 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt @@ -864,6 +864,8 @@ private constructor( @JvmField val MANAGEMENT_DISBURSEMENT = of("MANAGEMENT_DISBURSEMENT") + @JvmField val HOLD = of("HOLD") + @JvmField val PROGRAM_FUNDING = of("PROGRAM_FUNDING") @JvmStatic fun of(value: String) = TransactionCategory(JsonField.of(value)) @@ -890,6 +892,7 @@ private constructor( MANAGEMENT_FEE, MANAGEMENT_REWARD, MANAGEMENT_DISBURSEMENT, + HOLD, PROGRAM_FUNDING, } @@ -924,6 +927,7 @@ private constructor( MANAGEMENT_FEE, MANAGEMENT_REWARD, MANAGEMENT_DISBURSEMENT, + HOLD, PROGRAM_FUNDING, /** * An enum member indicating that [TransactionCategory] was instantiated with an @@ -960,6 +964,7 @@ private constructor( MANAGEMENT_FEE -> Value.MANAGEMENT_FEE MANAGEMENT_REWARD -> Value.MANAGEMENT_REWARD MANAGEMENT_DISBURSEMENT -> Value.MANAGEMENT_DISBURSEMENT + HOLD -> Value.HOLD PROGRAM_FUNDING -> Value.PROGRAM_FUNDING else -> Value._UNKNOWN } @@ -994,6 +999,7 @@ private constructor( MANAGEMENT_FEE -> Known.MANAGEMENT_FEE MANAGEMENT_REWARD -> Known.MANAGEMENT_REWARD MANAGEMENT_DISBURSEMENT -> Known.MANAGEMENT_DISBURSEMENT + HOLD -> Known.HOLD PROGRAM_FUNDING -> Known.PROGRAM_FUNDING else -> throw LithicInvalidDataException("Unknown TransactionCategory: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/HoldServiceAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/HoldServiceAsync.kt new file mode 100644 index 00000000..12f8a8bf --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/HoldServiceAsync.kt @@ -0,0 +1,330 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.async + +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.models.Hold +import com.lithic.api.models.HoldCreateParams +import com.lithic.api.models.HoldListPageAsync +import com.lithic.api.models.HoldListParams +import com.lithic.api.models.HoldRetrieveParams +import com.lithic.api.models.HoldVoidParams +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +interface HoldServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): HoldServiceAsync + + /** + * Create a hold on a financial account. Holds reserve funds by moving them from available to + * pending balance. They can be resolved via settlement (linked to a payment or book transfer), + * voiding, or expiration. + */ + fun create(financialAccountToken: String, params: HoldCreateParams): CompletableFuture = + create(financialAccountToken, params, RequestOptions.none()) + + /** @see create */ + fun create( + financialAccountToken: String, + params: HoldCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + create( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see create */ + fun create(params: HoldCreateParams): CompletableFuture = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: HoldCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** Get hold by token. */ + fun retrieve(holdToken: String): CompletableFuture = + retrieve(holdToken, HoldRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + holdToken: String, + params: HoldRetrieveParams = HoldRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + retrieve(params.toBuilder().holdToken(holdToken).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + holdToken: String, + params: HoldRetrieveParams = HoldRetrieveParams.none(), + ): CompletableFuture = retrieve(holdToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: HoldRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see retrieve */ + fun retrieve(params: HoldRetrieveParams): CompletableFuture = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve(holdToken: String, requestOptions: RequestOptions): CompletableFuture = + retrieve(holdToken, HoldRetrieveParams.none(), requestOptions) + + /** List holds for a financial account. */ + fun list(financialAccountToken: String): CompletableFuture = + list(financialAccountToken, HoldListParams.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + params: HoldListParams = HoldListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + list( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see list */ + fun list( + financialAccountToken: String, + params: HoldListParams = HoldListParams.none(), + ): CompletableFuture = + list(financialAccountToken, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: HoldListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see list */ + fun list(params: HoldListParams): CompletableFuture = + list(params, RequestOptions.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + requestOptions: RequestOptions, + ): CompletableFuture = + list(financialAccountToken, HoldListParams.none(), requestOptions) + + /** + * Void an active hold. This returns the held funds from pending back to available balance. Only + * holds in PENDING status can be voided. + */ + fun void_(holdToken: String): CompletableFuture = void_(holdToken, HoldVoidParams.none()) + + /** @see void_ */ + fun void_( + holdToken: String, + params: HoldVoidParams = HoldVoidParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + void_(params.toBuilder().holdToken(holdToken).build(), requestOptions) + + /** @see void_ */ + fun void_( + holdToken: String, + params: HoldVoidParams = HoldVoidParams.none(), + ): CompletableFuture = void_(holdToken, params, RequestOptions.none()) + + /** @see void_ */ + fun void_( + params: HoldVoidParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see void_ */ + fun void_(params: HoldVoidParams): CompletableFuture = + void_(params, RequestOptions.none()) + + /** @see void_ */ + fun void_(holdToken: String, requestOptions: RequestOptions): CompletableFuture = + void_(holdToken, HoldVoidParams.none(), requestOptions) + + /** A view of [HoldServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): HoldServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post + * /v1/financial_accounts/{financial_account_token}/holds`, but is otherwise the same as + * [HoldServiceAsync.create]. + */ + fun create( + financialAccountToken: String, + params: HoldCreateParams, + ): CompletableFuture> = + create(financialAccountToken, params, RequestOptions.none()) + + /** @see create */ + fun create( + financialAccountToken: String, + params: HoldCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + create( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see create */ + fun create(params: HoldCreateParams): CompletableFuture> = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: HoldCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** + * Returns a raw HTTP response for `get /v1/holds/{hold_token}`, but is otherwise the same + * as [HoldServiceAsync.retrieve]. + */ + fun retrieve(holdToken: String): CompletableFuture> = + retrieve(holdToken, HoldRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + holdToken: String, + params: HoldRetrieveParams = HoldRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + retrieve(params.toBuilder().holdToken(holdToken).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + holdToken: String, + params: HoldRetrieveParams = HoldRetrieveParams.none(), + ): CompletableFuture> = + retrieve(holdToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: HoldRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see retrieve */ + fun retrieve(params: HoldRetrieveParams): CompletableFuture> = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + holdToken: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + retrieve(holdToken, HoldRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get + * /v1/financial_accounts/{financial_account_token}/holds`, but is otherwise the same as + * [HoldServiceAsync.list]. + */ + fun list( + financialAccountToken: String + ): CompletableFuture> = + list(financialAccountToken, HoldListParams.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + params: HoldListParams = HoldListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + list( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see list */ + fun list( + financialAccountToken: String, + params: HoldListParams = HoldListParams.none(), + ): CompletableFuture> = + list(financialAccountToken, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: HoldListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see list */ + fun list(params: HoldListParams): CompletableFuture> = + list(params, RequestOptions.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + list(financialAccountToken, HoldListParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /v1/holds/{hold_token}/void`, but is otherwise the + * same as [HoldServiceAsync.void_]. + */ + fun void_(holdToken: String): CompletableFuture> = + void_(holdToken, HoldVoidParams.none()) + + /** @see void_ */ + fun void_( + holdToken: String, + params: HoldVoidParams = HoldVoidParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + void_(params.toBuilder().holdToken(holdToken).build(), requestOptions) + + /** @see void_ */ + fun void_( + holdToken: String, + params: HoldVoidParams = HoldVoidParams.none(), + ): CompletableFuture> = + void_(holdToken, params, RequestOptions.none()) + + /** @see void_ */ + fun void_( + params: HoldVoidParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see void_ */ + fun void_(params: HoldVoidParams): CompletableFuture> = + void_(params, RequestOptions.none()) + + /** @see void_ */ + fun void_( + holdToken: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + void_(holdToken, HoldVoidParams.none(), requestOptions) + } +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/HoldServiceAsyncImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/HoldServiceAsyncImpl.kt new file mode 100644 index 00000000..817d09de --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/HoldServiceAsyncImpl.kt @@ -0,0 +1,222 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.async + +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.checkRequired +import com.lithic.api.core.handlers.errorBodyHandler +import com.lithic.api.core.handlers.errorHandler +import com.lithic.api.core.handlers.jsonHandler +import com.lithic.api.core.http.HttpMethod +import com.lithic.api.core.http.HttpRequest +import com.lithic.api.core.http.HttpResponse +import com.lithic.api.core.http.HttpResponse.Handler +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.core.http.json +import com.lithic.api.core.http.parseable +import com.lithic.api.core.prepareAsync +import com.lithic.api.models.Hold +import com.lithic.api.models.HoldCreateParams +import com.lithic.api.models.HoldListPageAsync +import com.lithic.api.models.HoldListPageResponse +import com.lithic.api.models.HoldListParams +import com.lithic.api.models.HoldRetrieveParams +import com.lithic.api.models.HoldVoidParams +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class HoldServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + HoldServiceAsync { + + private val withRawResponse: HoldServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): HoldServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): HoldServiceAsync = + HoldServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun create( + params: HoldCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /v1/financial_accounts/{financial_account_token}/holds + withRawResponse().create(params, requestOptions).thenApply { it.parse() } + + override fun retrieve( + params: HoldRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /v1/holds/{hold_token} + withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() } + + override fun list( + params: HoldListParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /v1/financial_accounts/{financial_account_token}/holds + withRawResponse().list(params, requestOptions).thenApply { it.parse() } + + override fun void_( + params: HoldVoidParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /v1/holds/{hold_token}/void + withRawResponse().void_(params, requestOptions).thenApply { it.parse() } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + HoldServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): HoldServiceAsync.WithRawResponse = + HoldServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: HoldCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("financialAccountToken", params.financialAccountToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "financial_accounts", params._pathParam(0), "holds") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: HoldRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("holdToken", params.holdToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "holds", params._pathParam(0)) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val listHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun list( + params: HoldListParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("financialAccountToken", params.financialAccountToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "financial_accounts", params._pathParam(0), "holds") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { listHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + .let { + HoldListPageAsync.builder() + .service(HoldServiceAsyncImpl(clientOptions)) + .streamHandlerExecutor(clientOptions.streamHandlerExecutor) + .params(params) + .response(it) + .build() + } + } + } + } + + private val voidHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun void_( + params: HoldVoidParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("holdToken", params.holdToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "holds", params._pathParam(0), "void") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { voidHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + } +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/HoldService.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/HoldService.kt new file mode 100644 index 00000000..b62525ce --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/HoldService.kt @@ -0,0 +1,321 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.blocking + +import com.google.errorprone.annotations.MustBeClosed +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.models.Hold +import com.lithic.api.models.HoldCreateParams +import com.lithic.api.models.HoldListPage +import com.lithic.api.models.HoldListParams +import com.lithic.api.models.HoldRetrieveParams +import com.lithic.api.models.HoldVoidParams +import java.util.function.Consumer + +interface HoldService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): HoldService + + /** + * Create a hold on a financial account. Holds reserve funds by moving them from available to + * pending balance. They can be resolved via settlement (linked to a payment or book transfer), + * voiding, or expiration. + */ + fun create(financialAccountToken: String, params: HoldCreateParams): Hold = + create(financialAccountToken, params, RequestOptions.none()) + + /** @see create */ + fun create( + financialAccountToken: String, + params: HoldCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Hold = + create( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see create */ + fun create(params: HoldCreateParams): Hold = create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: HoldCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Hold + + /** Get hold by token. */ + fun retrieve(holdToken: String): Hold = retrieve(holdToken, HoldRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + holdToken: String, + params: HoldRetrieveParams = HoldRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Hold = retrieve(params.toBuilder().holdToken(holdToken).build(), requestOptions) + + /** @see retrieve */ + fun retrieve(holdToken: String, params: HoldRetrieveParams = HoldRetrieveParams.none()): Hold = + retrieve(holdToken, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: HoldRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Hold + + /** @see retrieve */ + fun retrieve(params: HoldRetrieveParams): Hold = retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve(holdToken: String, requestOptions: RequestOptions): Hold = + retrieve(holdToken, HoldRetrieveParams.none(), requestOptions) + + /** List holds for a financial account. */ + fun list(financialAccountToken: String): HoldListPage = + list(financialAccountToken, HoldListParams.none()) + + /** @see list */ + fun list( + financialAccountToken: String, + params: HoldListParams = HoldListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HoldListPage = + list( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see list */ + fun list( + financialAccountToken: String, + params: HoldListParams = HoldListParams.none(), + ): HoldListPage = list(financialAccountToken, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: HoldListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HoldListPage + + /** @see list */ + fun list(params: HoldListParams): HoldListPage = list(params, RequestOptions.none()) + + /** @see list */ + fun list(financialAccountToken: String, requestOptions: RequestOptions): HoldListPage = + list(financialAccountToken, HoldListParams.none(), requestOptions) + + /** + * Void an active hold. This returns the held funds from pending back to available balance. Only + * holds in PENDING status can be voided. + */ + fun void_(holdToken: String): Hold = void_(holdToken, HoldVoidParams.none()) + + /** @see void_ */ + fun void_( + holdToken: String, + params: HoldVoidParams = HoldVoidParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Hold = void_(params.toBuilder().holdToken(holdToken).build(), requestOptions) + + /** @see void_ */ + fun void_(holdToken: String, params: HoldVoidParams = HoldVoidParams.none()): Hold = + void_(holdToken, params, RequestOptions.none()) + + /** @see void_ */ + fun void_(params: HoldVoidParams, requestOptions: RequestOptions = RequestOptions.none()): Hold + + /** @see void_ */ + fun void_(params: HoldVoidParams): Hold = void_(params, RequestOptions.none()) + + /** @see void_ */ + fun void_(holdToken: String, requestOptions: RequestOptions): Hold = + void_(holdToken, HoldVoidParams.none(), requestOptions) + + /** A view of [HoldService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): HoldService.WithRawResponse + + /** + * Returns a raw HTTP response for `post + * /v1/financial_accounts/{financial_account_token}/holds`, but is otherwise the same as + * [HoldService.create]. + */ + @MustBeClosed + fun create(financialAccountToken: String, params: HoldCreateParams): HttpResponseFor = + create(financialAccountToken, params, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create( + financialAccountToken: String, + params: HoldCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see create */ + @MustBeClosed + fun create(params: HoldCreateParams): HttpResponseFor = + create(params, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create( + params: HoldCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** + * Returns a raw HTTP response for `get /v1/holds/{hold_token}`, but is otherwise the same + * as [HoldService.retrieve]. + */ + @MustBeClosed + fun retrieve(holdToken: String): HttpResponseFor = + retrieve(holdToken, HoldRetrieveParams.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + holdToken: String, + params: HoldRetrieveParams = HoldRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().holdToken(holdToken).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + holdToken: String, + params: HoldRetrieveParams = HoldRetrieveParams.none(), + ): HttpResponseFor = retrieve(holdToken, params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: HoldRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve(params: HoldRetrieveParams): HttpResponseFor = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve(holdToken: String, requestOptions: RequestOptions): HttpResponseFor = + retrieve(holdToken, HoldRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get + * /v1/financial_accounts/{financial_account_token}/holds`, but is otherwise the same as + * [HoldService.list]. + */ + @MustBeClosed + fun list(financialAccountToken: String): HttpResponseFor = + list(financialAccountToken, HoldListParams.none()) + + /** @see list */ + @MustBeClosed + fun list( + financialAccountToken: String, + params: HoldListParams = HoldListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + list( + params.toBuilder().financialAccountToken(financialAccountToken).build(), + requestOptions, + ) + + /** @see list */ + @MustBeClosed + fun list( + financialAccountToken: String, + params: HoldListParams = HoldListParams.none(), + ): HttpResponseFor = + list(financialAccountToken, params, RequestOptions.none()) + + /** @see list */ + @MustBeClosed + fun list( + params: HoldListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see list */ + @MustBeClosed + fun list(params: HoldListParams): HttpResponseFor = + list(params, RequestOptions.none()) + + /** @see list */ + @MustBeClosed + fun list( + financialAccountToken: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + list(financialAccountToken, HoldListParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /v1/holds/{hold_token}/void`, but is otherwise the + * same as [HoldService.void_]. + */ + @MustBeClosed + fun void_(holdToken: String): HttpResponseFor = + void_(holdToken, HoldVoidParams.none()) + + /** @see void_ */ + @MustBeClosed + fun void_( + holdToken: String, + params: HoldVoidParams = HoldVoidParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + void_(params.toBuilder().holdToken(holdToken).build(), requestOptions) + + /** @see void_ */ + @MustBeClosed + fun void_( + holdToken: String, + params: HoldVoidParams = HoldVoidParams.none(), + ): HttpResponseFor = void_(holdToken, params, RequestOptions.none()) + + /** @see void_ */ + @MustBeClosed + fun void_( + params: HoldVoidParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see void_ */ + @MustBeClosed + fun void_(params: HoldVoidParams): HttpResponseFor = + void_(params, RequestOptions.none()) + + /** @see void_ */ + @MustBeClosed + fun void_(holdToken: String, requestOptions: RequestOptions): HttpResponseFor = + void_(holdToken, HoldVoidParams.none(), requestOptions) + } +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/HoldServiceImpl.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/HoldServiceImpl.kt new file mode 100644 index 00000000..85328d45 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/HoldServiceImpl.kt @@ -0,0 +1,195 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.blocking + +import com.lithic.api.core.ClientOptions +import com.lithic.api.core.RequestOptions +import com.lithic.api.core.checkRequired +import com.lithic.api.core.handlers.errorBodyHandler +import com.lithic.api.core.handlers.errorHandler +import com.lithic.api.core.handlers.jsonHandler +import com.lithic.api.core.http.HttpMethod +import com.lithic.api.core.http.HttpRequest +import com.lithic.api.core.http.HttpResponse +import com.lithic.api.core.http.HttpResponse.Handler +import com.lithic.api.core.http.HttpResponseFor +import com.lithic.api.core.http.json +import com.lithic.api.core.http.parseable +import com.lithic.api.core.prepare +import com.lithic.api.models.Hold +import com.lithic.api.models.HoldCreateParams +import com.lithic.api.models.HoldListPage +import com.lithic.api.models.HoldListPageResponse +import com.lithic.api.models.HoldListParams +import com.lithic.api.models.HoldRetrieveParams +import com.lithic.api.models.HoldVoidParams +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class HoldServiceImpl internal constructor(private val clientOptions: ClientOptions) : HoldService { + + private val withRawResponse: HoldService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): HoldService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): HoldService = + HoldServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun create(params: HoldCreateParams, requestOptions: RequestOptions): Hold = + // post /v1/financial_accounts/{financial_account_token}/holds + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve(params: HoldRetrieveParams, requestOptions: RequestOptions): Hold = + // get /v1/holds/{hold_token} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun list(params: HoldListParams, requestOptions: RequestOptions): HoldListPage = + // get /v1/financial_accounts/{financial_account_token}/holds + withRawResponse().list(params, requestOptions).parse() + + override fun void_(params: HoldVoidParams, requestOptions: RequestOptions): Hold = + // post /v1/holds/{hold_token}/void + withRawResponse().void_(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + HoldService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): HoldService.WithRawResponse = + HoldServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: HoldCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("financialAccountToken", params.financialAccountToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "financial_accounts", params._pathParam(0), "holds") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: HoldRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("holdToken", params.holdToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "holds", params._pathParam(0)) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val listHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun list( + params: HoldListParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("financialAccountToken", params.financialAccountToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "financial_accounts", params._pathParam(0), "holds") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + .let { + HoldListPage.builder() + .service(HoldServiceImpl(clientOptions)) + .params(params) + .response(it) + .build() + } + } + } + + private val voidHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun void_( + params: HoldVoidParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("holdToken", params.holdToken().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("v1", "holds", params._pathParam(0), "void") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { voidHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListResponseTest.kt index 13e75cc7..1a1aa89b 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListResponseTest.kt @@ -51,6 +51,7 @@ internal class AccountActivityListResponseTest { assertThat(accountActivityListResponse.payment()).isEmpty assertThat(accountActivityListResponse.externalPayment()).isEmpty assertThat(accountActivityListResponse.managementOperation()).isEmpty + assertThat(accountActivityListResponse.hold()).isEmpty } @Test @@ -157,6 +158,7 @@ internal class AccountActivityListResponseTest { assertThat(accountActivityListResponse.payment()).isEmpty assertThat(accountActivityListResponse.externalPayment()).isEmpty assertThat(accountActivityListResponse.managementOperation()).isEmpty + assertThat(accountActivityListResponse.hold()).isEmpty } @Test @@ -453,6 +455,7 @@ internal class AccountActivityListResponseTest { assertThat(accountActivityListResponse.payment()).isEmpty assertThat(accountActivityListResponse.externalPayment()).isEmpty assertThat(accountActivityListResponse.managementOperation()).isEmpty + assertThat(accountActivityListResponse.hold()).isEmpty } @Test @@ -774,6 +777,7 @@ internal class AccountActivityListResponseTest { assertThat(accountActivityListResponse.payment()).contains(payment) assertThat(accountActivityListResponse.externalPayment()).isEmpty assertThat(accountActivityListResponse.managementOperation()).isEmpty + assertThat(accountActivityListResponse.hold()).isEmpty } @Test @@ -898,6 +902,7 @@ internal class AccountActivityListResponseTest { assertThat(accountActivityListResponse.payment()).isEmpty assertThat(accountActivityListResponse.externalPayment()).contains(externalPayment) assertThat(accountActivityListResponse.managementOperation()).isEmpty + assertThat(accountActivityListResponse.hold()).isEmpty } @Test @@ -1014,6 +1019,7 @@ internal class AccountActivityListResponseTest { assertThat(accountActivityListResponse.payment()).isEmpty assertThat(accountActivityListResponse.externalPayment()).isEmpty assertThat(accountActivityListResponse.managementOperation()).contains(managementOperation) + assertThat(accountActivityListResponse.hold()).isEmpty } @Test @@ -1088,6 +1094,87 @@ internal class AccountActivityListResponseTest { assertThat(roundtrippedAccountActivityListResponse).isEqualTo(accountActivityListResponse) } + @Test + fun ofHold() { + val hold = + Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Hold.HoldStatus.PENDING) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .addEvent( + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + ) + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .family(Hold.Family.HOLD) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .result(Hold.TransactionResult.APPROVED) + .userDefinedId("user_defined_id") + .build() + + val accountActivityListResponse = AccountActivityListResponse.ofHold(hold) + + assertThat(accountActivityListResponse.internal_()).isEmpty + assertThat(accountActivityListResponse.transfer()).isEmpty + assertThat(accountActivityListResponse.card()).isEmpty + assertThat(accountActivityListResponse.payment()).isEmpty + assertThat(accountActivityListResponse.externalPayment()).isEmpty + assertThat(accountActivityListResponse.managementOperation()).isEmpty + assertThat(accountActivityListResponse.hold()).contains(hold) + } + + @Test + fun ofHoldRoundtrip() { + val jsonMapper = jsonMapper() + val accountActivityListResponse = + AccountActivityListResponse.ofHold( + Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Hold.HoldStatus.PENDING) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .addEvent( + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + ) + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .family(Hold.Family.HOLD) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .result(Hold.TransactionResult.APPROVED) + .userDefinedId("user_defined_id") + .build() + ) + + val roundtrippedAccountActivityListResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(accountActivityListResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedAccountActivityListResponse).isEqualTo(accountActivityListResponse) + } + enum class IncompatibleJsonShapeTestCase(val value: JsonValue) { BOOLEAN(JsonValue.from(false)), STRING(JsonValue.from("invalid")), diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponseTest.kt index 367dcbcd..76fb11a2 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityRetrieveTransactionResponseTest.kt @@ -66,6 +66,7 @@ internal class AccountActivityRetrieveTransactionResponseTest { assertThat(accountActivityRetrieveTransactionResponse.payment()).isEmpty assertThat(accountActivityRetrieveTransactionResponse.externalPayment()).isEmpty assertThat(accountActivityRetrieveTransactionResponse.managementOperation()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.hold()).isEmpty } @Test @@ -183,6 +184,7 @@ internal class AccountActivityRetrieveTransactionResponseTest { assertThat(accountActivityRetrieveTransactionResponse.payment()).isEmpty assertThat(accountActivityRetrieveTransactionResponse.externalPayment()).isEmpty assertThat(accountActivityRetrieveTransactionResponse.managementOperation()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.hold()).isEmpty } @Test @@ -481,6 +483,7 @@ internal class AccountActivityRetrieveTransactionResponseTest { assertThat(accountActivityRetrieveTransactionResponse.payment()).isEmpty assertThat(accountActivityRetrieveTransactionResponse.externalPayment()).isEmpty assertThat(accountActivityRetrieveTransactionResponse.managementOperation()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.hold()).isEmpty } @Test @@ -804,6 +807,7 @@ internal class AccountActivityRetrieveTransactionResponseTest { assertThat(accountActivityRetrieveTransactionResponse.payment()).contains(payment) assertThat(accountActivityRetrieveTransactionResponse.externalPayment()).isEmpty assertThat(accountActivityRetrieveTransactionResponse.managementOperation()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.hold()).isEmpty } @Test @@ -930,6 +934,7 @@ internal class AccountActivityRetrieveTransactionResponseTest { assertThat(accountActivityRetrieveTransactionResponse.externalPayment()) .contains(externalPayment) assertThat(accountActivityRetrieveTransactionResponse.managementOperation()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.hold()).isEmpty } @Test @@ -1048,6 +1053,7 @@ internal class AccountActivityRetrieveTransactionResponseTest { assertThat(accountActivityRetrieveTransactionResponse.externalPayment()).isEmpty assertThat(accountActivityRetrieveTransactionResponse.managementOperation()) .contains(managementOperation) + assertThat(accountActivityRetrieveTransactionResponse.hold()).isEmpty } @Test @@ -1123,6 +1129,89 @@ internal class AccountActivityRetrieveTransactionResponseTest { .isEqualTo(accountActivityRetrieveTransactionResponse) } + @Test + fun ofHold() { + val hold = + Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Hold.HoldStatus.PENDING) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .addEvent( + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + ) + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .family(Hold.Family.HOLD) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .result(Hold.TransactionResult.APPROVED) + .userDefinedId("user_defined_id") + .build() + + val accountActivityRetrieveTransactionResponse = + AccountActivityRetrieveTransactionResponse.ofHold(hold) + + assertThat(accountActivityRetrieveTransactionResponse.internal_()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.transfer()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.card()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.payment()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.externalPayment()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.managementOperation()).isEmpty + assertThat(accountActivityRetrieveTransactionResponse.hold()).contains(hold) + } + + @Test + fun ofHoldRoundtrip() { + val jsonMapper = jsonMapper() + val accountActivityRetrieveTransactionResponse = + AccountActivityRetrieveTransactionResponse.ofHold( + Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Hold.HoldStatus.PENDING) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .addEvent( + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + ) + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .family(Hold.Family.HOLD) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .result(Hold.TransactionResult.APPROVED) + .userDefinedId("user_defined_id") + .build() + ) + + val roundtrippedAccountActivityRetrieveTransactionResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(accountActivityRetrieveTransactionResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedAccountActivityRetrieveTransactionResponse) + .isEqualTo(accountActivityRetrieveTransactionResponse) + } + enum class IncompatibleJsonShapeTestCase(val value: JsonValue) { BOOLEAN(JsonValue.from(false)), STRING(JsonValue.from("invalid")), diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldCreateParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldCreateParamsTest.kt new file mode 100644 index 00000000..a809eb76 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldCreateParamsTest.kt @@ -0,0 +1,70 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class HoldCreateParamsTest { + + @Test + fun create() { + HoldCreateParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(1L) + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .memo("memo") + .userDefinedId("user_defined_id") + .build() + } + + @Test + fun pathParams() { + val params = + HoldCreateParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(1L) + .build() + + assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun body() { + val params = + HoldCreateParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(1L) + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .memo("memo") + .userDefinedId("user_defined_id") + .build() + + val body = params._body() + + assertThat(body.amount()).isEqualTo(1L) + assertThat(body.token()).contains("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(body.expirationDatetime()) + .contains(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(body.memo()).contains("memo") + assertThat(body.userDefinedId()).contains("user_defined_id") + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + HoldCreateParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(1L) + .build() + + val body = params._body() + + assertThat(body.amount()).isEqualTo(1L) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldEventTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldEventTest.kt new file mode 100644 index 00000000..1754a1f7 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldEventTest.kt @@ -0,0 +1,61 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class HoldEventTest { + + @Test + fun create() { + val holdEvent = + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + + assertThat(holdEvent.token()).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(holdEvent.amount()).isEqualTo(0L) + assertThat(holdEvent.created()).isEqualTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(holdEvent.detailedResults()).containsExactly(HoldEvent.DetailedResults.APPROVED) + assertThat(holdEvent.memo()).contains("memo") + assertThat(holdEvent.result()).isEqualTo(HoldEvent.TransactionResult.APPROVED) + assertThat(holdEvent.settlingTransactionToken()) + .contains("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(holdEvent.type()).isEqualTo(HoldEvent.HoldEventType.HOLD_INITIATED) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val holdEvent = + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + + val roundtrippedHoldEvent = + jsonMapper.readValue( + jsonMapper.writeValueAsString(holdEvent), + jacksonTypeRef(), + ) + + assertThat(roundtrippedHoldEvent).isEqualTo(holdEvent) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldListPageResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldListPageResponseTest.kt new file mode 100644 index 00000000..53a95f53 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldListPageResponseTest.kt @@ -0,0 +1,121 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class HoldListPageResponseTest { + + @Test + fun create() { + val holdListPageResponse = + HoldListPageResponse.builder() + .addData( + Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Hold.HoldStatus.PENDING) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .addEvent( + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + ) + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .family(Hold.Family.HOLD) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .result(Hold.TransactionResult.APPROVED) + .userDefinedId("user_defined_id") + .build() + ) + .hasMore(true) + .build() + + assertThat(holdListPageResponse.data()) + .containsExactly( + Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Hold.HoldStatus.PENDING) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .addEvent( + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + ) + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .family(Hold.Family.HOLD) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .result(Hold.TransactionResult.APPROVED) + .userDefinedId("user_defined_id") + .build() + ) + assertThat(holdListPageResponse.hasMore()).isEqualTo(true) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val holdListPageResponse = + HoldListPageResponse.builder() + .addData( + Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Hold.HoldStatus.PENDING) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .addEvent( + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + ) + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .family(Hold.Family.HOLD) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .result(Hold.TransactionResult.APPROVED) + .userDefinedId("user_defined_id") + .build() + ) + .hasMore(true) + .build() + + val roundtrippedHoldListPageResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(holdListPageResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedHoldListPageResponse).isEqualTo(holdListPageResponse) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldListParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldListParamsTest.kt new file mode 100644 index 00000000..692aa594 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldListParamsTest.kt @@ -0,0 +1,76 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.lithic.api.core.http.QueryParams +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class HoldListParamsTest { + + @Test + fun create() { + HoldListParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .begin(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .end(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .endingBefore("ending_before") + .pageSize(1L) + .startingAfter("starting_after") + .status(HoldListParams.HoldStatus.PENDING) + .build() + } + + @Test + fun pathParams() { + val params = + HoldListParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + + assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = + HoldListParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .begin(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .end(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .endingBefore("ending_before") + .pageSize(1L) + .startingAfter("starting_after") + .status(HoldListParams.HoldStatus.PENDING) + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder() + .put("begin", "2019-12-27T18:11:19.117Z") + .put("end", "2019-12-27T18:11:19.117Z") + .put("ending_before", "ending_before") + .put("page_size", "1") + .put("starting_after", "starting_after") + .put("status", "PENDING") + .build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = + HoldListParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldRetrieveParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldRetrieveParamsTest.kt new file mode 100644 index 00000000..1a7cdadc --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldRetrieveParamsTest.kt @@ -0,0 +1,24 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class HoldRetrieveParamsTest { + + @Test + fun create() { + HoldRetrieveParams.builder().holdToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() + } + + @Test + fun pathParams() { + val params = + HoldRetrieveParams.builder().holdToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() + + assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldTest.kt new file mode 100644 index 00000000..562d7ba0 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldTest.kt @@ -0,0 +1,105 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import java.time.OffsetDateTime +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class HoldTest { + + @Test + fun create() { + val hold = + Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Hold.HoldStatus.PENDING) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .addEvent( + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + ) + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .family(Hold.Family.HOLD) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .result(Hold.TransactionResult.APPROVED) + .userDefinedId("user_defined_id") + .build() + + assertThat(hold.token()).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(hold.created()).isEqualTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(hold.status()).isEqualTo(Hold.HoldStatus.PENDING) + assertThat(hold.updated()).isEqualTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(hold.currency()).contains("currency") + assertThat(hold.events().getOrNull()) + .containsExactly( + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + ) + assertThat(hold.expirationDatetime()) + .contains(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(hold.family()).contains(Hold.Family.HOLD) + assertThat(hold.financialAccountToken()).contains("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(hold.pendingAmount()).contains(0L) + assertThat(hold.result()).contains(Hold.TransactionResult.APPROVED) + assertThat(hold.userDefinedId()).contains("user_defined_id") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val hold = + Hold.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Hold.HoldStatus.PENDING) + .updated(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .currency("currency") + .addEvent( + HoldEvent.builder() + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(0L) + .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .addDetailedResult(HoldEvent.DetailedResults.APPROVED) + .memo("memo") + .result(HoldEvent.TransactionResult.APPROVED) + .settlingTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .type(HoldEvent.HoldEventType.HOLD_INITIATED) + .build() + ) + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .family(Hold.Family.HOLD) + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .pendingAmount(0L) + .result(Hold.TransactionResult.APPROVED) + .userDefinedId("user_defined_id") + .build() + + val roundtrippedHold = + jsonMapper.readValue(jsonMapper.writeValueAsString(hold), jacksonTypeRef()) + + assertThat(roundtrippedHold).isEqualTo(hold) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldVoidParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldVoidParamsTest.kt new file mode 100644 index 00000000..73ef56f9 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/HoldVoidParamsTest.kt @@ -0,0 +1,48 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class HoldVoidParamsTest { + + @Test + fun create() { + HoldVoidParams.builder() + .holdToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .memo("memo") + .build() + } + + @Test + fun pathParams() { + val params = + HoldVoidParams.builder().holdToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() + + assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun body() { + val params = + HoldVoidParams.builder() + .holdToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .memo("memo") + .build() + + val body = params._body() + + assertThat(body.memo()).contains("memo") + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + HoldVoidParams.builder().holdToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e").build() + + val body = params._body() + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/HoldServiceAsyncTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/HoldServiceAsyncTest.kt new file mode 100644 index 00000000..a9d42e9c --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/HoldServiceAsyncTest.kt @@ -0,0 +1,91 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.async + +import com.lithic.api.TestServerExtension +import com.lithic.api.client.okhttp.LithicOkHttpClientAsync +import com.lithic.api.models.HoldCreateParams +import com.lithic.api.models.HoldVoidParams +import java.time.OffsetDateTime +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class HoldServiceAsyncTest { + + @Test + fun create() { + val client = + LithicOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val holdServiceAsync = client.holds() + + val holdFuture = + holdServiceAsync.create( + HoldCreateParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(1L) + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .memo("memo") + .userDefinedId("user_defined_id") + .build() + ) + + val hold = holdFuture.get() + hold.validate() + } + + @Test + fun retrieve() { + val client = + LithicOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val holdServiceAsync = client.holds() + + val holdFuture = holdServiceAsync.retrieve("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + + val hold = holdFuture.get() + hold.validate() + } + + @Test + fun list() { + val client = + LithicOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val holdServiceAsync = client.holds() + + val pageFuture = holdServiceAsync.list("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + + val page = pageFuture.get() + page.response().validate() + } + + @Test + fun void_() { + val client = + LithicOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val holdServiceAsync = client.holds() + + val holdFuture = + holdServiceAsync.void_( + HoldVoidParams.builder() + .holdToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .memo("memo") + .build() + ) + + val hold = holdFuture.get() + hold.validate() + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/HoldServiceTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/HoldServiceTest.kt new file mode 100644 index 00000000..59cc3682 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/HoldServiceTest.kt @@ -0,0 +1,87 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.services.blocking + +import com.lithic.api.TestServerExtension +import com.lithic.api.client.okhttp.LithicOkHttpClient +import com.lithic.api.models.HoldCreateParams +import com.lithic.api.models.HoldVoidParams +import java.time.OffsetDateTime +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class HoldServiceTest { + + @Test + fun create() { + val client = + LithicOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val holdService = client.holds() + + val hold = + holdService.create( + HoldCreateParams.builder() + .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .amount(1L) + .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .expirationDatetime(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .memo("memo") + .userDefinedId("user_defined_id") + .build() + ) + + hold.validate() + } + + @Test + fun retrieve() { + val client = + LithicOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val holdService = client.holds() + + val hold = holdService.retrieve("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + + hold.validate() + } + + @Test + fun list() { + val client = + LithicOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val holdService = client.holds() + + val page = holdService.list("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + + page.response().validate() + } + + @Test + fun void_() { + val client = + LithicOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My Lithic API Key") + .build() + val holdService = client.holds() + + val hold = + holdService.void_( + HoldVoidParams.builder() + .holdToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .memo("memo") + .build() + ) + + hold.validate() + } +} diff --git a/lithic-java-proguard-test/src/test/kotlin/com/lithic/api/proguard/ProGuardCompatibilityTest.kt b/lithic-java-proguard-test/src/test/kotlin/com/lithic/api/proguard/ProGuardCompatibilityTest.kt index eabccc2a..c5720dee 100644 --- a/lithic-java-proguard-test/src/test/kotlin/com/lithic/api/proguard/ProGuardCompatibilityTest.kt +++ b/lithic-java-proguard-test/src/test/kotlin/com/lithic/api/proguard/ProGuardCompatibilityTest.kt @@ -79,6 +79,7 @@ internal class ProGuardCompatibilityTest { assertThat(client.fundingEvents()).isNotNull() assertThat(client.fraud()).isNotNull() assertThat(client.networkPrograms()).isNotNull() + assertThat(client.holds()).isNotNull() assertThat(client.accountActivity()).isNotNull() assertThat(client.transferLimits()).isNotNull() assertThat(client.webhooks()).isNotNull() From 10b14732a71e84708c2da1234a47664b19354c97 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:05:51 +0000 Subject: [PATCH 02/10] chore(internal): codegen related update --- .github/workflows/ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 620a05d9..e7d7ae23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,14 +65,18 @@ jobs: run: ./scripts/build - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/lithic-java' + if: |- + github.repository == 'stainless-sdks/lithic-java' && + !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Build and upload Maven artifacts - if: github.repository == 'stainless-sdks/lithic-java' + if: |- + github.repository == 'stainless-sdks/lithic-java' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} From f57cd63e55e1331e79cd7f4bdea8b64bf5d05582 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 16:10:34 +0000 Subject: [PATCH 03/10] feat(api): add TypeScript rules, RuleFeature model, draft version state fields --- .stats.yml | 6 +- .../kotlin/com/lithic/api/models/AuthRule.kt | 344 +- .../api/models/AuthRuleV2CreateParams.kt | 174 +- .../api/models/AuthRuleV2DraftParams.kt | 47 +- .../com/lithic/api/models/RuleFeature.kt | 3181 +++++++++++++++++ .../api/models/TypescriptCodeParameters.kt | 271 ++ .../api/models/V2RetrieveFeaturesResponse.kt | 685 ---- .../lithic/api/models/VelocityLimitFilters.kt | 672 ++++ .../lithic/api/models/VelocityLimitParams.kt | 668 ---- .../com/lithic/api/models/AuthRuleTest.kt | 6 + .../models/AuthRuleV2ListPageResponseTest.kt | 6 + .../com/lithic/api/models/RuleFeatureTest.kt | 387 ++ .../models/TypescriptCodeParametersTest.kt | 59 + .../models/V2RetrieveFeaturesResponseTest.kt | 22 +- .../api/models/VelocityLimitFiltersTest.kt | 52 + .../api/models/VelocityLimitParamsTest.kt | 18 +- 16 files changed, 5204 insertions(+), 1394 deletions(-) create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/RuleFeature.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/TypescriptCodeParameters.kt create mode 100644 lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitFilters.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/RuleFeatureTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/TypescriptCodeParametersTest.kt create mode 100644 lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitFiltersTest.kt diff --git a/.stats.yml b/.stats.yml index b95d916a..31c05d97 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 189 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-ee2b9f00d3a9e0000e25abc0774615d6ad3300ce17b2f094e71b0229a907760f.yml -openapi_spec_hash: 01d2cbf4ac692dba2f3831462db929e4 -config_hash: a45e6da4e7b46db4ff6819d1dba5d815 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-1e902917b2eae41d549957e790eb6b137969e451efe673815647deba330fe05a.yml +openapi_spec_hash: 82cab06ce65462e60316939db630460a +config_hash: 00b60697e692f86b5be297d939962921 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRule.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRule.kt index 1d805631..46d18c7d 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRule.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRule.kt @@ -196,6 +196,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. * * @throws LithicInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). @@ -601,6 +603,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -910,6 +914,12 @@ private constructor( Parameters.ofConditionalTokenizationAction(conditionalTokenizationAction) ) + /** + * Alias for calling [parameters] with `Parameters.ofTypescriptCode(typescriptCode)`. + */ + fun parameters(typescriptCode: TypescriptCodeParameters) = + parameters(Parameters.ofTypescriptCode(typescriptCode)) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -1009,6 +1019,7 @@ private constructor( private val conditionalAchAction: ConditionalAchActionParameters? = null, private val conditionalTokenizationAction: ConditionalTokenizationActionParameters? = null, + private val typescriptCode: TypescriptCodeParameters? = null, private val _json: JsonValue? = null, ) { @@ -1035,6 +1046,10 @@ private constructor( fun conditionalTokenizationAction(): Optional = Optional.ofNullable(conditionalTokenizationAction) + /** Parameters for defining a TypeScript code rule */ + fun typescriptCode(): Optional = + Optional.ofNullable(typescriptCode) + @Deprecated("deprecated") fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -1049,6 +1064,8 @@ private constructor( fun isConditionalTokenizationAction(): Boolean = conditionalTokenizationAction != null + fun isTypescriptCode(): Boolean = typescriptCode != null + /** Deprecated: Use CONDITIONAL_ACTION instead. */ @Deprecated("deprecated") fun asConditionalBlock(): ConditionalBlockParameters = @@ -1071,6 +1088,10 @@ private constructor( fun asConditionalTokenizationAction(): ConditionalTokenizationActionParameters = conditionalTokenizationAction.getOrThrow("conditionalTokenizationAction") + /** Parameters for defining a TypeScript code rule */ + fun asTypescriptCode(): TypescriptCodeParameters = + typescriptCode.getOrThrow("typescriptCode") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -1087,6 +1108,7 @@ private constructor( visitor.visitConditionalAchAction(conditionalAchAction) conditionalTokenizationAction != null -> visitor.visitConditionalTokenizationAction(conditionalTokenizationAction) + typescriptCode != null -> visitor.visitTypescriptCode(typescriptCode) else -> visitor.unknown(_json) } @@ -1138,6 +1160,10 @@ private constructor( ) { conditionalTokenizationAction.validate() } + + override fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters) { + typescriptCode.validate() + } } ) validated = true @@ -1188,6 +1214,9 @@ private constructor( conditionalTokenizationAction: ConditionalTokenizationActionParameters ) = conditionalTokenizationAction.validity() + override fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters) = + typescriptCode.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1204,7 +1233,8 @@ private constructor( conditional3dsAction == other.conditional3dsAction && conditionalAuthorizationAction == other.conditionalAuthorizationAction && conditionalAchAction == other.conditionalAchAction && - conditionalTokenizationAction == other.conditionalTokenizationAction + conditionalTokenizationAction == other.conditionalTokenizationAction && + typescriptCode == other.typescriptCode } override fun hashCode(): Int = @@ -1216,6 +1246,7 @@ private constructor( conditionalAuthorizationAction, conditionalAchAction, conditionalTokenizationAction, + typescriptCode, ) override fun toString(): String = @@ -1232,6 +1263,7 @@ private constructor( "Parameters{conditionalAchAction=$conditionalAchAction}" conditionalTokenizationAction != null -> "Parameters{conditionalTokenizationAction=$conditionalTokenizationAction}" + typescriptCode != null -> "Parameters{typescriptCode=$typescriptCode}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1269,6 +1301,11 @@ private constructor( fun ofConditionalTokenizationAction( conditionalTokenizationAction: ConditionalTokenizationActionParameters ) = Parameters(conditionalTokenizationAction = conditionalTokenizationAction) + + /** Parameters for defining a TypeScript code rule */ + @JvmStatic + fun ofTypescriptCode(typescriptCode: TypescriptCodeParameters) = + Parameters(typescriptCode = typescriptCode) } /** @@ -1301,6 +1338,9 @@ private constructor( conditionalTokenizationAction: ConditionalTokenizationActionParameters ): T + /** Parameters for defining a TypeScript code rule */ + fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1357,6 +1397,8 @@ private constructor( ?.let { Parameters(conditionalTokenizationAction = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef()) + ?.let { Parameters(typescriptCode = it, _json = json) }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1395,6 +1437,7 @@ private constructor( generator.writeObject(value.conditionalAchAction) value.conditionalTokenizationAction != null -> generator.writeObject(value.conditionalTokenizationAction) + value.typescriptCode != null -> generator.writeObject(value.typescriptCode) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } @@ -1426,18 +1469,31 @@ private constructor( class DraftVersion @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( + private val error: JsonField, private val parameters: JsonField, + private val state: JsonField, private val version: JsonField, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( + @JsonProperty("error") @ExcludeMissing error: JsonField = JsonMissing.of(), @JsonProperty("parameters") @ExcludeMissing parameters: JsonField = JsonMissing.of(), + @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), @JsonProperty("version") @ExcludeMissing version: JsonField = JsonMissing.of(), - ) : this(parameters, version, mutableMapOf()) + ) : this(error, parameters, state, version, mutableMapOf()) + + /** + * An error message if the draft version failed compilation. Populated when `state` is + * `ERROR`, `null` otherwise. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun error(): Optional = error.getOptional("error") /** * Parameters for the Auth Rule @@ -1447,6 +1503,21 @@ private constructor( */ fun parameters(): Parameters = parameters.getRequired("parameters") + /** + * The state of the draft version. Most rules are created synchronously and the state is + * immediately `SHADOWING`. Rules backed by TypeScript code are compiled asynchronously — + * the state starts as `PENDING` and transitions to `SHADOWING` on success or `ERROR` on + * failure. + * - `PENDING`: Compilation of the rule is in progress (TypeScript rules only). + * - `SHADOWING`: The draft version is ready and evaluating in shadow mode alongside the + * current active version. It can be promoted to the active version. + * - `ERROR`: Compilation of the rule failed. Check the `error` field for details. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun state(): State = state.getRequired("state") + /** * The version of the rule, this is incremented whenever the rule's parameters change. * @@ -1455,6 +1526,13 @@ private constructor( */ fun version(): Long = version.getRequired("version") + /** + * Returns the raw JSON value of [error]. + * + * Unlike [error], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("error") @ExcludeMissing fun _error(): JsonField = error + /** * Returns the raw JSON value of [parameters]. * @@ -1464,6 +1542,13 @@ private constructor( @ExcludeMissing fun _parameters(): JsonField = parameters + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + /** * Returns the raw JSON value of [version]. * @@ -1490,7 +1575,9 @@ private constructor( * * The following fields are required: * ```java + * .error() * .parameters() + * .state() * .version() * ``` */ @@ -1500,17 +1587,39 @@ private constructor( /** A builder for [DraftVersion]. */ class Builder internal constructor() { + private var error: JsonField? = null private var parameters: JsonField? = null + private var state: JsonField? = null private var version: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(draftVersion: DraftVersion) = apply { + error = draftVersion.error parameters = draftVersion.parameters + state = draftVersion.state version = draftVersion.version additionalProperties = draftVersion.additionalProperties.toMutableMap() } + /** + * An error message if the draft version failed compilation. Populated when `state` is + * `ERROR`, `null` otherwise. + */ + fun error(error: String?) = error(JsonField.ofNullable(error)) + + /** Alias for calling [Builder.error] with `error.orElse(null)`. */ + fun error(error: Optional) = error(error.getOrNull()) + + /** + * Sets [Builder.error] to an arbitrary JSON value. + * + * You should usually call [Builder.error] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun error(error: JsonField) = apply { this.error = error } + /** Parameters for the Auth Rule */ fun parameters(parameters: Parameters) = parameters(JsonField.of(parameters)) @@ -1578,6 +1687,33 @@ private constructor( Parameters.ofConditionalTokenizationAction(conditionalTokenizationAction) ) + /** + * Alias for calling [parameters] with `Parameters.ofTypescriptCode(typescriptCode)`. + */ + fun parameters(typescriptCode: TypescriptCodeParameters) = + parameters(Parameters.ofTypescriptCode(typescriptCode)) + + /** + * The state of the draft version. Most rules are created synchronously and the state is + * immediately `SHADOWING`. Rules backed by TypeScript code are compiled asynchronously + * — the state starts as `PENDING` and transitions to `SHADOWING` on success or `ERROR` + * on failure. + * - `PENDING`: Compilation of the rule is in progress (TypeScript rules only). + * - `SHADOWING`: The draft version is ready and evaluating in shadow mode alongside the + * current active version. It can be promoted to the active version. + * - `ERROR`: Compilation of the rule failed. Check the `error` field for details. + */ + fun state(state: State) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [State] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun state(state: JsonField) = apply { this.state = state } + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -1618,7 +1754,9 @@ private constructor( * * The following fields are required: * ```java + * .error() * .parameters() + * .state() * .version() * ``` * @@ -1626,7 +1764,9 @@ private constructor( */ fun build(): DraftVersion = DraftVersion( + checkRequired("error", error), checkRequired("parameters", parameters), + checkRequired("state", state), checkRequired("version", version), additionalProperties.toMutableMap(), ) @@ -1639,7 +1779,9 @@ private constructor( return@apply } + error() parameters().validate() + state().validate() version() validated = true } @@ -1660,7 +1802,9 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (parameters.asKnown().getOrNull()?.validity() ?: 0) + + (if (error.asKnown().isPresent) 1 else 0) + + (parameters.asKnown().getOrNull()?.validity() ?: 0) + + (state.asKnown().getOrNull()?.validity() ?: 0) + (if (version.asKnown().isPresent) 1 else 0) /** Parameters for the Auth Rule */ @@ -1677,6 +1821,7 @@ private constructor( private val conditionalAchAction: ConditionalAchActionParameters? = null, private val conditionalTokenizationAction: ConditionalTokenizationActionParameters? = null, + private val typescriptCode: TypescriptCodeParameters? = null, private val _json: JsonValue? = null, ) { @@ -1703,6 +1848,10 @@ private constructor( fun conditionalTokenizationAction(): Optional = Optional.ofNullable(conditionalTokenizationAction) + /** Parameters for defining a TypeScript code rule */ + fun typescriptCode(): Optional = + Optional.ofNullable(typescriptCode) + @Deprecated("deprecated") fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -1717,6 +1866,8 @@ private constructor( fun isConditionalTokenizationAction(): Boolean = conditionalTokenizationAction != null + fun isTypescriptCode(): Boolean = typescriptCode != null + /** Deprecated: Use CONDITIONAL_ACTION instead. */ @Deprecated("deprecated") fun asConditionalBlock(): ConditionalBlockParameters = @@ -1739,6 +1890,10 @@ private constructor( fun asConditionalTokenizationAction(): ConditionalTokenizationActionParameters = conditionalTokenizationAction.getOrThrow("conditionalTokenizationAction") + /** Parameters for defining a TypeScript code rule */ + fun asTypescriptCode(): TypescriptCodeParameters = + typescriptCode.getOrThrow("typescriptCode") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -1755,6 +1910,7 @@ private constructor( visitor.visitConditionalAchAction(conditionalAchAction) conditionalTokenizationAction != null -> visitor.visitConditionalTokenizationAction(conditionalTokenizationAction) + typescriptCode != null -> visitor.visitTypescriptCode(typescriptCode) else -> visitor.unknown(_json) } @@ -1806,6 +1962,10 @@ private constructor( ) { conditionalTokenizationAction.validate() } + + override fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters) { + typescriptCode.validate() + } } ) validated = true @@ -1856,6 +2016,9 @@ private constructor( conditionalTokenizationAction: ConditionalTokenizationActionParameters ) = conditionalTokenizationAction.validity() + override fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters) = + typescriptCode.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1872,7 +2035,8 @@ private constructor( conditional3dsAction == other.conditional3dsAction && conditionalAuthorizationAction == other.conditionalAuthorizationAction && conditionalAchAction == other.conditionalAchAction && - conditionalTokenizationAction == other.conditionalTokenizationAction + conditionalTokenizationAction == other.conditionalTokenizationAction && + typescriptCode == other.typescriptCode } override fun hashCode(): Int = @@ -1884,6 +2048,7 @@ private constructor( conditionalAuthorizationAction, conditionalAchAction, conditionalTokenizationAction, + typescriptCode, ) override fun toString(): String = @@ -1900,6 +2065,7 @@ private constructor( "Parameters{conditionalAchAction=$conditionalAchAction}" conditionalTokenizationAction != null -> "Parameters{conditionalTokenizationAction=$conditionalTokenizationAction}" + typescriptCode != null -> "Parameters{typescriptCode=$typescriptCode}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1937,6 +2103,11 @@ private constructor( fun ofConditionalTokenizationAction( conditionalTokenizationAction: ConditionalTokenizationActionParameters ) = Parameters(conditionalTokenizationAction = conditionalTokenizationAction) + + /** Parameters for defining a TypeScript code rule */ + @JvmStatic + fun ofTypescriptCode(typescriptCode: TypescriptCodeParameters) = + Parameters(typescriptCode = typescriptCode) } /** @@ -1969,6 +2140,9 @@ private constructor( conditionalTokenizationAction: ConditionalTokenizationActionParameters ): T + /** Parameters for defining a TypeScript code rule */ + fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -2025,6 +2199,8 @@ private constructor( ?.let { Parameters(conditionalTokenizationAction = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef()) + ?.let { Parameters(typescriptCode = it, _json = json) }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -2063,6 +2239,7 @@ private constructor( generator.writeObject(value.conditionalAchAction) value.conditionalTokenizationAction != null -> generator.writeObject(value.conditionalTokenizationAction) + value.typescriptCode != null -> generator.writeObject(value.typescriptCode) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } @@ -2070,25 +2247,172 @@ private constructor( } } + /** + * The state of the draft version. Most rules are created synchronously and the state is + * immediately `SHADOWING`. Rules backed by TypeScript code are compiled asynchronously — + * the state starts as `PENDING` and transitions to `SHADOWING` on success or `ERROR` on + * failure. + * - `PENDING`: Compilation of the rule is in progress (TypeScript rules only). + * - `SHADOWING`: The draft version is ready and evaluating in shadow mode alongside the + * current active version. It can be promoted to the active version. + * - `ERROR`: Compilation of the rule failed. Check the `error` field for details. + */ + class State @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 PENDING = of("PENDING") + + @JvmField val SHADOWING = of("SHADOWING") + + @JvmField val ERROR = of("ERROR") + + @JvmStatic fun of(value: String) = State(JsonField.of(value)) + } + + /** An enum containing [State]'s known values. */ + enum class Known { + PENDING, + SHADOWING, + ERROR, + } + + /** + * An enum containing [State]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [State] 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 { + PENDING, + SHADOWING, + ERROR, + /** + * An enum member indicating that [State] 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) { + PENDING -> Value.PENDING + SHADOWING -> Value.SHADOWING + ERROR -> Value.ERROR + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + PENDING -> Known.PENDING + SHADOWING -> Known.SHADOWING + ERROR -> Known.ERROR + else -> throw LithicInvalidDataException("Unknown State: $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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): State = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 State && 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 DraftVersion && + error == other.error && parameters == other.parameters && + state == other.state && version == other.version && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(parameters, version, additionalProperties) + Objects.hash(error, parameters, state, version, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "DraftVersion{parameters=$parameters, version=$version, additionalProperties=$additionalProperties}" + "DraftVersion{error=$error, parameters=$parameters, state=$state, version=$version, additionalProperties=$additionalProperties}" } /** The state of the Auth Rule */ @@ -2231,6 +2555,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. */ class AuthRuleType @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -2255,6 +2581,8 @@ private constructor( @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") + @JvmField val TYPESCRIPT_CODE = of("TYPESCRIPT_CODE") + @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -2264,6 +2592,7 @@ private constructor( VELOCITY_LIMIT, MERCHANT_LOCK, CONDITIONAL_ACTION, + TYPESCRIPT_CODE, } /** @@ -2280,6 +2609,7 @@ private constructor( VELOCITY_LIMIT, MERCHANT_LOCK, CONDITIONAL_ACTION, + TYPESCRIPT_CODE, /** * An enum member indicating that [AuthRuleType] was instantiated with an unknown value. */ @@ -2299,6 +2629,7 @@ private constructor( VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION + TYPESCRIPT_CODE -> Value.TYPESCRIPT_CODE else -> Value._UNKNOWN } @@ -2317,6 +2648,7 @@ private constructor( VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION + TYPESCRIPT_CODE -> Known.TYPESCRIPT_CODE else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2CreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2CreateParams.kt index ff88bcb1..e8820e62 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2CreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2CreateParams.kt @@ -479,6 +479,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. * * @throws LithicInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected @@ -694,6 +696,13 @@ private constructor( Parameters.ofConditionalTokenizationAction(conditionalTokenizationAction) ) + /** + * Alias for calling [parameters] with + * `Parameters.ofTypescriptCode(typescriptCode)`. + */ + fun parameters(typescriptCode: TypescriptCodeParameters) = + parameters(Parameters.ofTypescriptCode(typescriptCode)) + /** * The type of Auth Rule. For certain rule types, this determines the event stream * during which it will be evaluated. For rules that can be applied to one of @@ -705,6 +714,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -902,6 +913,7 @@ private constructor( private val conditionalTokenizationAction: ConditionalTokenizationActionParameters? = null, + private val typescriptCode: TypescriptCodeParameters? = null, private val _json: JsonValue? = null, ) { @@ -930,6 +942,10 @@ private constructor( Optional = Optional.ofNullable(conditionalTokenizationAction) + /** Parameters for defining a TypeScript code rule */ + fun typescriptCode(): Optional = + Optional.ofNullable(typescriptCode) + @Deprecated("deprecated") fun isConditionalBlock(): Boolean = conditionalBlock != null @@ -947,6 +963,8 @@ private constructor( fun isConditionalTokenizationAction(): Boolean = conditionalTokenizationAction != null + fun isTypescriptCode(): Boolean = typescriptCode != null + /** Deprecated: Use CONDITIONAL_ACTION instead. */ @Deprecated("deprecated") fun asConditionalBlock(): ConditionalBlockParameters = @@ -970,6 +988,10 @@ private constructor( fun asConditionalTokenizationAction(): ConditionalTokenizationActionParameters = conditionalTokenizationAction.getOrThrow("conditionalTokenizationAction") + /** Parameters for defining a TypeScript code rule */ + fun asTypescriptCode(): TypescriptCodeParameters = + typescriptCode.getOrThrow("typescriptCode") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -990,6 +1012,7 @@ private constructor( visitor.visitConditionalTokenizationAction( conditionalTokenizationAction ) + typescriptCode != null -> visitor.visitTypescriptCode(typescriptCode) else -> visitor.unknown(_json) } @@ -1043,6 +1066,12 @@ private constructor( ) { conditionalTokenizationAction.validate() } + + override fun visitTypescriptCode( + typescriptCode: TypescriptCodeParameters + ) { + typescriptCode.validate() + } } ) validated = true @@ -1095,6 +1124,10 @@ private constructor( ConditionalTokenizationActionParameters ) = conditionalTokenizationAction.validity() + override fun visitTypescriptCode( + typescriptCode: TypescriptCodeParameters + ) = typescriptCode.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1111,7 +1144,8 @@ private constructor( conditional3dsAction == other.conditional3dsAction && conditionalAuthorizationAction == other.conditionalAuthorizationAction && conditionalAchAction == other.conditionalAchAction && - conditionalTokenizationAction == other.conditionalTokenizationAction + conditionalTokenizationAction == other.conditionalTokenizationAction && + typescriptCode == other.typescriptCode } override fun hashCode(): Int = @@ -1123,6 +1157,7 @@ private constructor( conditionalAuthorizationAction, conditionalAchAction, conditionalTokenizationAction, + typescriptCode, ) override fun toString(): String = @@ -1139,6 +1174,7 @@ private constructor( "Parameters{conditionalAchAction=$conditionalAchAction}" conditionalTokenizationAction != null -> "Parameters{conditionalTokenizationAction=$conditionalTokenizationAction}" + typescriptCode != null -> "Parameters{typescriptCode=$typescriptCode}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1178,6 +1214,11 @@ private constructor( fun ofConditionalTokenizationAction( conditionalTokenizationAction: ConditionalTokenizationActionParameters ) = Parameters(conditionalTokenizationAction = conditionalTokenizationAction) + + /** Parameters for defining a TypeScript code rule */ + @JvmStatic + fun ofTypescriptCode(typescriptCode: TypescriptCodeParameters) = + Parameters(typescriptCode = typescriptCode) } /** @@ -1210,6 +1251,9 @@ private constructor( conditionalTokenizationAction: ConditionalTokenizationActionParameters ): T + /** Parameters for defining a TypeScript code rule */ + fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1281,6 +1325,8 @@ private constructor( _json = json, ) }, + tryDeserialize(node, jacksonTypeRef()) + ?.let { Parameters(typescriptCode = it, _json = json) }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1320,6 +1366,8 @@ private constructor( generator.writeObject(value.conditionalAchAction) value.conditionalTokenizationAction != null -> generator.writeObject(value.conditionalTokenizationAction) + value.typescriptCode != null -> + generator.writeObject(value.typescriptCode) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } @@ -1337,6 +1385,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. */ class AuthRuleType @JsonCreator @@ -1362,6 +1412,8 @@ private constructor( @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") + @JvmField val TYPESCRIPT_CODE = of("TYPESCRIPT_CODE") + @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -1371,6 +1423,7 @@ private constructor( VELOCITY_LIMIT, MERCHANT_LOCK, CONDITIONAL_ACTION, + TYPESCRIPT_CODE, } /** @@ -1388,6 +1441,7 @@ private constructor( VELOCITY_LIMIT, MERCHANT_LOCK, CONDITIONAL_ACTION, + TYPESCRIPT_CODE, /** * An enum member indicating that [AuthRuleType] was instantiated with an * unknown value. @@ -1408,6 +1462,7 @@ private constructor( VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION + TYPESCRIPT_CODE -> Value.TYPESCRIPT_CODE else -> Value._UNKNOWN } @@ -1426,6 +1481,7 @@ private constructor( VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION + TYPESCRIPT_CODE -> Known.TYPESCRIPT_CODE else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -1572,6 +1628,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. * * @throws LithicInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected @@ -1783,6 +1841,13 @@ private constructor( Parameters.ofConditionalTokenizationAction(conditionalTokenizationAction) ) + /** + * Alias for calling [parameters] with + * `Parameters.ofTypescriptCode(typescriptCode)`. + */ + fun parameters(typescriptCode: TypescriptCodeParameters) = + parameters(Parameters.ofTypescriptCode(typescriptCode)) + /** * The type of Auth Rule. For certain rule types, this determines the event stream * during which it will be evaluated. For rules that can be applied to one of @@ -1794,6 +1859,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -1935,6 +2002,7 @@ private constructor( private val conditionalTokenizationAction: ConditionalTokenizationActionParameters? = null, + private val typescriptCode: TypescriptCodeParameters? = null, private val _json: JsonValue? = null, ) { @@ -1963,6 +2031,10 @@ private constructor( Optional = Optional.ofNullable(conditionalTokenizationAction) + /** Parameters for defining a TypeScript code rule */ + fun typescriptCode(): Optional = + Optional.ofNullable(typescriptCode) + @Deprecated("deprecated") fun isConditionalBlock(): Boolean = conditionalBlock != null @@ -1980,6 +2052,8 @@ private constructor( fun isConditionalTokenizationAction(): Boolean = conditionalTokenizationAction != null + fun isTypescriptCode(): Boolean = typescriptCode != null + /** Deprecated: Use CONDITIONAL_ACTION instead. */ @Deprecated("deprecated") fun asConditionalBlock(): ConditionalBlockParameters = @@ -2003,6 +2077,10 @@ private constructor( fun asConditionalTokenizationAction(): ConditionalTokenizationActionParameters = conditionalTokenizationAction.getOrThrow("conditionalTokenizationAction") + /** Parameters for defining a TypeScript code rule */ + fun asTypescriptCode(): TypescriptCodeParameters = + typescriptCode.getOrThrow("typescriptCode") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -2023,6 +2101,7 @@ private constructor( visitor.visitConditionalTokenizationAction( conditionalTokenizationAction ) + typescriptCode != null -> visitor.visitTypescriptCode(typescriptCode) else -> visitor.unknown(_json) } @@ -2076,6 +2155,12 @@ private constructor( ) { conditionalTokenizationAction.validate() } + + override fun visitTypescriptCode( + typescriptCode: TypescriptCodeParameters + ) { + typescriptCode.validate() + } } ) validated = true @@ -2128,6 +2213,10 @@ private constructor( ConditionalTokenizationActionParameters ) = conditionalTokenizationAction.validity() + override fun visitTypescriptCode( + typescriptCode: TypescriptCodeParameters + ) = typescriptCode.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -2144,7 +2233,8 @@ private constructor( conditional3dsAction == other.conditional3dsAction && conditionalAuthorizationAction == other.conditionalAuthorizationAction && conditionalAchAction == other.conditionalAchAction && - conditionalTokenizationAction == other.conditionalTokenizationAction + conditionalTokenizationAction == other.conditionalTokenizationAction && + typescriptCode == other.typescriptCode } override fun hashCode(): Int = @@ -2156,6 +2246,7 @@ private constructor( conditionalAuthorizationAction, conditionalAchAction, conditionalTokenizationAction, + typescriptCode, ) override fun toString(): String = @@ -2172,6 +2263,7 @@ private constructor( "Parameters{conditionalAchAction=$conditionalAchAction}" conditionalTokenizationAction != null -> "Parameters{conditionalTokenizationAction=$conditionalTokenizationAction}" + typescriptCode != null -> "Parameters{typescriptCode=$typescriptCode}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -2211,6 +2303,11 @@ private constructor( fun ofConditionalTokenizationAction( conditionalTokenizationAction: ConditionalTokenizationActionParameters ) = Parameters(conditionalTokenizationAction = conditionalTokenizationAction) + + /** Parameters for defining a TypeScript code rule */ + @JvmStatic + fun ofTypescriptCode(typescriptCode: TypescriptCodeParameters) = + Parameters(typescriptCode = typescriptCode) } /** @@ -2243,6 +2340,9 @@ private constructor( conditionalTokenizationAction: ConditionalTokenizationActionParameters ): T + /** Parameters for defining a TypeScript code rule */ + fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -2314,6 +2414,8 @@ private constructor( _json = json, ) }, + tryDeserialize(node, jacksonTypeRef()) + ?.let { Parameters(typescriptCode = it, _json = json) }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -2353,6 +2455,8 @@ private constructor( generator.writeObject(value.conditionalAchAction) value.conditionalTokenizationAction != null -> generator.writeObject(value.conditionalTokenizationAction) + value.typescriptCode != null -> + generator.writeObject(value.typescriptCode) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } @@ -2370,6 +2474,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. */ class AuthRuleType @JsonCreator @@ -2395,6 +2501,8 @@ private constructor( @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") + @JvmField val TYPESCRIPT_CODE = of("TYPESCRIPT_CODE") + @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -2404,6 +2512,7 @@ private constructor( VELOCITY_LIMIT, MERCHANT_LOCK, CONDITIONAL_ACTION, + TYPESCRIPT_CODE, } /** @@ -2421,6 +2530,7 @@ private constructor( VELOCITY_LIMIT, MERCHANT_LOCK, CONDITIONAL_ACTION, + TYPESCRIPT_CODE, /** * An enum member indicating that [AuthRuleType] was instantiated with an * unknown value. @@ -2441,6 +2551,7 @@ private constructor( VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION + TYPESCRIPT_CODE -> Value.TYPESCRIPT_CODE else -> Value._UNKNOWN } @@ -2459,6 +2570,7 @@ private constructor( VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION + TYPESCRIPT_CODE -> Known.TYPESCRIPT_CODE else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -2608,6 +2720,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. * * @throws LithicInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected @@ -2815,6 +2929,13 @@ private constructor( Parameters.ofConditionalTokenizationAction(conditionalTokenizationAction) ) + /** + * Alias for calling [parameters] with + * `Parameters.ofTypescriptCode(typescriptCode)`. + */ + fun parameters(typescriptCode: TypescriptCodeParameters) = + parameters(Parameters.ofTypescriptCode(typescriptCode)) + /** Whether the Auth Rule applies to all authorizations on the card program. */ fun programLevel(programLevel: Boolean) = programLevel(JsonField.of(programLevel)) @@ -2840,6 +2961,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -3011,6 +3134,7 @@ private constructor( private val conditionalTokenizationAction: ConditionalTokenizationActionParameters? = null, + private val typescriptCode: TypescriptCodeParameters? = null, private val _json: JsonValue? = null, ) { @@ -3039,6 +3163,10 @@ private constructor( Optional = Optional.ofNullable(conditionalTokenizationAction) + /** Parameters for defining a TypeScript code rule */ + fun typescriptCode(): Optional = + Optional.ofNullable(typescriptCode) + @Deprecated("deprecated") fun isConditionalBlock(): Boolean = conditionalBlock != null @@ -3056,6 +3184,8 @@ private constructor( fun isConditionalTokenizationAction(): Boolean = conditionalTokenizationAction != null + fun isTypescriptCode(): Boolean = typescriptCode != null + /** Deprecated: Use CONDITIONAL_ACTION instead. */ @Deprecated("deprecated") fun asConditionalBlock(): ConditionalBlockParameters = @@ -3079,6 +3209,10 @@ private constructor( fun asConditionalTokenizationAction(): ConditionalTokenizationActionParameters = conditionalTokenizationAction.getOrThrow("conditionalTokenizationAction") + /** Parameters for defining a TypeScript code rule */ + fun asTypescriptCode(): TypescriptCodeParameters = + typescriptCode.getOrThrow("typescriptCode") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -3099,6 +3233,7 @@ private constructor( visitor.visitConditionalTokenizationAction( conditionalTokenizationAction ) + typescriptCode != null -> visitor.visitTypescriptCode(typescriptCode) else -> visitor.unknown(_json) } @@ -3152,6 +3287,12 @@ private constructor( ) { conditionalTokenizationAction.validate() } + + override fun visitTypescriptCode( + typescriptCode: TypescriptCodeParameters + ) { + typescriptCode.validate() + } } ) validated = true @@ -3204,6 +3345,10 @@ private constructor( ConditionalTokenizationActionParameters ) = conditionalTokenizationAction.validity() + override fun visitTypescriptCode( + typescriptCode: TypescriptCodeParameters + ) = typescriptCode.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -3220,7 +3365,8 @@ private constructor( conditional3dsAction == other.conditional3dsAction && conditionalAuthorizationAction == other.conditionalAuthorizationAction && conditionalAchAction == other.conditionalAchAction && - conditionalTokenizationAction == other.conditionalTokenizationAction + conditionalTokenizationAction == other.conditionalTokenizationAction && + typescriptCode == other.typescriptCode } override fun hashCode(): Int = @@ -3232,6 +3378,7 @@ private constructor( conditionalAuthorizationAction, conditionalAchAction, conditionalTokenizationAction, + typescriptCode, ) override fun toString(): String = @@ -3248,6 +3395,7 @@ private constructor( "Parameters{conditionalAchAction=$conditionalAchAction}" conditionalTokenizationAction != null -> "Parameters{conditionalTokenizationAction=$conditionalTokenizationAction}" + typescriptCode != null -> "Parameters{typescriptCode=$typescriptCode}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -3287,6 +3435,11 @@ private constructor( fun ofConditionalTokenizationAction( conditionalTokenizationAction: ConditionalTokenizationActionParameters ) = Parameters(conditionalTokenizationAction = conditionalTokenizationAction) + + /** Parameters for defining a TypeScript code rule */ + @JvmStatic + fun ofTypescriptCode(typescriptCode: TypescriptCodeParameters) = + Parameters(typescriptCode = typescriptCode) } /** @@ -3319,6 +3472,9 @@ private constructor( conditionalTokenizationAction: ConditionalTokenizationActionParameters ): T + /** Parameters for defining a TypeScript code rule */ + fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -3390,6 +3546,8 @@ private constructor( _json = json, ) }, + tryDeserialize(node, jacksonTypeRef()) + ?.let { Parameters(typescriptCode = it, _json = json) }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -3429,6 +3587,8 @@ private constructor( generator.writeObject(value.conditionalAchAction) value.conditionalTokenizationAction != null -> generator.writeObject(value.conditionalTokenizationAction) + value.typescriptCode != null -> + generator.writeObject(value.typescriptCode) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } @@ -3446,6 +3606,8 @@ private constructor( * - `MERCHANT_LOCK`: AUTHORIZATION event stream. * - `CONDITIONAL_ACTION`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. + * - `TYPESCRIPT_CODE`: AUTHORIZATION, THREE_DS_AUTHENTICATION, TOKENIZATION, + * ACH_CREDIT_RECEIPT, or ACH_DEBIT_RECEIPT event stream. */ class AuthRuleType @JsonCreator @@ -3471,6 +3633,8 @@ private constructor( @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") + @JvmField val TYPESCRIPT_CODE = of("TYPESCRIPT_CODE") + @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -3480,6 +3644,7 @@ private constructor( VELOCITY_LIMIT, MERCHANT_LOCK, CONDITIONAL_ACTION, + TYPESCRIPT_CODE, } /** @@ -3497,6 +3662,7 @@ private constructor( VELOCITY_LIMIT, MERCHANT_LOCK, CONDITIONAL_ACTION, + TYPESCRIPT_CODE, /** * An enum member indicating that [AuthRuleType] was instantiated with an * unknown value. @@ -3517,6 +3683,7 @@ private constructor( VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION + TYPESCRIPT_CODE -> Value.TYPESCRIPT_CODE else -> Value._UNKNOWN } @@ -3535,6 +3702,7 @@ private constructor( VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION + TYPESCRIPT_CODE -> Known.TYPESCRIPT_CODE else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2DraftParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2DraftParams.kt index 56772a9b..c375bbbb 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2DraftParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2DraftParams.kt @@ -180,6 +180,11 @@ private constructor( body.parameters(conditionalTokenizationAction) } + /** Alias for calling [parameters] with `Parameters.ofTypescriptCode(typescriptCode)`. */ + fun parameters(typescriptCode: TypescriptCodeParameters) = apply { + body.parameters(typescriptCode) + } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { body.additionalProperties(additionalBodyProperties) } @@ -454,6 +459,12 @@ private constructor( Parameters.ofConditionalTokenizationAction(conditionalTokenizationAction) ) + /** + * Alias for calling [parameters] with `Parameters.ofTypescriptCode(typescriptCode)`. + */ + fun parameters(typescriptCode: TypescriptCodeParameters) = + parameters(Parameters.ofTypescriptCode(typescriptCode)) + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -540,6 +551,7 @@ private constructor( null, private val conditionalAchAction: ConditionalAchActionParameters? = null, private val conditionalTokenizationAction: ConditionalTokenizationActionParameters? = null, + private val typescriptCode: TypescriptCodeParameters? = null, private val _json: JsonValue? = null, ) { @@ -565,6 +577,10 @@ private constructor( fun conditionalTokenizationAction(): Optional = Optional.ofNullable(conditionalTokenizationAction) + /** Parameters for defining a TypeScript code rule */ + fun typescriptCode(): Optional = + Optional.ofNullable(typescriptCode) + @Deprecated("deprecated") fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -579,6 +595,8 @@ private constructor( fun isConditionalTokenizationAction(): Boolean = conditionalTokenizationAction != null + fun isTypescriptCode(): Boolean = typescriptCode != null + /** Deprecated: Use CONDITIONAL_ACTION instead. */ @Deprecated("deprecated") fun asConditionalBlock(): ConditionalBlockParameters = @@ -601,6 +619,10 @@ private constructor( fun asConditionalTokenizationAction(): ConditionalTokenizationActionParameters = conditionalTokenizationAction.getOrThrow("conditionalTokenizationAction") + /** Parameters for defining a TypeScript code rule */ + fun asTypescriptCode(): TypescriptCodeParameters = + typescriptCode.getOrThrow("typescriptCode") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -616,6 +638,7 @@ private constructor( visitor.visitConditionalAchAction(conditionalAchAction) conditionalTokenizationAction != null -> visitor.visitConditionalTokenizationAction(conditionalTokenizationAction) + typescriptCode != null -> visitor.visitTypescriptCode(typescriptCode) else -> visitor.unknown(_json) } @@ -667,6 +690,10 @@ private constructor( ) { conditionalTokenizationAction.validate() } + + override fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters) { + typescriptCode.validate() + } } ) validated = true @@ -717,6 +744,9 @@ private constructor( conditionalTokenizationAction: ConditionalTokenizationActionParameters ) = conditionalTokenizationAction.validity() + override fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters) = + typescriptCode.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -733,7 +763,8 @@ private constructor( conditional3dsAction == other.conditional3dsAction && conditionalAuthorizationAction == other.conditionalAuthorizationAction && conditionalAchAction == other.conditionalAchAction && - conditionalTokenizationAction == other.conditionalTokenizationAction + conditionalTokenizationAction == other.conditionalTokenizationAction && + typescriptCode == other.typescriptCode } override fun hashCode(): Int = @@ -745,6 +776,7 @@ private constructor( conditionalAuthorizationAction, conditionalAchAction, conditionalTokenizationAction, + typescriptCode, ) override fun toString(): String = @@ -761,6 +793,7 @@ private constructor( "Parameters{conditionalAchAction=$conditionalAchAction}" conditionalTokenizationAction != null -> "Parameters{conditionalTokenizationAction=$conditionalTokenizationAction}" + typescriptCode != null -> "Parameters{typescriptCode=$typescriptCode}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -798,6 +831,11 @@ private constructor( fun ofConditionalTokenizationAction( conditionalTokenizationAction: ConditionalTokenizationActionParameters ) = Parameters(conditionalTokenizationAction = conditionalTokenizationAction) + + /** Parameters for defining a TypeScript code rule */ + @JvmStatic + fun ofTypescriptCode(typescriptCode: TypescriptCodeParameters) = + Parameters(typescriptCode = typescriptCode) } /** @@ -825,6 +863,9 @@ private constructor( conditionalTokenizationAction: ConditionalTokenizationActionParameters ): T + /** Parameters for defining a TypeScript code rule */ + fun visitTypescriptCode(typescriptCode: TypescriptCodeParameters): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -873,6 +914,9 @@ private constructor( ?.let { Parameters(conditionalTokenizationAction = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + Parameters(typescriptCode = it, _json = json) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -910,6 +954,7 @@ private constructor( generator.writeObject(value.conditionalAchAction) value.conditionalTokenizationAction != null -> generator.writeObject(value.conditionalTokenizationAction) + value.typescriptCode != null -> generator.writeObject(value.typescriptCode) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/RuleFeature.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/RuleFeature.kt new file mode 100644 index 00000000..e5fd1d51 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/RuleFeature.kt @@ -0,0 +1,3181 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.BaseDeserializer +import com.lithic.api.core.BaseSerializer +import com.lithic.api.core.Enum +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.allMaxBy +import com.lithic.api.core.checkRequired +import com.lithic.api.core.getOrThrow +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * A feature made available to the rule. The `name` field is the variable name used in the rule + * function signature. The `type` field determines which data the feature provides to the rule at + * evaluation time. + * - `AUTHORIZATION`: The authorization request being evaluated. Only available for AUTHORIZATION + * event stream rules. + * - `AUTHENTICATION`: The 3DS authentication request being evaluated. Only available for + * THREE_DS_AUTHENTICATION event stream rules. + * - `TOKENIZATION`: The tokenization request being evaluated. Only available for TOKENIZATION event + * stream rules. + * - `ACH_RECEIPT`: The ACH receipt being evaluated. Only available for ACH_CREDIT_RECEIPT and + * ACH_DEBIT_RECEIPT event stream rules. + * - `CARD`: The card associated with the event. Available for AUTHORIZATION and + * THREE_DS_AUTHENTICATION event stream rules. + * - `ACCOUNT_HOLDER`: The account holder associated with the card. Available for + * THREE_DS_AUTHENTICATION event stream rules. + * - `IP_METADATA`: IP address metadata for the request. Available for THREE_DS_AUTHENTICATION event + * stream rules. + * - `SPEND_VELOCITY`: Spend velocity data for the card or account. Requires `scope`, `period`, and + * optionally `filters` to configure the velocity calculation. Available for AUTHORIZATION event + * stream rules. + */ +@JsonDeserialize(using = RuleFeature.Deserializer::class) +@JsonSerialize(using = RuleFeature.Serializer::class) +class RuleFeature +private constructor( + private val authorization: AuthorizationFeature? = null, + private val authentication: AuthenticationFeature? = null, + private val tokenization: TokenizationFeature? = null, + private val achReceipt: AchReceiptFeature? = null, + private val card: CardFeature? = null, + private val accountHolder: AccountHolderFeature? = null, + private val ipMetadata: IpMetadataFeature? = null, + private val spendVelocity: SpendVelocityFeature? = null, + private val _json: JsonValue? = null, +) { + + fun authorization(): Optional = Optional.ofNullable(authorization) + + fun authentication(): Optional = Optional.ofNullable(authentication) + + fun tokenization(): Optional = Optional.ofNullable(tokenization) + + fun achReceipt(): Optional = Optional.ofNullable(achReceipt) + + fun card(): Optional = Optional.ofNullable(card) + + fun accountHolder(): Optional = Optional.ofNullable(accountHolder) + + fun ipMetadata(): Optional = Optional.ofNullable(ipMetadata) + + fun spendVelocity(): Optional = Optional.ofNullable(spendVelocity) + + fun isAuthorization(): Boolean = authorization != null + + fun isAuthentication(): Boolean = authentication != null + + fun isTokenization(): Boolean = tokenization != null + + fun isAchReceipt(): Boolean = achReceipt != null + + fun isCard(): Boolean = card != null + + fun isAccountHolder(): Boolean = accountHolder != null + + fun isIpMetadata(): Boolean = ipMetadata != null + + fun isSpendVelocity(): Boolean = spendVelocity != null + + fun asAuthorization(): AuthorizationFeature = authorization.getOrThrow("authorization") + + fun asAuthentication(): AuthenticationFeature = authentication.getOrThrow("authentication") + + fun asTokenization(): TokenizationFeature = tokenization.getOrThrow("tokenization") + + fun asAchReceipt(): AchReceiptFeature = achReceipt.getOrThrow("achReceipt") + + fun asCard(): CardFeature = card.getOrThrow("card") + + fun asAccountHolder(): AccountHolderFeature = accountHolder.getOrThrow("accountHolder") + + fun asIpMetadata(): IpMetadataFeature = ipMetadata.getOrThrow("ipMetadata") + + fun asSpendVelocity(): SpendVelocityFeature = spendVelocity.getOrThrow("spendVelocity") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + authorization != null -> visitor.visitAuthorization(authorization) + authentication != null -> visitor.visitAuthentication(authentication) + tokenization != null -> visitor.visitTokenization(tokenization) + achReceipt != null -> visitor.visitAchReceipt(achReceipt) + card != null -> visitor.visitCard(card) + accountHolder != null -> visitor.visitAccountHolder(accountHolder) + ipMetadata != null -> visitor.visitIpMetadata(ipMetadata) + spendVelocity != null -> visitor.visitSpendVelocity(spendVelocity) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): RuleFeature = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitAuthorization(authorization: AuthorizationFeature) { + authorization.validate() + } + + override fun visitAuthentication(authentication: AuthenticationFeature) { + authentication.validate() + } + + override fun visitTokenization(tokenization: TokenizationFeature) { + tokenization.validate() + } + + override fun visitAchReceipt(achReceipt: AchReceiptFeature) { + achReceipt.validate() + } + + override fun visitCard(card: CardFeature) { + card.validate() + } + + override fun visitAccountHolder(accountHolder: AccountHolderFeature) { + accountHolder.validate() + } + + override fun visitIpMetadata(ipMetadata: IpMetadataFeature) { + ipMetadata.validate() + } + + override fun visitSpendVelocity(spendVelocity: SpendVelocityFeature) { + spendVelocity.validate() + } + } + ) + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + accept( + object : Visitor { + override fun visitAuthorization(authorization: AuthorizationFeature) = + authorization.validity() + + override fun visitAuthentication(authentication: AuthenticationFeature) = + authentication.validity() + + override fun visitTokenization(tokenization: TokenizationFeature) = + tokenization.validity() + + override fun visitAchReceipt(achReceipt: AchReceiptFeature) = achReceipt.validity() + + override fun visitCard(card: CardFeature) = card.validity() + + override fun visitAccountHolder(accountHolder: AccountHolderFeature) = + accountHolder.validity() + + override fun visitIpMetadata(ipMetadata: IpMetadataFeature) = ipMetadata.validity() + + override fun visitSpendVelocity(spendVelocity: SpendVelocityFeature) = + spendVelocity.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is RuleFeature && + authorization == other.authorization && + authentication == other.authentication && + tokenization == other.tokenization && + achReceipt == other.achReceipt && + card == other.card && + accountHolder == other.accountHolder && + ipMetadata == other.ipMetadata && + spendVelocity == other.spendVelocity + } + + override fun hashCode(): Int = + Objects.hash( + authorization, + authentication, + tokenization, + achReceipt, + card, + accountHolder, + ipMetadata, + spendVelocity, + ) + + override fun toString(): String = + when { + authorization != null -> "RuleFeature{authorization=$authorization}" + authentication != null -> "RuleFeature{authentication=$authentication}" + tokenization != null -> "RuleFeature{tokenization=$tokenization}" + achReceipt != null -> "RuleFeature{achReceipt=$achReceipt}" + card != null -> "RuleFeature{card=$card}" + accountHolder != null -> "RuleFeature{accountHolder=$accountHolder}" + ipMetadata != null -> "RuleFeature{ipMetadata=$ipMetadata}" + spendVelocity != null -> "RuleFeature{spendVelocity=$spendVelocity}" + _json != null -> "RuleFeature{_unknown=$_json}" + else -> throw IllegalStateException("Invalid RuleFeature") + } + + companion object { + + @JvmStatic + fun ofAuthorization(authorization: AuthorizationFeature) = + RuleFeature(authorization = authorization) + + @JvmStatic + fun ofAuthentication(authentication: AuthenticationFeature) = + RuleFeature(authentication = authentication) + + @JvmStatic + fun ofTokenization(tokenization: TokenizationFeature) = + RuleFeature(tokenization = tokenization) + + @JvmStatic + fun ofAchReceipt(achReceipt: AchReceiptFeature) = RuleFeature(achReceipt = achReceipt) + + @JvmStatic fun ofCard(card: CardFeature) = RuleFeature(card = card) + + @JvmStatic + fun ofAccountHolder(accountHolder: AccountHolderFeature) = + RuleFeature(accountHolder = accountHolder) + + @JvmStatic + fun ofIpMetadata(ipMetadata: IpMetadataFeature) = RuleFeature(ipMetadata = ipMetadata) + + @JvmStatic + fun ofSpendVelocity(spendVelocity: SpendVelocityFeature) = + RuleFeature(spendVelocity = spendVelocity) + } + + /** + * An interface that defines how to map each variant of [RuleFeature] to a value of type [T]. + */ + interface Visitor { + + fun visitAuthorization(authorization: AuthorizationFeature): T + + fun visitAuthentication(authentication: AuthenticationFeature): T + + fun visitTokenization(tokenization: TokenizationFeature): T + + fun visitAchReceipt(achReceipt: AchReceiptFeature): T + + fun visitCard(card: CardFeature): T + + fun visitAccountHolder(accountHolder: AccountHolderFeature): T + + fun visitIpMetadata(ipMetadata: IpMetadataFeature): T + + fun visitSpendVelocity(spendVelocity: SpendVelocityFeature): T + + /** + * Maps an unknown variant of [RuleFeature] to a value of type [T]. + * + * An instance of [RuleFeature] can contain an unknown variant if it was deserialized from + * data that doesn't match any known variant. For example, if the SDK is on an older version + * than the API, then the API may respond with new variants that the SDK is unaware of. + * + * @throws LithicInvalidDataException in the default implementation. + */ + fun unknown(json: JsonValue?): T { + throw LithicInvalidDataException("Unknown RuleFeature: $json") + } + } + + internal class Deserializer : BaseDeserializer(RuleFeature::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): RuleFeature { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + RuleFeature(authorization = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + RuleFeature(authentication = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + RuleFeature(tokenization = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + RuleFeature(achReceipt = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + RuleFeature(card = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + RuleFeature(accountHolder = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + RuleFeature(ipMetadata = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + RuleFeature(spendVelocity = it, _json = json) + }, + ) + .filterNotNull() + .allMaxBy { it.validity() } + .toList() + return when (bestMatches.size) { + // This can happen if what we're deserializing is completely incompatible with all + // the possible variants (e.g. deserializing from boolean). + 0 -> RuleFeature(_json = json) + 1 -> bestMatches.single() + // If there's more than one match with the highest validity, then use the first + // completely valid match, or simply the first match if none are completely valid. + else -> bestMatches.firstOrNull { it.isValid() } ?: bestMatches.first() + } + } + } + + internal class Serializer : BaseSerializer(RuleFeature::class) { + + override fun serialize( + value: RuleFeature, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.authorization != null -> generator.writeObject(value.authorization) + value.authentication != null -> generator.writeObject(value.authentication) + value.tokenization != null -> generator.writeObject(value.tokenization) + value.achReceipt != null -> generator.writeObject(value.achReceipt) + value.card != null -> generator.writeObject(value.card) + value.accountHolder != null -> generator.writeObject(value.accountHolder) + value.ipMetadata != null -> generator.writeObject(value.ipMetadata) + value.spendVelocity != null -> generator.writeObject(value.spendVelocity) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid RuleFeature") + } + } + } + + class AuthorizationFeature + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(type, name, mutableMapOf()) + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = type.getRequired("type") + + /** + * The variable name for this feature in the rule function signature + * + * @throws LithicInvalidDataException 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 [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 [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @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 [AuthorizationFeature]. + * + * The following fields are required: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AuthorizationFeature]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(authorizationFeature: AuthorizationFeature) = apply { + type = authorizationFeature.type + name = authorizationFeature.name + additionalProperties = authorizationFeature.additionalProperties.toMutableMap() + } + + 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 } + + /** The variable name for this feature in the rule function signature */ + 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 } + + 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 [AuthorizationFeature]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): AuthorizationFeature = + AuthorizationFeature( + checkRequired("type", type), + name, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): AuthorizationFeature = apply { + if (validated) { + return@apply + } + + type().validate() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + (type.asKnown().getOrNull()?.validity() ?: 0) + (if (name.asKnown().isPresent) 1 else 0) + + 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 AUTHORIZATION = of("AUTHORIZATION") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + AUTHORIZATION + } + + /** + * 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 { + AUTHORIZATION, + /** 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) { + AUTHORIZATION -> Value.AUTHORIZATION + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AUTHORIZATION -> Known.AUTHORIZATION + else -> throw LithicInvalidDataException("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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("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: LithicInvalidDataException) { + 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 AuthorizationFeature && + type == other.type && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(type, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AuthorizationFeature{type=$type, name=$name, additionalProperties=$additionalProperties}" + } + + class AuthenticationFeature + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(type, name, mutableMapOf()) + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = type.getRequired("type") + + /** + * The variable name for this feature in the rule function signature + * + * @throws LithicInvalidDataException 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 [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 [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @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 [AuthenticationFeature]. + * + * The following fields are required: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AuthenticationFeature]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(authenticationFeature: AuthenticationFeature) = apply { + type = authenticationFeature.type + name = authenticationFeature.name + additionalProperties = authenticationFeature.additionalProperties.toMutableMap() + } + + 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 } + + /** The variable name for this feature in the rule function signature */ + 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 } + + 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 [AuthenticationFeature]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): AuthenticationFeature = + AuthenticationFeature( + checkRequired("type", type), + name, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): AuthenticationFeature = apply { + if (validated) { + return@apply + } + + type().validate() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + (type.asKnown().getOrNull()?.validity() ?: 0) + (if (name.asKnown().isPresent) 1 else 0) + + 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 AUTHENTICATION = of("AUTHENTICATION") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + AUTHENTICATION + } + + /** + * 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 { + AUTHENTICATION, + /** 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) { + AUTHENTICATION -> Value.AUTHENTICATION + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AUTHENTICATION -> Known.AUTHENTICATION + else -> throw LithicInvalidDataException("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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("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: LithicInvalidDataException) { + 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 AuthenticationFeature && + type == other.type && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(type, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AuthenticationFeature{type=$type, name=$name, additionalProperties=$additionalProperties}" + } + + class TokenizationFeature + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(type, name, mutableMapOf()) + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = type.getRequired("type") + + /** + * The variable name for this feature in the rule function signature + * + * @throws LithicInvalidDataException 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 [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 [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @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 [TokenizationFeature]. + * + * The following fields are required: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TokenizationFeature]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(tokenizationFeature: TokenizationFeature) = apply { + type = tokenizationFeature.type + name = tokenizationFeature.name + additionalProperties = tokenizationFeature.additionalProperties.toMutableMap() + } + + 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 } + + /** The variable name for this feature in the rule function signature */ + 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 } + + 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 [TokenizationFeature]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TokenizationFeature = + TokenizationFeature( + checkRequired("type", type), + name, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): TokenizationFeature = apply { + if (validated) { + return@apply + } + + type().validate() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + (type.asKnown().getOrNull()?.validity() ?: 0) + (if (name.asKnown().isPresent) 1 else 0) + + 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 TOKENIZATION = of("TOKENIZATION") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + TOKENIZATION + } + + /** + * 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 { + TOKENIZATION, + /** 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) { + TOKENIZATION -> Value.TOKENIZATION + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + TOKENIZATION -> Known.TOKENIZATION + else -> throw LithicInvalidDataException("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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("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: LithicInvalidDataException) { + 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 TokenizationFeature && + type == other.type && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(type, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "TokenizationFeature{type=$type, name=$name, additionalProperties=$additionalProperties}" + } + + class AchReceiptFeature + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(type, name, mutableMapOf()) + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = type.getRequired("type") + + /** + * The variable name for this feature in the rule function signature + * + * @throws LithicInvalidDataException 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 [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 [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @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 [AchReceiptFeature]. + * + * The following fields are required: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AchReceiptFeature]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(achReceiptFeature: AchReceiptFeature) = apply { + type = achReceiptFeature.type + name = achReceiptFeature.name + additionalProperties = achReceiptFeature.additionalProperties.toMutableMap() + } + + 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 } + + /** The variable name for this feature in the rule function signature */ + 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 } + + 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 [AchReceiptFeature]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): AchReceiptFeature = + AchReceiptFeature( + checkRequired("type", type), + name, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): AchReceiptFeature = apply { + if (validated) { + return@apply + } + + type().validate() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + (type.asKnown().getOrNull()?.validity() ?: 0) + (if (name.asKnown().isPresent) 1 else 0) + + 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 ACH_RECEIPT = of("ACH_RECEIPT") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + ACH_RECEIPT + } + + /** + * 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 { + ACH_RECEIPT, + /** 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) { + ACH_RECEIPT -> Value.ACH_RECEIPT + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + ACH_RECEIPT -> Known.ACH_RECEIPT + else -> throw LithicInvalidDataException("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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("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: LithicInvalidDataException) { + 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 AchReceiptFeature && + type == other.type && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(type, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AchReceiptFeature{type=$type, name=$name, additionalProperties=$additionalProperties}" + } + + class CardFeature + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(type, name, mutableMapOf()) + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = type.getRequired("type") + + /** + * The variable name for this feature in the rule function signature + * + * @throws LithicInvalidDataException 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 [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 [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @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 [CardFeature]. + * + * The following fields are required: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CardFeature]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(cardFeature: CardFeature) = apply { + type = cardFeature.type + name = cardFeature.name + additionalProperties = cardFeature.additionalProperties.toMutableMap() + } + + 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 } + + /** The variable name for this feature in the rule function signature */ + 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 } + + 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 [CardFeature]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): CardFeature = + CardFeature(checkRequired("type", type), name, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): CardFeature = apply { + if (validated) { + return@apply + } + + type().validate() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + (type.asKnown().getOrNull()?.validity() ?: 0) + (if (name.asKnown().isPresent) 1 else 0) + + 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 CARD = of("CARD") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + CARD + } + + /** + * 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 { + CARD, + /** 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) { + CARD -> Value.CARD + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + CARD -> Known.CARD + else -> throw LithicInvalidDataException("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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("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: LithicInvalidDataException) { + 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 CardFeature && + type == other.type && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(type, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CardFeature{type=$type, name=$name, additionalProperties=$additionalProperties}" + } + + class AccountHolderFeature + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(type, name, mutableMapOf()) + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = type.getRequired("type") + + /** + * The variable name for this feature in the rule function signature + * + * @throws LithicInvalidDataException 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 [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 [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @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 [AccountHolderFeature]. + * + * The following fields are required: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [AccountHolderFeature]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(accountHolderFeature: AccountHolderFeature) = apply { + type = accountHolderFeature.type + name = accountHolderFeature.name + additionalProperties = accountHolderFeature.additionalProperties.toMutableMap() + } + + 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 } + + /** The variable name for this feature in the rule function signature */ + 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 } + + 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 [AccountHolderFeature]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): AccountHolderFeature = + AccountHolderFeature( + checkRequired("type", type), + name, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): AccountHolderFeature = apply { + if (validated) { + return@apply + } + + type().validate() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + (type.asKnown().getOrNull()?.validity() ?: 0) + (if (name.asKnown().isPresent) 1 else 0) + + 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 ACCOUNT_HOLDER = of("ACCOUNT_HOLDER") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + ACCOUNT_HOLDER + } + + /** + * 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 { + ACCOUNT_HOLDER, + /** 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) { + ACCOUNT_HOLDER -> Value.ACCOUNT_HOLDER + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + ACCOUNT_HOLDER -> Known.ACCOUNT_HOLDER + else -> throw LithicInvalidDataException("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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("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: LithicInvalidDataException) { + 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 AccountHolderFeature && + type == other.type && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(type, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "AccountHolderFeature{type=$type, name=$name, additionalProperties=$additionalProperties}" + } + + class IpMetadataFeature + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val type: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(type, name, mutableMapOf()) + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = type.getRequired("type") + + /** + * The variable name for this feature in the rule function signature + * + * @throws LithicInvalidDataException 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 [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 [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @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 [IpMetadataFeature]. + * + * The following fields are required: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [IpMetadataFeature]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(ipMetadataFeature: IpMetadataFeature) = apply { + type = ipMetadataFeature.type + name = ipMetadataFeature.name + additionalProperties = ipMetadataFeature.additionalProperties.toMutableMap() + } + + 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 } + + /** The variable name for this feature in the rule function signature */ + 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 } + + 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 [IpMetadataFeature]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): IpMetadataFeature = + IpMetadataFeature( + checkRequired("type", type), + name, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): IpMetadataFeature = apply { + if (validated) { + return@apply + } + + type().validate() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + (type.asKnown().getOrNull()?.validity() ?: 0) + (if (name.asKnown().isPresent) 1 else 0) + + 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 IP_METADATA = of("IP_METADATA") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + IP_METADATA + } + + /** + * 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 { + IP_METADATA, + /** 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) { + IP_METADATA -> Value.IP_METADATA + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + IP_METADATA -> Known.IP_METADATA + else -> throw LithicInvalidDataException("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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("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: LithicInvalidDataException) { + 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 IpMetadataFeature && + type == other.type && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(type, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "IpMetadataFeature{type=$type, name=$name, additionalProperties=$additionalProperties}" + } + + class SpendVelocityFeature + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val period: JsonField, + private val scope: JsonField, + private val type: JsonField, + private val filters: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("period") + @ExcludeMissing + period: JsonField = JsonMissing.of(), + @JsonProperty("scope") + @ExcludeMissing + scope: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("filters") + @ExcludeMissing + filters: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(period, scope, type, filters, name, mutableMapOf()) + + /** + * Velocity over the current day since 00:00 / 12 AM in Eastern Time + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun period(): VelocityLimitPeriod = period.getRequired("period") + + /** + * The scope the velocity is calculated for + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun scope(): VelocityScope = scope.getRequired("scope") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun type(): Type = type.getRequired("type") + + /** + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun filters(): Optional = filters.getOptional("filters") + + /** + * The variable name for this feature in the rule function signature + * + * @throws LithicInvalidDataException 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 [period]. + * + * Unlike [period], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("period") + @ExcludeMissing + fun _period(): JsonField = period + + /** + * Returns the raw JSON value of [scope]. + * + * Unlike [scope], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("scope") @ExcludeMissing fun _scope(): JsonField = scope + + /** + * 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 [filters]. + * + * Unlike [filters], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("filters") + @ExcludeMissing + fun _filters(): JsonField = filters + + /** + * 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 + + @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 [SpendVelocityFeature]. + * + * The following fields are required: + * ```java + * .period() + * .scope() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [SpendVelocityFeature]. */ + class Builder internal constructor() { + + private var period: JsonField? = null + private var scope: JsonField? = null + private var type: JsonField? = null + private var filters: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(spendVelocityFeature: SpendVelocityFeature) = apply { + period = spendVelocityFeature.period + scope = spendVelocityFeature.scope + type = spendVelocityFeature.type + filters = spendVelocityFeature.filters + name = spendVelocityFeature.name + additionalProperties = spendVelocityFeature.additionalProperties.toMutableMap() + } + + /** Velocity over the current day since 00:00 / 12 AM in Eastern Time */ + fun period(period: VelocityLimitPeriod) = period(JsonField.of(period)) + + /** + * Sets [Builder.period] to an arbitrary JSON value. + * + * You should usually call [Builder.period] with a well-typed [VelocityLimitPeriod] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun period(period: JsonField) = apply { this.period = period } + + /** + * Alias for calling [period] with + * `VelocityLimitPeriod.ofTrailingWindowObject(trailingWindowObject)`. + */ + fun period(trailingWindowObject: VelocityLimitPeriod.TrailingWindowObject) = + period(VelocityLimitPeriod.ofTrailingWindowObject(trailingWindowObject)) + + /** + * Alias for calling [period] with + * `VelocityLimitPeriod.ofFixedWindowDay(fixedWindowDay)`. + */ + fun period(fixedWindowDay: VelocityLimitPeriod.FixedWindowDay) = + period(VelocityLimitPeriod.ofFixedWindowDay(fixedWindowDay)) + + /** + * Alias for calling [period] with + * `VelocityLimitPeriod.ofFixedWindowWeek(fixedWindowWeek)`. + */ + fun period(fixedWindowWeek: VelocityLimitPeriod.FixedWindowWeek) = + period(VelocityLimitPeriod.ofFixedWindowWeek(fixedWindowWeek)) + + /** + * Alias for calling [period] with + * `VelocityLimitPeriod.ofFixedWindowMonth(fixedWindowMonth)`. + */ + fun period(fixedWindowMonth: VelocityLimitPeriod.FixedWindowMonth) = + period(VelocityLimitPeriod.ofFixedWindowMonth(fixedWindowMonth)) + + /** + * Alias for calling [period] with + * `VelocityLimitPeriod.ofFixedWindowYear(fixedWindowYear)`. + */ + fun period(fixedWindowYear: VelocityLimitPeriod.FixedWindowYear) = + period(VelocityLimitPeriod.ofFixedWindowYear(fixedWindowYear)) + + /** The scope the velocity is calculated for */ + fun scope(scope: VelocityScope) = scope(JsonField.of(scope)) + + /** + * Sets [Builder.scope] to an arbitrary JSON value. + * + * You should usually call [Builder.scope] with a well-typed [VelocityScope] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun scope(scope: JsonField) = apply { this.scope = scope } + + 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 } + + fun filters(filters: VelocityLimitFilters) = filters(JsonField.of(filters)) + + /** + * Sets [Builder.filters] to an arbitrary JSON value. + * + * You should usually call [Builder.filters] with a well-typed [VelocityLimitFilters] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun filters(filters: JsonField) = apply { this.filters = filters } + + /** The variable name for this feature in the rule function signature */ + 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 } + + 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 [SpendVelocityFeature]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .period() + * .scope() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): SpendVelocityFeature = + SpendVelocityFeature( + checkRequired("period", period), + checkRequired("scope", scope), + checkRequired("type", type), + filters, + name, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): SpendVelocityFeature = apply { + if (validated) { + return@apply + } + + period().validate() + scope().validate() + type().validate() + filters().ifPresent { it.validate() } + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + (period.asKnown().getOrNull()?.validity() ?: 0) + + (scope.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (filters.asKnown().getOrNull()?.validity() ?: 0) + + (if (name.asKnown().isPresent) 1 else 0) + + /** The scope the velocity is calculated for */ + class VelocityScope @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 CARD = of("CARD") + + @JvmField val ACCOUNT = of("ACCOUNT") + + @JvmStatic fun of(value: String) = VelocityScope(JsonField.of(value)) + } + + /** An enum containing [VelocityScope]'s known values. */ + enum class Known { + CARD, + ACCOUNT, + } + + /** + * An enum containing [VelocityScope]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [VelocityScope] 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 { + CARD, + ACCOUNT, + /** + * An enum member indicating that [VelocityScope] 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) { + CARD -> Value.CARD + ACCOUNT -> Value.ACCOUNT + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + CARD -> Known.CARD + ACCOUNT -> Known.ACCOUNT + else -> throw LithicInvalidDataException("Unknown VelocityScope: $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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + fun validate(): VelocityScope = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 VelocityScope && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + 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 SPEND_VELOCITY = of("SPEND_VELOCITY") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + SPEND_VELOCITY + } + + /** + * 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 { + SPEND_VELOCITY, + /** 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) { + SPEND_VELOCITY -> Value.SPEND_VELOCITY + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + SPEND_VELOCITY -> Known.SPEND_VELOCITY + else -> throw LithicInvalidDataException("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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + LithicInvalidDataException("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: LithicInvalidDataException) { + 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 SpendVelocityFeature && + period == other.period && + scope == other.scope && + type == other.type && + filters == other.filters && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(period, scope, type, filters, name, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "SpendVelocityFeature{period=$period, scope=$scope, type=$type, filters=$filters, name=$name, additionalProperties=$additionalProperties}" + } +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/TypescriptCodeParameters.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/TypescriptCodeParameters.kt new file mode 100644 index 00000000..e0b86cc8 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/TypescriptCodeParameters.kt @@ -0,0 +1,271 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkKnown +import com.lithic.api.core.checkRequired +import com.lithic.api.core.toImmutable +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +/** Parameters for defining a TypeScript code rule */ +class TypescriptCodeParameters +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val code: JsonField, + private val features: JsonField>, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("code") @ExcludeMissing code: JsonField = JsonMissing.of(), + @JsonProperty("features") + @ExcludeMissing + features: JsonField> = JsonMissing.of(), + ) : this(code, features, mutableMapOf()) + + /** + * The TypeScript source code of the rule. Must define a `rule()` function that accepts the + * declared features as positional arguments (in the same order as the `features` array) and + * returns an array of actions. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun code(): String = code.getRequired("code") + + /** + * Features available to the TypeScript code at evaluation time + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun features(): List = features.getRequired("features") + + /** + * Returns the raw JSON value of [code]. + * + * Unlike [code], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("code") @ExcludeMissing fun _code(): JsonField = code + + /** + * Returns the raw JSON value of [features]. + * + * Unlike [features], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("features") + @ExcludeMissing + fun _features(): JsonField> = features + + @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 [TypescriptCodeParameters]. + * + * The following fields are required: + * ```java + * .code() + * .features() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TypescriptCodeParameters]. */ + class Builder internal constructor() { + + private var code: JsonField? = null + private var features: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(typescriptCodeParameters: TypescriptCodeParameters) = apply { + code = typescriptCodeParameters.code + features = typescriptCodeParameters.features.map { it.toMutableList() } + additionalProperties = typescriptCodeParameters.additionalProperties.toMutableMap() + } + + /** + * The TypeScript source code of the rule. Must define a `rule()` function that accepts the + * declared features as positional arguments (in the same order as the `features` array) and + * returns an array of actions. + */ + fun code(code: String) = code(JsonField.of(code)) + + /** + * Sets [Builder.code] to an arbitrary JSON value. + * + * You should usually call [Builder.code] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun code(code: JsonField) = apply { this.code = code } + + /** Features available to the TypeScript code at evaluation time */ + fun features(features: List) = features(JsonField.of(features)) + + /** + * Sets [Builder.features] to an arbitrary JSON value. + * + * You should usually call [Builder.features] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun features(features: JsonField>) = apply { + this.features = features.map { it.toMutableList() } + } + + /** + * Adds a single [RuleFeature] to [features]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addFeature(feature: RuleFeature) = apply { + features = + (features ?: JsonField.of(mutableListOf())).also { + checkKnown("features", it).add(feature) + } + } + + /** Alias for calling [addFeature] with `RuleFeature.ofAuthorization(authorization)`. */ + fun addFeature(authorization: RuleFeature.AuthorizationFeature) = + addFeature(RuleFeature.ofAuthorization(authorization)) + + /** Alias for calling [addFeature] with `RuleFeature.ofAuthentication(authentication)`. */ + fun addFeature(authentication: RuleFeature.AuthenticationFeature) = + addFeature(RuleFeature.ofAuthentication(authentication)) + + /** Alias for calling [addFeature] with `RuleFeature.ofTokenization(tokenization)`. */ + fun addFeature(tokenization: RuleFeature.TokenizationFeature) = + addFeature(RuleFeature.ofTokenization(tokenization)) + + /** Alias for calling [addFeature] with `RuleFeature.ofAchReceipt(achReceipt)`. */ + fun addFeature(achReceipt: RuleFeature.AchReceiptFeature) = + addFeature(RuleFeature.ofAchReceipt(achReceipt)) + + /** Alias for calling [addFeature] with `RuleFeature.ofCard(card)`. */ + fun addFeature(card: RuleFeature.CardFeature) = addFeature(RuleFeature.ofCard(card)) + + /** Alias for calling [addFeature] with `RuleFeature.ofAccountHolder(accountHolder)`. */ + fun addFeature(accountHolder: RuleFeature.AccountHolderFeature) = + addFeature(RuleFeature.ofAccountHolder(accountHolder)) + + /** Alias for calling [addFeature] with `RuleFeature.ofIpMetadata(ipMetadata)`. */ + fun addFeature(ipMetadata: RuleFeature.IpMetadataFeature) = + addFeature(RuleFeature.ofIpMetadata(ipMetadata)) + + /** Alias for calling [addFeature] with `RuleFeature.ofSpendVelocity(spendVelocity)`. */ + fun addFeature(spendVelocity: RuleFeature.SpendVelocityFeature) = + addFeature(RuleFeature.ofSpendVelocity(spendVelocity)) + + 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 [TypescriptCodeParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .code() + * .features() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TypescriptCodeParameters = + TypescriptCodeParameters( + checkRequired("code", code), + checkRequired("features", features).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): TypescriptCodeParameters = apply { + if (validated) { + return@apply + } + + code() + features().forEach { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 (code.asKnown().isPresent) 1 else 0) + + (features.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TypescriptCodeParameters && + code == other.code && + features == other.features && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(code, features, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "TypescriptCodeParameters{code=$code, features=$features, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2RetrieveFeaturesResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2RetrieveFeaturesResponse.kt index 9eb3f21f..18a813a4 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2RetrieveFeaturesResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2RetrieveFeaturesResponse.kt @@ -18,7 +18,6 @@ import com.lithic.api.errors.LithicInvalidDataException import java.time.OffsetDateTime import java.util.Collections import java.util.Objects -import java.util.Optional import kotlin.jvm.optionals.getOrNull class V2RetrieveFeaturesResponse @@ -511,690 +510,6 @@ private constructor( (scope.asKnown().getOrNull()?.validity() ?: 0) + (value.asKnown().getOrNull()?.validity() ?: 0) - class VelocityLimitFilters - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val excludeCountries: JsonField>, - private val excludeMccs: JsonField>, - private val includeCountries: JsonField>, - private val includeMccs: JsonField>, - private val includePanEntryModes: JsonField>, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("exclude_countries") - @ExcludeMissing - excludeCountries: JsonField> = JsonMissing.of(), - @JsonProperty("exclude_mccs") - @ExcludeMissing - excludeMccs: JsonField> = JsonMissing.of(), - @JsonProperty("include_countries") - @ExcludeMissing - includeCountries: JsonField> = JsonMissing.of(), - @JsonProperty("include_mccs") - @ExcludeMissing - includeMccs: JsonField> = JsonMissing.of(), - @JsonProperty("include_pan_entry_modes") - @ExcludeMissing - includePanEntryModes: JsonField> = JsonMissing.of(), - ) : this( - excludeCountries, - excludeMccs, - includeCountries, - includeMccs, - includePanEntryModes, - mutableMapOf(), - ) - - /** - * ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. - * Transactions matching any of the provided will be excluded from the calculated - * velocity. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun excludeCountries(): Optional> = - excludeCountries.getOptional("exclude_countries") - - /** - * Merchant Category Codes to exclude from the velocity calculation. Transactions - * matching this MCC will be excluded from the calculated velocity. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun excludeMccs(): Optional> = excludeMccs.getOptional("exclude_mccs") - - /** - * ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. Transactions - * not matching any of the provided will not be included in the calculated velocity. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun includeCountries(): Optional> = - includeCountries.getOptional("include_countries") - - /** - * Merchant Category Codes to include in the velocity calculation. Transactions not - * matching this MCC will not be included in the calculated velocity. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun includeMccs(): Optional> = includeMccs.getOptional("include_mccs") - - /** - * PAN entry modes to include in the velocity calculation. Transactions not matching any - * of the provided will not be included in the calculated velocity. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun includePanEntryModes(): Optional> = - includePanEntryModes.getOptional("include_pan_entry_modes") - - /** - * Returns the raw JSON value of [excludeCountries]. - * - * Unlike [excludeCountries], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("exclude_countries") - @ExcludeMissing - fun _excludeCountries(): JsonField> = excludeCountries - - /** - * Returns the raw JSON value of [excludeMccs]. - * - * Unlike [excludeMccs], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("exclude_mccs") - @ExcludeMissing - fun _excludeMccs(): JsonField> = excludeMccs - - /** - * Returns the raw JSON value of [includeCountries]. - * - * Unlike [includeCountries], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("include_countries") - @ExcludeMissing - fun _includeCountries(): JsonField> = includeCountries - - /** - * Returns the raw JSON value of [includeMccs]. - * - * Unlike [includeMccs], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("include_mccs") - @ExcludeMissing - fun _includeMccs(): JsonField> = includeMccs - - /** - * Returns the raw JSON value of [includePanEntryModes]. - * - * Unlike [includePanEntryModes], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("include_pan_entry_modes") - @ExcludeMissing - fun _includePanEntryModes(): JsonField> = includePanEntryModes - - @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 [VelocityLimitFilters]. - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [VelocityLimitFilters]. */ - class Builder internal constructor() { - - private var excludeCountries: JsonField>? = null - private var excludeMccs: JsonField>? = null - private var includeCountries: JsonField>? = null - private var includeMccs: JsonField>? = null - private var includePanEntryModes: JsonField>? = - null - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(velocityLimitFilters: VelocityLimitFilters) = apply { - excludeCountries = - velocityLimitFilters.excludeCountries.map { it.toMutableList() } - excludeMccs = velocityLimitFilters.excludeMccs.map { it.toMutableList() } - includeCountries = - velocityLimitFilters.includeCountries.map { it.toMutableList() } - includeMccs = velocityLimitFilters.includeMccs.map { it.toMutableList() } - includePanEntryModes = - velocityLimitFilters.includePanEntryModes.map { it.toMutableList() } - additionalProperties = velocityLimitFilters.additionalProperties.toMutableMap() - } - - /** - * ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. - * Transactions matching any of the provided will be excluded from the calculated - * velocity. - */ - fun excludeCountries(excludeCountries: List?) = - excludeCountries(JsonField.ofNullable(excludeCountries)) - - /** - * Alias for calling [Builder.excludeCountries] with - * `excludeCountries.orElse(null)`. - */ - fun excludeCountries(excludeCountries: Optional>) = - excludeCountries(excludeCountries.getOrNull()) - - /** - * Sets [Builder.excludeCountries] to an arbitrary JSON value. - * - * You should usually call [Builder.excludeCountries] with a well-typed - * `List` value instead. This method is primarily for setting the field to - * an undocumented or not yet supported value. - */ - fun excludeCountries(excludeCountries: JsonField>) = apply { - this.excludeCountries = excludeCountries.map { it.toMutableList() } - } - - /** - * Adds a single [String] to [excludeCountries]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addExcludeCountry(excludeCountry: String) = apply { - excludeCountries = - (excludeCountries ?: JsonField.of(mutableListOf())).also { - checkKnown("excludeCountries", it).add(excludeCountry) - } - } - - /** - * Merchant Category Codes to exclude from the velocity calculation. Transactions - * matching this MCC will be excluded from the calculated velocity. - */ - fun excludeMccs(excludeMccs: List?) = - excludeMccs(JsonField.ofNullable(excludeMccs)) - - /** Alias for calling [Builder.excludeMccs] with `excludeMccs.orElse(null)`. */ - fun excludeMccs(excludeMccs: Optional>) = - excludeMccs(excludeMccs.getOrNull()) - - /** - * Sets [Builder.excludeMccs] to an arbitrary JSON value. - * - * You should usually call [Builder.excludeMccs] with a well-typed `List` - * value instead. This method is primarily for setting the field to an undocumented - * or not yet supported value. - */ - fun excludeMccs(excludeMccs: JsonField>) = apply { - this.excludeMccs = excludeMccs.map { it.toMutableList() } - } - - /** - * Adds a single [String] to [excludeMccs]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addExcludeMcc(excludeMcc: String) = apply { - excludeMccs = - (excludeMccs ?: JsonField.of(mutableListOf())).also { - checkKnown("excludeMccs", it).add(excludeMcc) - } - } - - /** - * ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. - * Transactions not matching any of the provided will not be included in the - * calculated velocity. - */ - fun includeCountries(includeCountries: List?) = - includeCountries(JsonField.ofNullable(includeCountries)) - - /** - * Alias for calling [Builder.includeCountries] with - * `includeCountries.orElse(null)`. - */ - fun includeCountries(includeCountries: Optional>) = - includeCountries(includeCountries.getOrNull()) - - /** - * Sets [Builder.includeCountries] to an arbitrary JSON value. - * - * You should usually call [Builder.includeCountries] with a well-typed - * `List` value instead. This method is primarily for setting the field to - * an undocumented or not yet supported value. - */ - fun includeCountries(includeCountries: JsonField>) = apply { - this.includeCountries = includeCountries.map { it.toMutableList() } - } - - /** - * Adds a single [String] to [includeCountries]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addIncludeCountry(includeCountry: String) = apply { - includeCountries = - (includeCountries ?: JsonField.of(mutableListOf())).also { - checkKnown("includeCountries", it).add(includeCountry) - } - } - - /** - * Merchant Category Codes to include in the velocity calculation. Transactions not - * matching this MCC will not be included in the calculated velocity. - */ - fun includeMccs(includeMccs: List?) = - includeMccs(JsonField.ofNullable(includeMccs)) - - /** Alias for calling [Builder.includeMccs] with `includeMccs.orElse(null)`. */ - fun includeMccs(includeMccs: Optional>) = - includeMccs(includeMccs.getOrNull()) - - /** - * Sets [Builder.includeMccs] to an arbitrary JSON value. - * - * You should usually call [Builder.includeMccs] with a well-typed `List` - * value instead. This method is primarily for setting the field to an undocumented - * or not yet supported value. - */ - fun includeMccs(includeMccs: JsonField>) = apply { - this.includeMccs = includeMccs.map { it.toMutableList() } - } - - /** - * Adds a single [String] to [includeMccs]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addIncludeMcc(includeMcc: String) = apply { - includeMccs = - (includeMccs ?: JsonField.of(mutableListOf())).also { - checkKnown("includeMccs", it).add(includeMcc) - } - } - - /** - * PAN entry modes to include in the velocity calculation. Transactions not matching - * any of the provided will not be included in the calculated velocity. - */ - fun includePanEntryModes(includePanEntryModes: List?) = - includePanEntryModes(JsonField.ofNullable(includePanEntryModes)) - - /** - * Alias for calling [Builder.includePanEntryModes] with - * `includePanEntryModes.orElse(null)`. - */ - fun includePanEntryModes( - includePanEntryModes: Optional> - ) = includePanEntryModes(includePanEntryModes.getOrNull()) - - /** - * Sets [Builder.includePanEntryModes] to an arbitrary JSON value. - * - * You should usually call [Builder.includePanEntryModes] with a well-typed - * `List` value instead. This method is primarily for setting - * the field to an undocumented or not yet supported value. - */ - fun includePanEntryModes( - includePanEntryModes: JsonField> - ) = apply { - this.includePanEntryModes = includePanEntryModes.map { it.toMutableList() } - } - - /** - * Adds a single [IncludePanEntryMode] to [includePanEntryModes]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addIncludePanEntryMode(includePanEntryMode: IncludePanEntryMode) = apply { - includePanEntryModes = - (includePanEntryModes ?: JsonField.of(mutableListOf())).also { - checkKnown("includePanEntryModes", it).add(includePanEntryMode) - } - } - - 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 [VelocityLimitFilters]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): VelocityLimitFilters = - VelocityLimitFilters( - (excludeCountries ?: JsonMissing.of()).map { it.toImmutable() }, - (excludeMccs ?: JsonMissing.of()).map { it.toImmutable() }, - (includeCountries ?: JsonMissing.of()).map { it.toImmutable() }, - (includeMccs ?: JsonMissing.of()).map { it.toImmutable() }, - (includePanEntryModes ?: JsonMissing.of()).map { it.toImmutable() }, - additionalProperties.toMutableMap(), - ) - } - - private var validated: Boolean = false - - fun validate(): VelocityLimitFilters = apply { - if (validated) { - return@apply - } - - excludeCountries() - excludeMccs() - includeCountries() - includeMccs() - includePanEntryModes().ifPresent { it.forEach { it.validate() } } - validated = true - } - - fun isValid(): Boolean = - try { - validate() - true - } catch (e: LithicInvalidDataException) { - 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 = - (excludeCountries.asKnown().getOrNull()?.size ?: 0) + - (excludeMccs.asKnown().getOrNull()?.size ?: 0) + - (includeCountries.asKnown().getOrNull()?.size ?: 0) + - (includeMccs.asKnown().getOrNull()?.size ?: 0) + - (includePanEntryModes.asKnown().getOrNull()?.sumOf { it.validity().toInt() } - ?: 0) - - class IncludePanEntryMode - @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 AUTO_ENTRY = of("AUTO_ENTRY") - - @JvmField val BAR_CODE = of("BAR_CODE") - - @JvmField val CONTACTLESS = of("CONTACTLESS") - - @JvmField val CREDENTIAL_ON_FILE = of("CREDENTIAL_ON_FILE") - - @JvmField val ECOMMERCE = of("ECOMMERCE") - - @JvmField val ERROR_KEYED = of("ERROR_KEYED") - - @JvmField val ERROR_MAGNETIC_STRIPE = of("ERROR_MAGNETIC_STRIPE") - - @JvmField val ICC = of("ICC") - - @JvmField val KEY_ENTERED = of("KEY_ENTERED") - - @JvmField val MAGNETIC_STRIPE = of("MAGNETIC_STRIPE") - - @JvmField val MANUAL = of("MANUAL") - - @JvmField val OCR = of("OCR") - - @JvmField val SECURE_CARDLESS = of("SECURE_CARDLESS") - - @JvmField val UNSPECIFIED = of("UNSPECIFIED") - - @JvmField val UNKNOWN = of("UNKNOWN") - - @JvmStatic fun of(value: String) = IncludePanEntryMode(JsonField.of(value)) - } - - /** An enum containing [IncludePanEntryMode]'s known values. */ - enum class Known { - AUTO_ENTRY, - BAR_CODE, - CONTACTLESS, - CREDENTIAL_ON_FILE, - ECOMMERCE, - ERROR_KEYED, - ERROR_MAGNETIC_STRIPE, - ICC, - KEY_ENTERED, - MAGNETIC_STRIPE, - MANUAL, - OCR, - SECURE_CARDLESS, - UNSPECIFIED, - UNKNOWN, - } - - /** - * An enum containing [IncludePanEntryMode]'s known values, as well as an [_UNKNOWN] - * member. - * - * An instance of [IncludePanEntryMode] 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 { - AUTO_ENTRY, - BAR_CODE, - CONTACTLESS, - CREDENTIAL_ON_FILE, - ECOMMERCE, - ERROR_KEYED, - ERROR_MAGNETIC_STRIPE, - ICC, - KEY_ENTERED, - MAGNETIC_STRIPE, - MANUAL, - OCR, - SECURE_CARDLESS, - UNSPECIFIED, - UNKNOWN, - /** - * An enum member indicating that [IncludePanEntryMode] 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) { - AUTO_ENTRY -> Value.AUTO_ENTRY - BAR_CODE -> Value.BAR_CODE - CONTACTLESS -> Value.CONTACTLESS - CREDENTIAL_ON_FILE -> Value.CREDENTIAL_ON_FILE - ECOMMERCE -> Value.ECOMMERCE - ERROR_KEYED -> Value.ERROR_KEYED - ERROR_MAGNETIC_STRIPE -> Value.ERROR_MAGNETIC_STRIPE - ICC -> Value.ICC - KEY_ENTERED -> Value.KEY_ENTERED - MAGNETIC_STRIPE -> Value.MAGNETIC_STRIPE - MANUAL -> Value.MANUAL - OCR -> Value.OCR - SECURE_CARDLESS -> Value.SECURE_CARDLESS - UNSPECIFIED -> Value.UNSPECIFIED - 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 LithicInvalidDataException if this class instance's value is a not a - * known member. - */ - fun known(): Known = - when (this) { - AUTO_ENTRY -> Known.AUTO_ENTRY - BAR_CODE -> Known.BAR_CODE - CONTACTLESS -> Known.CONTACTLESS - CREDENTIAL_ON_FILE -> Known.CREDENTIAL_ON_FILE - ECOMMERCE -> Known.ECOMMERCE - ERROR_KEYED -> Known.ERROR_KEYED - ERROR_MAGNETIC_STRIPE -> Known.ERROR_MAGNETIC_STRIPE - ICC -> Known.ICC - KEY_ENTERED -> Known.KEY_ENTERED - MAGNETIC_STRIPE -> Known.MAGNETIC_STRIPE - MANUAL -> Known.MANUAL - OCR -> Known.OCR - SECURE_CARDLESS -> Known.SECURE_CARDLESS - UNSPECIFIED -> Known.UNSPECIFIED - UNKNOWN -> Known.UNKNOWN - else -> - throw LithicInvalidDataException("Unknown IncludePanEntryMode: $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 LithicInvalidDataException if this class instance's value does not have - * the expected primitive type. - */ - fun asString(): String = - _value().asString().orElseThrow { - LithicInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): IncludePanEntryMode = apply { - if (validated) { - return@apply - } - - known() - validated = true - } - - fun isValid(): Boolean = - try { - validate() - true - } catch (e: LithicInvalidDataException) { - 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 IncludePanEntryMode && 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 VelocityLimitFilters && - excludeCountries == other.excludeCountries && - excludeMccs == other.excludeMccs && - includeCountries == other.includeCountries && - includeMccs == other.includeMccs && - includePanEntryModes == other.includePanEntryModes && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash( - excludeCountries, - excludeMccs, - includeCountries, - includeMccs, - includePanEntryModes, - additionalProperties, - ) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "VelocityLimitFilters{excludeCountries=$excludeCountries, excludeMccs=$excludeMccs, includeCountries=$includeCountries, includeMccs=$includeMccs, includePanEntryModes=$includePanEntryModes, additionalProperties=$additionalProperties}" - } - /** The scope the velocity is calculated for */ class VelocityScope @JsonCreator private constructor(private val value: JsonField) : Enum { diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitFilters.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitFilters.kt new file mode 100644 index 00000000..d1cccd43 --- /dev/null +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitFilters.kt @@ -0,0 +1,672 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.lithic.api.core.Enum +import com.lithic.api.core.ExcludeMissing +import com.lithic.api.core.JsonField +import com.lithic.api.core.JsonMissing +import com.lithic.api.core.JsonValue +import com.lithic.api.core.checkKnown +import com.lithic.api.core.toImmutable +import com.lithic.api.errors.LithicInvalidDataException +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class VelocityLimitFilters +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val excludeCountries: JsonField>, + private val excludeMccs: JsonField>, + private val includeCountries: JsonField>, + private val includeMccs: JsonField>, + private val includePanEntryModes: JsonField>, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("exclude_countries") + @ExcludeMissing + excludeCountries: JsonField> = JsonMissing.of(), + @JsonProperty("exclude_mccs") + @ExcludeMissing + excludeMccs: JsonField> = JsonMissing.of(), + @JsonProperty("include_countries") + @ExcludeMissing + includeCountries: JsonField> = JsonMissing.of(), + @JsonProperty("include_mccs") + @ExcludeMissing + includeMccs: JsonField> = JsonMissing.of(), + @JsonProperty("include_pan_entry_modes") + @ExcludeMissing + includePanEntryModes: JsonField> = JsonMissing.of(), + ) : this( + excludeCountries, + excludeMccs, + includeCountries, + includeMccs, + includePanEntryModes, + mutableMapOf(), + ) + + /** + * ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. Transactions + * matching any of the provided will be excluded from the calculated velocity. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun excludeCountries(): Optional> = + excludeCountries.getOptional("exclude_countries") + + /** + * Merchant Category Codes to exclude from the velocity calculation. Transactions matching this + * MCC will be excluded from the calculated velocity. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun excludeMccs(): Optional> = excludeMccs.getOptional("exclude_mccs") + + /** + * ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. Transactions not + * matching any of the provided will not be included in the calculated velocity. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun includeCountries(): Optional> = + includeCountries.getOptional("include_countries") + + /** + * Merchant Category Codes to include in the velocity calculation. Transactions not matching + * this MCC will not be included in the calculated velocity. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun includeMccs(): Optional> = includeMccs.getOptional("include_mccs") + + /** + * PAN entry modes to include in the velocity calculation. Transactions not matching any of the + * provided will not be included in the calculated velocity. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun includePanEntryModes(): Optional> = + includePanEntryModes.getOptional("include_pan_entry_modes") + + /** + * Returns the raw JSON value of [excludeCountries]. + * + * Unlike [excludeCountries], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("exclude_countries") + @ExcludeMissing + fun _excludeCountries(): JsonField> = excludeCountries + + /** + * Returns the raw JSON value of [excludeMccs]. + * + * Unlike [excludeMccs], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("exclude_mccs") + @ExcludeMissing + fun _excludeMccs(): JsonField> = excludeMccs + + /** + * Returns the raw JSON value of [includeCountries]. + * + * Unlike [includeCountries], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("include_countries") + @ExcludeMissing + fun _includeCountries(): JsonField> = includeCountries + + /** + * Returns the raw JSON value of [includeMccs]. + * + * Unlike [includeMccs], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("include_mccs") + @ExcludeMissing + fun _includeMccs(): JsonField> = includeMccs + + /** + * Returns the raw JSON value of [includePanEntryModes]. + * + * Unlike [includePanEntryModes], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("include_pan_entry_modes") + @ExcludeMissing + fun _includePanEntryModes(): JsonField> = includePanEntryModes + + @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 [VelocityLimitFilters]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [VelocityLimitFilters]. */ + class Builder internal constructor() { + + private var excludeCountries: JsonField>? = null + private var excludeMccs: JsonField>? = null + private var includeCountries: JsonField>? = null + private var includeMccs: JsonField>? = null + private var includePanEntryModes: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(velocityLimitFilters: VelocityLimitFilters) = apply { + excludeCountries = velocityLimitFilters.excludeCountries.map { it.toMutableList() } + excludeMccs = velocityLimitFilters.excludeMccs.map { it.toMutableList() } + includeCountries = velocityLimitFilters.includeCountries.map { it.toMutableList() } + includeMccs = velocityLimitFilters.includeMccs.map { it.toMutableList() } + includePanEntryModes = + velocityLimitFilters.includePanEntryModes.map { it.toMutableList() } + additionalProperties = velocityLimitFilters.additionalProperties.toMutableMap() + } + + /** + * ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. Transactions + * matching any of the provided will be excluded from the calculated velocity. + */ + fun excludeCountries(excludeCountries: List?) = + excludeCountries(JsonField.ofNullable(excludeCountries)) + + /** Alias for calling [Builder.excludeCountries] with `excludeCountries.orElse(null)`. */ + fun excludeCountries(excludeCountries: Optional>) = + excludeCountries(excludeCountries.getOrNull()) + + /** + * Sets [Builder.excludeCountries] to an arbitrary JSON value. + * + * You should usually call [Builder.excludeCountries] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun excludeCountries(excludeCountries: JsonField>) = apply { + this.excludeCountries = excludeCountries.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [excludeCountries]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addExcludeCountry(excludeCountry: String) = apply { + excludeCountries = + (excludeCountries ?: JsonField.of(mutableListOf())).also { + checkKnown("excludeCountries", it).add(excludeCountry) + } + } + + /** + * Merchant Category Codes to exclude from the velocity calculation. Transactions matching + * this MCC will be excluded from the calculated velocity. + */ + fun excludeMccs(excludeMccs: List?) = excludeMccs(JsonField.ofNullable(excludeMccs)) + + /** Alias for calling [Builder.excludeMccs] with `excludeMccs.orElse(null)`. */ + fun excludeMccs(excludeMccs: Optional>) = excludeMccs(excludeMccs.getOrNull()) + + /** + * Sets [Builder.excludeMccs] to an arbitrary JSON value. + * + * You should usually call [Builder.excludeMccs] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun excludeMccs(excludeMccs: JsonField>) = apply { + this.excludeMccs = excludeMccs.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [excludeMccs]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addExcludeMcc(excludeMcc: String) = apply { + excludeMccs = + (excludeMccs ?: JsonField.of(mutableListOf())).also { + checkKnown("excludeMccs", it).add(excludeMcc) + } + } + + /** + * ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. Transactions not + * matching any of the provided will not be included in the calculated velocity. + */ + fun includeCountries(includeCountries: List?) = + includeCountries(JsonField.ofNullable(includeCountries)) + + /** Alias for calling [Builder.includeCountries] with `includeCountries.orElse(null)`. */ + fun includeCountries(includeCountries: Optional>) = + includeCountries(includeCountries.getOrNull()) + + /** + * Sets [Builder.includeCountries] to an arbitrary JSON value. + * + * You should usually call [Builder.includeCountries] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun includeCountries(includeCountries: JsonField>) = apply { + this.includeCountries = includeCountries.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [includeCountries]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addIncludeCountry(includeCountry: String) = apply { + includeCountries = + (includeCountries ?: JsonField.of(mutableListOf())).also { + checkKnown("includeCountries", it).add(includeCountry) + } + } + + /** + * Merchant Category Codes to include in the velocity calculation. Transactions not matching + * this MCC will not be included in the calculated velocity. + */ + fun includeMccs(includeMccs: List?) = includeMccs(JsonField.ofNullable(includeMccs)) + + /** Alias for calling [Builder.includeMccs] with `includeMccs.orElse(null)`. */ + fun includeMccs(includeMccs: Optional>) = includeMccs(includeMccs.getOrNull()) + + /** + * Sets [Builder.includeMccs] to an arbitrary JSON value. + * + * You should usually call [Builder.includeMccs] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun includeMccs(includeMccs: JsonField>) = apply { + this.includeMccs = includeMccs.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [includeMccs]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addIncludeMcc(includeMcc: String) = apply { + includeMccs = + (includeMccs ?: JsonField.of(mutableListOf())).also { + checkKnown("includeMccs", it).add(includeMcc) + } + } + + /** + * PAN entry modes to include in the velocity calculation. Transactions not matching any of + * the provided will not be included in the calculated velocity. + */ + fun includePanEntryModes(includePanEntryModes: List?) = + includePanEntryModes(JsonField.ofNullable(includePanEntryModes)) + + /** + * Alias for calling [Builder.includePanEntryModes] with + * `includePanEntryModes.orElse(null)`. + */ + fun includePanEntryModes(includePanEntryModes: Optional>) = + includePanEntryModes(includePanEntryModes.getOrNull()) + + /** + * Sets [Builder.includePanEntryModes] to an arbitrary JSON value. + * + * You should usually call [Builder.includePanEntryModes] with a well-typed + * `List` value instead. This method is primarily for setting the field + * to an undocumented or not yet supported value. + */ + fun includePanEntryModes(includePanEntryModes: JsonField>) = + apply { + this.includePanEntryModes = includePanEntryModes.map { it.toMutableList() } + } + + /** + * Adds a single [IncludePanEntryMode] to [includePanEntryModes]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addIncludePanEntryMode(includePanEntryMode: IncludePanEntryMode) = apply { + includePanEntryModes = + (includePanEntryModes ?: JsonField.of(mutableListOf())).also { + checkKnown("includePanEntryModes", it).add(includePanEntryMode) + } + } + + 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 [VelocityLimitFilters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): VelocityLimitFilters = + VelocityLimitFilters( + (excludeCountries ?: JsonMissing.of()).map { it.toImmutable() }, + (excludeMccs ?: JsonMissing.of()).map { it.toImmutable() }, + (includeCountries ?: JsonMissing.of()).map { it.toImmutable() }, + (includeMccs ?: JsonMissing.of()).map { it.toImmutable() }, + (includePanEntryModes ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): VelocityLimitFilters = apply { + if (validated) { + return@apply + } + + excludeCountries() + excludeMccs() + includeCountries() + includeMccs() + includePanEntryModes().ifPresent { it.forEach { it.validate() } } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 = + (excludeCountries.asKnown().getOrNull()?.size ?: 0) + + (excludeMccs.asKnown().getOrNull()?.size ?: 0) + + (includeCountries.asKnown().getOrNull()?.size ?: 0) + + (includeMccs.asKnown().getOrNull()?.size ?: 0) + + (includePanEntryModes.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + class IncludePanEntryMode + @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 AUTO_ENTRY = of("AUTO_ENTRY") + + @JvmField val BAR_CODE = of("BAR_CODE") + + @JvmField val CONTACTLESS = of("CONTACTLESS") + + @JvmField val CREDENTIAL_ON_FILE = of("CREDENTIAL_ON_FILE") + + @JvmField val ECOMMERCE = of("ECOMMERCE") + + @JvmField val ERROR_KEYED = of("ERROR_KEYED") + + @JvmField val ERROR_MAGNETIC_STRIPE = of("ERROR_MAGNETIC_STRIPE") + + @JvmField val ICC = of("ICC") + + @JvmField val KEY_ENTERED = of("KEY_ENTERED") + + @JvmField val MAGNETIC_STRIPE = of("MAGNETIC_STRIPE") + + @JvmField val MANUAL = of("MANUAL") + + @JvmField val OCR = of("OCR") + + @JvmField val SECURE_CARDLESS = of("SECURE_CARDLESS") + + @JvmField val UNSPECIFIED = of("UNSPECIFIED") + + @JvmField val UNKNOWN = of("UNKNOWN") + + @JvmStatic fun of(value: String) = IncludePanEntryMode(JsonField.of(value)) + } + + /** An enum containing [IncludePanEntryMode]'s known values. */ + enum class Known { + AUTO_ENTRY, + BAR_CODE, + CONTACTLESS, + CREDENTIAL_ON_FILE, + ECOMMERCE, + ERROR_KEYED, + ERROR_MAGNETIC_STRIPE, + ICC, + KEY_ENTERED, + MAGNETIC_STRIPE, + MANUAL, + OCR, + SECURE_CARDLESS, + UNSPECIFIED, + UNKNOWN, + } + + /** + * An enum containing [IncludePanEntryMode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [IncludePanEntryMode] 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 { + AUTO_ENTRY, + BAR_CODE, + CONTACTLESS, + CREDENTIAL_ON_FILE, + ECOMMERCE, + ERROR_KEYED, + ERROR_MAGNETIC_STRIPE, + ICC, + KEY_ENTERED, + MAGNETIC_STRIPE, + MANUAL, + OCR, + SECURE_CARDLESS, + UNSPECIFIED, + UNKNOWN, + /** + * An enum member indicating that [IncludePanEntryMode] 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) { + AUTO_ENTRY -> Value.AUTO_ENTRY + BAR_CODE -> Value.BAR_CODE + CONTACTLESS -> Value.CONTACTLESS + CREDENTIAL_ON_FILE -> Value.CREDENTIAL_ON_FILE + ECOMMERCE -> Value.ECOMMERCE + ERROR_KEYED -> Value.ERROR_KEYED + ERROR_MAGNETIC_STRIPE -> Value.ERROR_MAGNETIC_STRIPE + ICC -> Value.ICC + KEY_ENTERED -> Value.KEY_ENTERED + MAGNETIC_STRIPE -> Value.MAGNETIC_STRIPE + MANUAL -> Value.MANUAL + OCR -> Value.OCR + SECURE_CARDLESS -> Value.SECURE_CARDLESS + UNSPECIFIED -> Value.UNSPECIFIED + 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 LithicInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AUTO_ENTRY -> Known.AUTO_ENTRY + BAR_CODE -> Known.BAR_CODE + CONTACTLESS -> Known.CONTACTLESS + CREDENTIAL_ON_FILE -> Known.CREDENTIAL_ON_FILE + ECOMMERCE -> Known.ECOMMERCE + ERROR_KEYED -> Known.ERROR_KEYED + ERROR_MAGNETIC_STRIPE -> Known.ERROR_MAGNETIC_STRIPE + ICC -> Known.ICC + KEY_ENTERED -> Known.KEY_ENTERED + MAGNETIC_STRIPE -> Known.MAGNETIC_STRIPE + MANUAL -> Known.MANUAL + OCR -> Known.OCR + SECURE_CARDLESS -> Known.SECURE_CARDLESS + UNSPECIFIED -> Known.UNSPECIFIED + UNKNOWN -> Known.UNKNOWN + else -> throw LithicInvalidDataException("Unknown IncludePanEntryMode: $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 LithicInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { LithicInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + fun validate(): IncludePanEntryMode = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + 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 IncludePanEntryMode && 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 VelocityLimitFilters && + excludeCountries == other.excludeCountries && + excludeMccs == other.excludeMccs && + includeCountries == other.includeCountries && + includeMccs == other.includeMccs && + includePanEntryModes == other.includePanEntryModes && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + excludeCountries, + excludeMccs, + includeCountries, + includeMccs, + includePanEntryModes, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "VelocityLimitFilters{excludeCountries=$excludeCountries, excludeMccs=$excludeMccs, includeCountries=$includeCountries, includeMccs=$includeMccs, includePanEntryModes=$includePanEntryModes, additionalProperties=$additionalProperties}" +} diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitParams.kt index 5f98fc8d..7b89e461 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/VelocityLimitParams.kt @@ -11,9 +11,7 @@ import com.lithic.api.core.ExcludeMissing import com.lithic.api.core.JsonField import com.lithic.api.core.JsonMissing import com.lithic.api.core.JsonValue -import com.lithic.api.core.checkKnown import com.lithic.api.core.checkRequired -import com.lithic.api.core.toImmutable import com.lithic.api.errors.LithicInvalidDataException import java.util.Collections import java.util.Objects @@ -499,672 +497,6 @@ private constructor( override fun toString() = value.toString() } - class VelocityLimitFilters - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val excludeCountries: JsonField>, - private val excludeMccs: JsonField>, - private val includeCountries: JsonField>, - private val includeMccs: JsonField>, - private val includePanEntryModes: JsonField>, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("exclude_countries") - @ExcludeMissing - excludeCountries: JsonField> = JsonMissing.of(), - @JsonProperty("exclude_mccs") - @ExcludeMissing - excludeMccs: JsonField> = JsonMissing.of(), - @JsonProperty("include_countries") - @ExcludeMissing - includeCountries: JsonField> = JsonMissing.of(), - @JsonProperty("include_mccs") - @ExcludeMissing - includeMccs: JsonField> = JsonMissing.of(), - @JsonProperty("include_pan_entry_modes") - @ExcludeMissing - includePanEntryModes: JsonField> = JsonMissing.of(), - ) : this( - excludeCountries, - excludeMccs, - includeCountries, - includeMccs, - includePanEntryModes, - mutableMapOf(), - ) - - /** - * ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. Transactions - * matching any of the provided will be excluded from the calculated velocity. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun excludeCountries(): Optional> = - excludeCountries.getOptional("exclude_countries") - - /** - * Merchant Category Codes to exclude from the velocity calculation. Transactions matching - * this MCC will be excluded from the calculated velocity. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun excludeMccs(): Optional> = excludeMccs.getOptional("exclude_mccs") - - /** - * ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. Transactions not - * matching any of the provided will not be included in the calculated velocity. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun includeCountries(): Optional> = - includeCountries.getOptional("include_countries") - - /** - * Merchant Category Codes to include in the velocity calculation. Transactions not matching - * this MCC will not be included in the calculated velocity. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun includeMccs(): Optional> = includeMccs.getOptional("include_mccs") - - /** - * PAN entry modes to include in the velocity calculation. Transactions not matching any of - * the provided will not be included in the calculated velocity. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun includePanEntryModes(): Optional> = - includePanEntryModes.getOptional("include_pan_entry_modes") - - /** - * Returns the raw JSON value of [excludeCountries]. - * - * Unlike [excludeCountries], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("exclude_countries") - @ExcludeMissing - fun _excludeCountries(): JsonField> = excludeCountries - - /** - * Returns the raw JSON value of [excludeMccs]. - * - * Unlike [excludeMccs], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("exclude_mccs") - @ExcludeMissing - fun _excludeMccs(): JsonField> = excludeMccs - - /** - * Returns the raw JSON value of [includeCountries]. - * - * Unlike [includeCountries], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("include_countries") - @ExcludeMissing - fun _includeCountries(): JsonField> = includeCountries - - /** - * Returns the raw JSON value of [includeMccs]. - * - * Unlike [includeMccs], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("include_mccs") - @ExcludeMissing - fun _includeMccs(): JsonField> = includeMccs - - /** - * Returns the raw JSON value of [includePanEntryModes]. - * - * Unlike [includePanEntryModes], this method doesn't throw if the JSON field has an - * unexpected type. - */ - @JsonProperty("include_pan_entry_modes") - @ExcludeMissing - fun _includePanEntryModes(): JsonField> = includePanEntryModes - - @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 [VelocityLimitFilters]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [VelocityLimitFilters]. */ - class Builder internal constructor() { - - private var excludeCountries: JsonField>? = null - private var excludeMccs: JsonField>? = null - private var includeCountries: JsonField>? = null - private var includeMccs: JsonField>? = null - private var includePanEntryModes: JsonField>? = null - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(velocityLimitFilters: VelocityLimitFilters) = apply { - excludeCountries = velocityLimitFilters.excludeCountries.map { it.toMutableList() } - excludeMccs = velocityLimitFilters.excludeMccs.map { it.toMutableList() } - includeCountries = velocityLimitFilters.includeCountries.map { it.toMutableList() } - includeMccs = velocityLimitFilters.includeMccs.map { it.toMutableList() } - includePanEntryModes = - velocityLimitFilters.includePanEntryModes.map { it.toMutableList() } - additionalProperties = velocityLimitFilters.additionalProperties.toMutableMap() - } - - /** - * ISO-3166-1 alpha-3 Country Codes to exclude from the velocity calculation. - * Transactions matching any of the provided will be excluded from the calculated - * velocity. - */ - fun excludeCountries(excludeCountries: List?) = - excludeCountries(JsonField.ofNullable(excludeCountries)) - - /** - * Alias for calling [Builder.excludeCountries] with `excludeCountries.orElse(null)`. - */ - fun excludeCountries(excludeCountries: Optional>) = - excludeCountries(excludeCountries.getOrNull()) - - /** - * Sets [Builder.excludeCountries] to an arbitrary JSON value. - * - * You should usually call [Builder.excludeCountries] with a well-typed `List` - * value instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun excludeCountries(excludeCountries: JsonField>) = apply { - this.excludeCountries = excludeCountries.map { it.toMutableList() } - } - - /** - * Adds a single [String] to [excludeCountries]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addExcludeCountry(excludeCountry: String) = apply { - excludeCountries = - (excludeCountries ?: JsonField.of(mutableListOf())).also { - checkKnown("excludeCountries", it).add(excludeCountry) - } - } - - /** - * Merchant Category Codes to exclude from the velocity calculation. Transactions - * matching this MCC will be excluded from the calculated velocity. - */ - fun excludeMccs(excludeMccs: List?) = - excludeMccs(JsonField.ofNullable(excludeMccs)) - - /** Alias for calling [Builder.excludeMccs] with `excludeMccs.orElse(null)`. */ - fun excludeMccs(excludeMccs: Optional>) = - excludeMccs(excludeMccs.getOrNull()) - - /** - * Sets [Builder.excludeMccs] to an arbitrary JSON value. - * - * You should usually call [Builder.excludeMccs] with a well-typed `List` value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun excludeMccs(excludeMccs: JsonField>) = apply { - this.excludeMccs = excludeMccs.map { it.toMutableList() } - } - - /** - * Adds a single [String] to [excludeMccs]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addExcludeMcc(excludeMcc: String) = apply { - excludeMccs = - (excludeMccs ?: JsonField.of(mutableListOf())).also { - checkKnown("excludeMccs", it).add(excludeMcc) - } - } - - /** - * ISO-3166-1 alpha-3 Country Codes to include in the velocity calculation. Transactions - * not matching any of the provided will not be included in the calculated velocity. - */ - fun includeCountries(includeCountries: List?) = - includeCountries(JsonField.ofNullable(includeCountries)) - - /** - * Alias for calling [Builder.includeCountries] with `includeCountries.orElse(null)`. - */ - fun includeCountries(includeCountries: Optional>) = - includeCountries(includeCountries.getOrNull()) - - /** - * Sets [Builder.includeCountries] to an arbitrary JSON value. - * - * You should usually call [Builder.includeCountries] with a well-typed `List` - * value instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun includeCountries(includeCountries: JsonField>) = apply { - this.includeCountries = includeCountries.map { it.toMutableList() } - } - - /** - * Adds a single [String] to [includeCountries]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addIncludeCountry(includeCountry: String) = apply { - includeCountries = - (includeCountries ?: JsonField.of(mutableListOf())).also { - checkKnown("includeCountries", it).add(includeCountry) - } - } - - /** - * Merchant Category Codes to include in the velocity calculation. Transactions not - * matching this MCC will not be included in the calculated velocity. - */ - fun includeMccs(includeMccs: List?) = - includeMccs(JsonField.ofNullable(includeMccs)) - - /** Alias for calling [Builder.includeMccs] with `includeMccs.orElse(null)`. */ - fun includeMccs(includeMccs: Optional>) = - includeMccs(includeMccs.getOrNull()) - - /** - * Sets [Builder.includeMccs] to an arbitrary JSON value. - * - * You should usually call [Builder.includeMccs] with a well-typed `List` value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun includeMccs(includeMccs: JsonField>) = apply { - this.includeMccs = includeMccs.map { it.toMutableList() } - } - - /** - * Adds a single [String] to [includeMccs]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addIncludeMcc(includeMcc: String) = apply { - includeMccs = - (includeMccs ?: JsonField.of(mutableListOf())).also { - checkKnown("includeMccs", it).add(includeMcc) - } - } - - /** - * PAN entry modes to include in the velocity calculation. Transactions not matching any - * of the provided will not be included in the calculated velocity. - */ - fun includePanEntryModes(includePanEntryModes: List?) = - includePanEntryModes(JsonField.ofNullable(includePanEntryModes)) - - /** - * Alias for calling [Builder.includePanEntryModes] with - * `includePanEntryModes.orElse(null)`. - */ - fun includePanEntryModes(includePanEntryModes: Optional>) = - includePanEntryModes(includePanEntryModes.getOrNull()) - - /** - * Sets [Builder.includePanEntryModes] to an arbitrary JSON value. - * - * You should usually call [Builder.includePanEntryModes] with a well-typed - * `List` value instead. This method is primarily for setting the - * field to an undocumented or not yet supported value. - */ - fun includePanEntryModes(includePanEntryModes: JsonField>) = - apply { - this.includePanEntryModes = includePanEntryModes.map { it.toMutableList() } - } - - /** - * Adds a single [IncludePanEntryMode] to [includePanEntryModes]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addIncludePanEntryMode(includePanEntryMode: IncludePanEntryMode) = apply { - includePanEntryModes = - (includePanEntryModes ?: JsonField.of(mutableListOf())).also { - checkKnown("includePanEntryModes", it).add(includePanEntryMode) - } - } - - 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 [VelocityLimitFilters]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): VelocityLimitFilters = - VelocityLimitFilters( - (excludeCountries ?: JsonMissing.of()).map { it.toImmutable() }, - (excludeMccs ?: JsonMissing.of()).map { it.toImmutable() }, - (includeCountries ?: JsonMissing.of()).map { it.toImmutable() }, - (includeMccs ?: JsonMissing.of()).map { it.toImmutable() }, - (includePanEntryModes ?: JsonMissing.of()).map { it.toImmutable() }, - additionalProperties.toMutableMap(), - ) - } - - private var validated: Boolean = false - - fun validate(): VelocityLimitFilters = apply { - if (validated) { - return@apply - } - - excludeCountries() - excludeMccs() - includeCountries() - includeMccs() - includePanEntryModes().ifPresent { it.forEach { it.validate() } } - validated = true - } - - fun isValid(): Boolean = - try { - validate() - true - } catch (e: LithicInvalidDataException) { - 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 = - (excludeCountries.asKnown().getOrNull()?.size ?: 0) + - (excludeMccs.asKnown().getOrNull()?.size ?: 0) + - (includeCountries.asKnown().getOrNull()?.size ?: 0) + - (includeMccs.asKnown().getOrNull()?.size ?: 0) + - (includePanEntryModes.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) - - class IncludePanEntryMode - @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 AUTO_ENTRY = of("AUTO_ENTRY") - - @JvmField val BAR_CODE = of("BAR_CODE") - - @JvmField val CONTACTLESS = of("CONTACTLESS") - - @JvmField val CREDENTIAL_ON_FILE = of("CREDENTIAL_ON_FILE") - - @JvmField val ECOMMERCE = of("ECOMMERCE") - - @JvmField val ERROR_KEYED = of("ERROR_KEYED") - - @JvmField val ERROR_MAGNETIC_STRIPE = of("ERROR_MAGNETIC_STRIPE") - - @JvmField val ICC = of("ICC") - - @JvmField val KEY_ENTERED = of("KEY_ENTERED") - - @JvmField val MAGNETIC_STRIPE = of("MAGNETIC_STRIPE") - - @JvmField val MANUAL = of("MANUAL") - - @JvmField val OCR = of("OCR") - - @JvmField val SECURE_CARDLESS = of("SECURE_CARDLESS") - - @JvmField val UNSPECIFIED = of("UNSPECIFIED") - - @JvmField val UNKNOWN = of("UNKNOWN") - - @JvmStatic fun of(value: String) = IncludePanEntryMode(JsonField.of(value)) - } - - /** An enum containing [IncludePanEntryMode]'s known values. */ - enum class Known { - AUTO_ENTRY, - BAR_CODE, - CONTACTLESS, - CREDENTIAL_ON_FILE, - ECOMMERCE, - ERROR_KEYED, - ERROR_MAGNETIC_STRIPE, - ICC, - KEY_ENTERED, - MAGNETIC_STRIPE, - MANUAL, - OCR, - SECURE_CARDLESS, - UNSPECIFIED, - UNKNOWN, - } - - /** - * An enum containing [IncludePanEntryMode]'s known values, as well as an [_UNKNOWN] - * member. - * - * An instance of [IncludePanEntryMode] 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 { - AUTO_ENTRY, - BAR_CODE, - CONTACTLESS, - CREDENTIAL_ON_FILE, - ECOMMERCE, - ERROR_KEYED, - ERROR_MAGNETIC_STRIPE, - ICC, - KEY_ENTERED, - MAGNETIC_STRIPE, - MANUAL, - OCR, - SECURE_CARDLESS, - UNSPECIFIED, - UNKNOWN, - /** - * An enum member indicating that [IncludePanEntryMode] 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) { - AUTO_ENTRY -> Value.AUTO_ENTRY - BAR_CODE -> Value.BAR_CODE - CONTACTLESS -> Value.CONTACTLESS - CREDENTIAL_ON_FILE -> Value.CREDENTIAL_ON_FILE - ECOMMERCE -> Value.ECOMMERCE - ERROR_KEYED -> Value.ERROR_KEYED - ERROR_MAGNETIC_STRIPE -> Value.ERROR_MAGNETIC_STRIPE - ICC -> Value.ICC - KEY_ENTERED -> Value.KEY_ENTERED - MAGNETIC_STRIPE -> Value.MAGNETIC_STRIPE - MANUAL -> Value.MANUAL - OCR -> Value.OCR - SECURE_CARDLESS -> Value.SECURE_CARDLESS - UNSPECIFIED -> Value.UNSPECIFIED - 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 LithicInvalidDataException if this class instance's value is a not a known - * member. - */ - fun known(): Known = - when (this) { - AUTO_ENTRY -> Known.AUTO_ENTRY - BAR_CODE -> Known.BAR_CODE - CONTACTLESS -> Known.CONTACTLESS - CREDENTIAL_ON_FILE -> Known.CREDENTIAL_ON_FILE - ECOMMERCE -> Known.ECOMMERCE - ERROR_KEYED -> Known.ERROR_KEYED - ERROR_MAGNETIC_STRIPE -> Known.ERROR_MAGNETIC_STRIPE - ICC -> Known.ICC - KEY_ENTERED -> Known.KEY_ENTERED - MAGNETIC_STRIPE -> Known.MAGNETIC_STRIPE - MANUAL -> Known.MANUAL - OCR -> Known.OCR - SECURE_CARDLESS -> Known.SECURE_CARDLESS - UNSPECIFIED -> Known.UNSPECIFIED - UNKNOWN -> Known.UNKNOWN - else -> throw LithicInvalidDataException("Unknown IncludePanEntryMode: $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 LithicInvalidDataException if this class instance's value does not have the - * expected primitive type. - */ - fun asString(): String = - _value().asString().orElseThrow { - LithicInvalidDataException("Value is not a String") - } - - private var validated: Boolean = false - - fun validate(): IncludePanEntryMode = apply { - if (validated) { - return@apply - } - - known() - validated = true - } - - fun isValid(): Boolean = - try { - validate() - true - } catch (e: LithicInvalidDataException) { - 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 IncludePanEntryMode && 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 VelocityLimitFilters && - excludeCountries == other.excludeCountries && - excludeMccs == other.excludeMccs && - includeCountries == other.includeCountries && - includeMccs == other.includeMccs && - includePanEntryModes == other.includePanEntryModes && - additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { - Objects.hash( - excludeCountries, - excludeMccs, - includeCountries, - includeMccs, - includePanEntryModes, - additionalProperties, - ) - } - - override fun hashCode(): Int = hashCode - - override fun toString() = - "VelocityLimitFilters{excludeCountries=$excludeCountries, excludeMccs=$excludeMccs, includeCountries=$includeCountries, includeMccs=$includeMccs, includePanEntryModes=$includePanEntryModes, additionalProperties=$additionalProperties}" - } - override fun equals(other: Any?): Boolean { if (this === other) { return true diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleTest.kt index 16f77974..557acfc4 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleTest.kt @@ -36,6 +36,7 @@ internal class AuthRuleTest { ) .draftVersion( AuthRule.DraftVersion.builder() + .error("error") .parameters( ConditionalBlockParameters.builder() .addCondition( @@ -47,6 +48,7 @@ internal class AuthRuleTest { ) .build() ) + .state(AuthRule.DraftVersion.State.PENDING) .version(0L) .build() ) @@ -84,6 +86,7 @@ internal class AuthRuleTest { assertThat(authRule.draftVersion()) .contains( AuthRule.DraftVersion.builder() + .error("error") .parameters( ConditionalBlockParameters.builder() .addCondition( @@ -95,6 +98,7 @@ internal class AuthRuleTest { ) .build() ) + .state(AuthRule.DraftVersion.State.PENDING) .version(0L) .build() ) @@ -135,6 +139,7 @@ internal class AuthRuleTest { ) .draftVersion( AuthRule.DraftVersion.builder() + .error("error") .parameters( ConditionalBlockParameters.builder() .addCondition( @@ -146,6 +151,7 @@ internal class AuthRuleTest { ) .build() ) + .state(AuthRule.DraftVersion.State.PENDING) .version(0L) .build() ) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ListPageResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ListPageResponseTest.kt index 9ccbb547..13992a10 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ListPageResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ListPageResponseTest.kt @@ -37,6 +37,7 @@ internal class AuthRuleV2ListPageResponseTest { ) .draftVersion( AuthRule.DraftVersion.builder() + .error("error") .parameters( ConditionalBlockParameters.builder() .addCondition( @@ -48,6 +49,7 @@ internal class AuthRuleV2ListPageResponseTest { ) .build() ) + .state(AuthRule.DraftVersion.State.PENDING) .version(0L) .build() ) @@ -88,6 +90,7 @@ internal class AuthRuleV2ListPageResponseTest { ) .draftVersion( AuthRule.DraftVersion.builder() + .error("error") .parameters( ConditionalBlockParameters.builder() .addCondition( @@ -99,6 +102,7 @@ internal class AuthRuleV2ListPageResponseTest { ) .build() ) + .state(AuthRule.DraftVersion.State.PENDING) .version(0L) .build() ) @@ -143,6 +147,7 @@ internal class AuthRuleV2ListPageResponseTest { ) .draftVersion( AuthRule.DraftVersion.builder() + .error("error") .parameters( ConditionalBlockParameters.builder() .addCondition( @@ -154,6 +159,7 @@ internal class AuthRuleV2ListPageResponseTest { ) .build() ) + .state(AuthRule.DraftVersion.State.PENDING) .version(0L) .build() ) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/RuleFeatureTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/RuleFeatureTest.kt new file mode 100644 index 00000000..08105ce4 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/RuleFeatureTest.kt @@ -0,0 +1,387 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.JsonValue +import com.lithic.api.core.jsonMapper +import com.lithic.api.errors.LithicInvalidDataException +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class RuleFeatureTest { + + @Test + fun ofAuthorization() { + val authorization = + RuleFeature.AuthorizationFeature.builder() + .type(RuleFeature.AuthorizationFeature.Type.AUTHORIZATION) + .name("name") + .build() + + val ruleFeature = RuleFeature.ofAuthorization(authorization) + + assertThat(ruleFeature.authorization()).contains(authorization) + assertThat(ruleFeature.authentication()).isEmpty + assertThat(ruleFeature.tokenization()).isEmpty + assertThat(ruleFeature.achReceipt()).isEmpty + assertThat(ruleFeature.card()).isEmpty + assertThat(ruleFeature.accountHolder()).isEmpty + assertThat(ruleFeature.ipMetadata()).isEmpty + assertThat(ruleFeature.spendVelocity()).isEmpty + } + + @Test + fun ofAuthorizationRoundtrip() { + val jsonMapper = jsonMapper() + val ruleFeature = + RuleFeature.ofAuthorization( + RuleFeature.AuthorizationFeature.builder() + .type(RuleFeature.AuthorizationFeature.Type.AUTHORIZATION) + .name("name") + .build() + ) + + val roundtrippedRuleFeature = + jsonMapper.readValue( + jsonMapper.writeValueAsString(ruleFeature), + jacksonTypeRef(), + ) + + assertThat(roundtrippedRuleFeature).isEqualTo(ruleFeature) + } + + @Test + fun ofAuthentication() { + val authentication = + RuleFeature.AuthenticationFeature.builder() + .type(RuleFeature.AuthenticationFeature.Type.AUTHENTICATION) + .name("name") + .build() + + val ruleFeature = RuleFeature.ofAuthentication(authentication) + + assertThat(ruleFeature.authorization()).isEmpty + assertThat(ruleFeature.authentication()).contains(authentication) + assertThat(ruleFeature.tokenization()).isEmpty + assertThat(ruleFeature.achReceipt()).isEmpty + assertThat(ruleFeature.card()).isEmpty + assertThat(ruleFeature.accountHolder()).isEmpty + assertThat(ruleFeature.ipMetadata()).isEmpty + assertThat(ruleFeature.spendVelocity()).isEmpty + } + + @Test + fun ofAuthenticationRoundtrip() { + val jsonMapper = jsonMapper() + val ruleFeature = + RuleFeature.ofAuthentication( + RuleFeature.AuthenticationFeature.builder() + .type(RuleFeature.AuthenticationFeature.Type.AUTHENTICATION) + .name("name") + .build() + ) + + val roundtrippedRuleFeature = + jsonMapper.readValue( + jsonMapper.writeValueAsString(ruleFeature), + jacksonTypeRef(), + ) + + assertThat(roundtrippedRuleFeature).isEqualTo(ruleFeature) + } + + @Test + fun ofTokenization() { + val tokenization = + RuleFeature.TokenizationFeature.builder() + .type(RuleFeature.TokenizationFeature.Type.TOKENIZATION) + .name("name") + .build() + + val ruleFeature = RuleFeature.ofTokenization(tokenization) + + assertThat(ruleFeature.authorization()).isEmpty + assertThat(ruleFeature.authentication()).isEmpty + assertThat(ruleFeature.tokenization()).contains(tokenization) + assertThat(ruleFeature.achReceipt()).isEmpty + assertThat(ruleFeature.card()).isEmpty + assertThat(ruleFeature.accountHolder()).isEmpty + assertThat(ruleFeature.ipMetadata()).isEmpty + assertThat(ruleFeature.spendVelocity()).isEmpty + } + + @Test + fun ofTokenizationRoundtrip() { + val jsonMapper = jsonMapper() + val ruleFeature = + RuleFeature.ofTokenization( + RuleFeature.TokenizationFeature.builder() + .type(RuleFeature.TokenizationFeature.Type.TOKENIZATION) + .name("name") + .build() + ) + + val roundtrippedRuleFeature = + jsonMapper.readValue( + jsonMapper.writeValueAsString(ruleFeature), + jacksonTypeRef(), + ) + + assertThat(roundtrippedRuleFeature).isEqualTo(ruleFeature) + } + + @Test + fun ofAchReceipt() { + val achReceipt = + RuleFeature.AchReceiptFeature.builder() + .type(RuleFeature.AchReceiptFeature.Type.ACH_RECEIPT) + .name("name") + .build() + + val ruleFeature = RuleFeature.ofAchReceipt(achReceipt) + + assertThat(ruleFeature.authorization()).isEmpty + assertThat(ruleFeature.authentication()).isEmpty + assertThat(ruleFeature.tokenization()).isEmpty + assertThat(ruleFeature.achReceipt()).contains(achReceipt) + assertThat(ruleFeature.card()).isEmpty + assertThat(ruleFeature.accountHolder()).isEmpty + assertThat(ruleFeature.ipMetadata()).isEmpty + assertThat(ruleFeature.spendVelocity()).isEmpty + } + + @Test + fun ofAchReceiptRoundtrip() { + val jsonMapper = jsonMapper() + val ruleFeature = + RuleFeature.ofAchReceipt( + RuleFeature.AchReceiptFeature.builder() + .type(RuleFeature.AchReceiptFeature.Type.ACH_RECEIPT) + .name("name") + .build() + ) + + val roundtrippedRuleFeature = + jsonMapper.readValue( + jsonMapper.writeValueAsString(ruleFeature), + jacksonTypeRef(), + ) + + assertThat(roundtrippedRuleFeature).isEqualTo(ruleFeature) + } + + @Test + fun ofCard() { + val card = + RuleFeature.CardFeature.builder() + .type(RuleFeature.CardFeature.Type.CARD) + .name("name") + .build() + + val ruleFeature = RuleFeature.ofCard(card) + + assertThat(ruleFeature.authorization()).isEmpty + assertThat(ruleFeature.authentication()).isEmpty + assertThat(ruleFeature.tokenization()).isEmpty + assertThat(ruleFeature.achReceipt()).isEmpty + assertThat(ruleFeature.card()).contains(card) + assertThat(ruleFeature.accountHolder()).isEmpty + assertThat(ruleFeature.ipMetadata()).isEmpty + assertThat(ruleFeature.spendVelocity()).isEmpty + } + + @Test + fun ofCardRoundtrip() { + val jsonMapper = jsonMapper() + val ruleFeature = + RuleFeature.ofCard( + RuleFeature.CardFeature.builder() + .type(RuleFeature.CardFeature.Type.CARD) + .name("name") + .build() + ) + + val roundtrippedRuleFeature = + jsonMapper.readValue( + jsonMapper.writeValueAsString(ruleFeature), + jacksonTypeRef(), + ) + + assertThat(roundtrippedRuleFeature).isEqualTo(ruleFeature) + } + + @Test + fun ofAccountHolder() { + val accountHolder = + RuleFeature.AccountHolderFeature.builder() + .type(RuleFeature.AccountHolderFeature.Type.ACCOUNT_HOLDER) + .name("name") + .build() + + val ruleFeature = RuleFeature.ofAccountHolder(accountHolder) + + assertThat(ruleFeature.authorization()).isEmpty + assertThat(ruleFeature.authentication()).isEmpty + assertThat(ruleFeature.tokenization()).isEmpty + assertThat(ruleFeature.achReceipt()).isEmpty + assertThat(ruleFeature.card()).isEmpty + assertThat(ruleFeature.accountHolder()).contains(accountHolder) + assertThat(ruleFeature.ipMetadata()).isEmpty + assertThat(ruleFeature.spendVelocity()).isEmpty + } + + @Test + fun ofAccountHolderRoundtrip() { + val jsonMapper = jsonMapper() + val ruleFeature = + RuleFeature.ofAccountHolder( + RuleFeature.AccountHolderFeature.builder() + .type(RuleFeature.AccountHolderFeature.Type.ACCOUNT_HOLDER) + .name("name") + .build() + ) + + val roundtrippedRuleFeature = + jsonMapper.readValue( + jsonMapper.writeValueAsString(ruleFeature), + jacksonTypeRef(), + ) + + assertThat(roundtrippedRuleFeature).isEqualTo(ruleFeature) + } + + @Test + fun ofIpMetadata() { + val ipMetadata = + RuleFeature.IpMetadataFeature.builder() + .type(RuleFeature.IpMetadataFeature.Type.IP_METADATA) + .name("name") + .build() + + val ruleFeature = RuleFeature.ofIpMetadata(ipMetadata) + + assertThat(ruleFeature.authorization()).isEmpty + assertThat(ruleFeature.authentication()).isEmpty + assertThat(ruleFeature.tokenization()).isEmpty + assertThat(ruleFeature.achReceipt()).isEmpty + assertThat(ruleFeature.card()).isEmpty + assertThat(ruleFeature.accountHolder()).isEmpty + assertThat(ruleFeature.ipMetadata()).contains(ipMetadata) + assertThat(ruleFeature.spendVelocity()).isEmpty + } + + @Test + fun ofIpMetadataRoundtrip() { + val jsonMapper = jsonMapper() + val ruleFeature = + RuleFeature.ofIpMetadata( + RuleFeature.IpMetadataFeature.builder() + .type(RuleFeature.IpMetadataFeature.Type.IP_METADATA) + .name("name") + .build() + ) + + val roundtrippedRuleFeature = + jsonMapper.readValue( + jsonMapper.writeValueAsString(ruleFeature), + jacksonTypeRef(), + ) + + assertThat(roundtrippedRuleFeature).isEqualTo(ruleFeature) + } + + @Test + fun ofSpendVelocity() { + val spendVelocity = + RuleFeature.SpendVelocityFeature.builder() + .period( + VelocityLimitPeriod.TrailingWindowObject.builder() + .duration(10L) + .type(VelocityLimitPeriod.TrailingWindowObject.Type.CUSTOM) + .build() + ) + .scope(RuleFeature.SpendVelocityFeature.VelocityScope.CARD) + .type(RuleFeature.SpendVelocityFeature.Type.SPEND_VELOCITY) + .filters( + VelocityLimitFilters.builder() + .addExcludeCountry("USD") + .addExcludeMcc("5542") + .addIncludeCountry("USD") + .addIncludeMcc("5542") + .addIncludePanEntryMode(VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY) + .build() + ) + .name("name") + .build() + + val ruleFeature = RuleFeature.ofSpendVelocity(spendVelocity) + + assertThat(ruleFeature.authorization()).isEmpty + assertThat(ruleFeature.authentication()).isEmpty + assertThat(ruleFeature.tokenization()).isEmpty + assertThat(ruleFeature.achReceipt()).isEmpty + assertThat(ruleFeature.card()).isEmpty + assertThat(ruleFeature.accountHolder()).isEmpty + assertThat(ruleFeature.ipMetadata()).isEmpty + assertThat(ruleFeature.spendVelocity()).contains(spendVelocity) + } + + @Test + fun ofSpendVelocityRoundtrip() { + val jsonMapper = jsonMapper() + val ruleFeature = + RuleFeature.ofSpendVelocity( + RuleFeature.SpendVelocityFeature.builder() + .period( + VelocityLimitPeriod.TrailingWindowObject.builder() + .duration(10L) + .type(VelocityLimitPeriod.TrailingWindowObject.Type.CUSTOM) + .build() + ) + .scope(RuleFeature.SpendVelocityFeature.VelocityScope.CARD) + .type(RuleFeature.SpendVelocityFeature.Type.SPEND_VELOCITY) + .filters( + VelocityLimitFilters.builder() + .addExcludeCountry("USD") + .addExcludeMcc("5542") + .addIncludeCountry("USD") + .addIncludeMcc("5542") + .addIncludePanEntryMode( + VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY + ) + .build() + ) + .name("name") + .build() + ) + + val roundtrippedRuleFeature = + jsonMapper.readValue( + jsonMapper.writeValueAsString(ruleFeature), + jacksonTypeRef(), + ) + + assertThat(roundtrippedRuleFeature).isEqualTo(ruleFeature) + } + + enum class IncompatibleJsonShapeTestCase(val value: JsonValue) { + BOOLEAN(JsonValue.from(false)), + STRING(JsonValue.from("invalid")), + INTEGER(JsonValue.from(-1)), + FLOAT(JsonValue.from(3.14)), + ARRAY(JsonValue.from(listOf("invalid", "array"))), + } + + @ParameterizedTest + @EnumSource + fun incompatibleJsonShapeDeserializesToUnknown(testCase: IncompatibleJsonShapeTestCase) { + val ruleFeature = jsonMapper().convertValue(testCase.value, jacksonTypeRef()) + + val e = assertThrows { ruleFeature.validate() } + assertThat(e).hasMessageStartingWith("Unknown ") + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/TypescriptCodeParametersTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/TypescriptCodeParametersTest.kt new file mode 100644 index 00000000..39ae3805 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/TypescriptCodeParametersTest.kt @@ -0,0 +1,59 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TypescriptCodeParametersTest { + + @Test + fun create() { + val typescriptCodeParameters = + TypescriptCodeParameters.builder() + .code("code") + .addFeature( + RuleFeature.AuthorizationFeature.builder() + .type(RuleFeature.AuthorizationFeature.Type.AUTHORIZATION) + .name("name") + .build() + ) + .build() + + assertThat(typescriptCodeParameters.code()).isEqualTo("code") + assertThat(typescriptCodeParameters.features()) + .containsExactly( + RuleFeature.ofAuthorization( + RuleFeature.AuthorizationFeature.builder() + .type(RuleFeature.AuthorizationFeature.Type.AUTHORIZATION) + .name("name") + .build() + ) + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val typescriptCodeParameters = + TypescriptCodeParameters.builder() + .code("code") + .addFeature( + RuleFeature.AuthorizationFeature.builder() + .type(RuleFeature.AuthorizationFeature.Type.AUTHORIZATION) + .name("name") + .build() + ) + .build() + + val roundtrippedTypescriptCodeParameters = + jsonMapper.readValue( + jsonMapper.writeValueAsString(typescriptCodeParameters), + jacksonTypeRef(), + ) + + assertThat(roundtrippedTypescriptCodeParameters).isEqualTo(typescriptCodeParameters) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2RetrieveFeaturesResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2RetrieveFeaturesResponseTest.kt index 2ccca623..d3683d98 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2RetrieveFeaturesResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2RetrieveFeaturesResponseTest.kt @@ -18,17 +18,13 @@ internal class V2RetrieveFeaturesResponseTest { .addFeature( V2RetrieveFeaturesResponse.SpendFeatureState.builder() .filters( - V2RetrieveFeaturesResponse.SpendFeatureState.VelocityLimitFilters - .builder() + VelocityLimitFilters.builder() .addExcludeCountry("USD") .addExcludeMcc("5542") .addIncludeCountry("USD") .addIncludeMcc("5542") .addIncludePanEntryMode( - V2RetrieveFeaturesResponse.SpendFeatureState - .VelocityLimitFilters - .IncludePanEntryMode - .AUTO_ENTRY + VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY ) .build() ) @@ -55,15 +51,13 @@ internal class V2RetrieveFeaturesResponseTest { .containsExactly( V2RetrieveFeaturesResponse.SpendFeatureState.builder() .filters( - V2RetrieveFeaturesResponse.SpendFeatureState.VelocityLimitFilters.builder() + VelocityLimitFilters.builder() .addExcludeCountry("USD") .addExcludeMcc("5542") .addIncludeCountry("USD") .addIncludeMcc("5542") .addIncludePanEntryMode( - V2RetrieveFeaturesResponse.SpendFeatureState.VelocityLimitFilters - .IncludePanEntryMode - .AUTO_ENTRY + VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY ) .build() ) @@ -93,17 +87,13 @@ internal class V2RetrieveFeaturesResponseTest { .addFeature( V2RetrieveFeaturesResponse.SpendFeatureState.builder() .filters( - V2RetrieveFeaturesResponse.SpendFeatureState.VelocityLimitFilters - .builder() + VelocityLimitFilters.builder() .addExcludeCountry("USD") .addExcludeMcc("5542") .addIncludeCountry("USD") .addIncludeMcc("5542") .addIncludePanEntryMode( - V2RetrieveFeaturesResponse.SpendFeatureState - .VelocityLimitFilters - .IncludePanEntryMode - .AUTO_ENTRY + VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY ) .build() ) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitFiltersTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitFiltersTest.kt new file mode 100644 index 00000000..c1b64552 --- /dev/null +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitFiltersTest.kt @@ -0,0 +1,52 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.lithic.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.lithic.api.core.jsonMapper +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class VelocityLimitFiltersTest { + + @Test + fun create() { + val velocityLimitFilters = + VelocityLimitFilters.builder() + .addExcludeCountry("USD") + .addExcludeMcc("5542") + .addIncludeCountry("USD") + .addIncludeMcc("5542") + .addIncludePanEntryMode(VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY) + .build() + + assertThat(velocityLimitFilters.excludeCountries().getOrNull()).containsExactly("USD") + assertThat(velocityLimitFilters.excludeMccs().getOrNull()).containsExactly("5542") + assertThat(velocityLimitFilters.includeCountries().getOrNull()).containsExactly("USD") + assertThat(velocityLimitFilters.includeMccs().getOrNull()).containsExactly("5542") + assertThat(velocityLimitFilters.includePanEntryModes().getOrNull()) + .containsExactly(VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val velocityLimitFilters = + VelocityLimitFilters.builder() + .addExcludeCountry("USD") + .addExcludeMcc("5542") + .addIncludeCountry("USD") + .addIncludeMcc("5542") + .addIncludePanEntryMode(VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY) + .build() + + val roundtrippedVelocityLimitFilters = + jsonMapper.readValue( + jsonMapper.writeValueAsString(velocityLimitFilters), + jacksonTypeRef(), + ) + + assertThat(roundtrippedVelocityLimitFilters).isEqualTo(velocityLimitFilters) + } +} diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitParamsTest.kt index 7d219a89..91d3b146 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/VelocityLimitParamsTest.kt @@ -21,14 +21,12 @@ internal class VelocityLimitParamsTest { ) .scope(VelocityLimitParams.VelocityScope.CARD) .filters( - VelocityLimitParams.VelocityLimitFilters.builder() + VelocityLimitFilters.builder() .addExcludeCountry("USD") .addExcludeMcc("5542") .addIncludeCountry("USD") .addIncludeMcc("5542") - .addIncludePanEntryMode( - VelocityLimitParams.VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY - ) + .addIncludePanEntryMode(VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY) .build() ) .limitAmount(10000L) @@ -47,14 +45,12 @@ internal class VelocityLimitParamsTest { assertThat(velocityLimitParams.scope()).isEqualTo(VelocityLimitParams.VelocityScope.CARD) assertThat(velocityLimitParams.filters()) .contains( - VelocityLimitParams.VelocityLimitFilters.builder() + VelocityLimitFilters.builder() .addExcludeCountry("USD") .addExcludeMcc("5542") .addIncludeCountry("USD") .addIncludeMcc("5542") - .addIncludePanEntryMode( - VelocityLimitParams.VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY - ) + .addIncludePanEntryMode(VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY) .build() ) assertThat(velocityLimitParams.limitAmount()).contains(10000L) @@ -74,14 +70,12 @@ internal class VelocityLimitParamsTest { ) .scope(VelocityLimitParams.VelocityScope.CARD) .filters( - VelocityLimitParams.VelocityLimitFilters.builder() + VelocityLimitFilters.builder() .addExcludeCountry("USD") .addExcludeMcc("5542") .addIncludeCountry("USD") .addIncludeMcc("5542") - .addIncludePanEntryMode( - VelocityLimitParams.VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY - ) + .addIncludePanEntryMode(VelocityLimitFilters.IncludePanEntryMode.AUTO_ENTRY) .build() ) .limitAmount(10000L) From 1e30690af36ee4c265fd3e772680ee3bf8878091 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 08:18:59 +0000 Subject: [PATCH 04/10] fix(api): Disable MCP server to fix TypeScript SDK package publishing --- .stats.yml | 2 +- README.md | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/.stats.yml b/.stats.yml index 31c05d97..4e2f0a05 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 189 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-1e902917b2eae41d549957e790eb6b137969e451efe673815647deba330fe05a.yml openapi_spec_hash: 82cab06ce65462e60316939db630460a -config_hash: 00b60697e692f86b5be297d939962921 +config_hash: 8799cfd589579f105ef8696a6d664c71 diff --git a/README.md b/README.md index cd00fb36..cffe4d66 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,6 @@ The Lithic Java SDK provides convenient access to the [Lithic REST API](https:// The Lithic Java SDK is similar to the Lithic Kotlin SDK but with minor differences that make it more ergonomic for use in Java, such as `Optional` instead of nullable values, `Stream` instead of `Sequence`, and `CompletableFuture` instead of suspend functions. -## MCP Server - -Use the Lithic MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. - -[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=lithic-mcp&config=eyJuYW1lIjoibGl0aGljLW1jcCIsInRyYW5zcG9ydCI6Imh0dHAiLCJ1cmwiOiJodHRwczovL2xpdGhpYy5zdGxtY3AuY29tIiwiaGVhZGVycyI6eyJ4LWxpdGhpYy1hcGkta2V5IjoiTXkgTGl0aGljIEFQSSBLZXkifX0) -[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22lithic-mcp%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Flithic.stlmcp.com%22%2C%22headers%22%3A%7B%22x-lithic-api-key%22%3A%22My%20Lithic%20API%20Key%22%7D%7D) - -> Note: You may need to set environment variables in your MCP client. - The REST API documentation can be found on [docs.lithic.com](https://docs.lithic.com). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.lithic.api/lithic-java/0.119.0). From 42c61b6534cff16b5e45a4b8ca15f5e8e3f4dacd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 14:18:59 +0000 Subject: [PATCH 05/10] fix(client): incorrect `Retry-After` parsing --- .../api/core/http/RetryingHttpClient.kt | 2 +- .../api/core/http/RetryingHttpClientTest.kt | 224 +++++++++++++++--- 2 files changed, 192 insertions(+), 34 deletions(-) diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/core/http/RetryingHttpClient.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/core/http/RetryingHttpClient.kt index 733b9370..1a3efdc5 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/core/http/RetryingHttpClient.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/core/http/RetryingHttpClient.kt @@ -201,7 +201,7 @@ private constructor( ?: headers.values("Retry-After").getOrNull(0)?.let { retryAfter -> retryAfter.toFloatOrNull()?.times(TimeUnit.SECONDS.toNanos(1)) ?: try { - ChronoUnit.MILLIS.between( + ChronoUnit.NANOS.between( OffsetDateTime.now(clock), OffsetDateTime.parse( retryAfter, diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/core/http/RetryingHttpClientTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/core/http/RetryingHttpClientTest.kt index 58cde824..9da44782 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/core/http/RetryingHttpClientTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/core/http/RetryingHttpClientTest.kt @@ -20,7 +20,11 @@ import com.lithic.api.core.RequestOptions import com.lithic.api.core.Sleeper import com.lithic.api.errors.LithicRetryableException import java.io.InputStream +import java.time.Clock import java.time.Duration +import java.time.OffsetDateTime +import java.time.ZoneOffset +import java.time.format.DateTimeFormatter import java.util.concurrent.CompletableFuture import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.BeforeEach @@ -36,6 +40,21 @@ internal class RetryingHttpClientTest { private lateinit var baseUrl: String private lateinit var httpClient: HttpClient + private class RecordingSleeper : Sleeper { + val durations = mutableListOf() + + override fun sleep(duration: Duration) { + durations.add(duration) + } + + override fun sleepAsync(duration: Duration): CompletableFuture { + durations.add(duration) + return CompletableFuture.completedFuture(null) + } + + override fun close() {} + } + @BeforeEach fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) { baseUrl = wmRuntimeInfo.httpBaseUrl @@ -86,7 +105,8 @@ internal class RetryingHttpClientTest { @ValueSource(booleans = [false, true]) fun execute(async: Boolean) { stubFor(post(urlPathEqualTo("/something")).willReturn(ok())) - val retryingClient = retryingHttpClientBuilder().build() + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).build() val response = retryingClient.execute( @@ -100,6 +120,7 @@ internal class RetryingHttpClientTest { assertThat(response.statusCode()).isEqualTo(200) verify(1, postRequestedFor(urlPathEqualTo("/something"))) + assertThat(sleeper.durations).isEmpty() assertNoResponseLeaks() } @@ -111,8 +132,12 @@ internal class RetryingHttpClientTest { .withHeader("X-Some-Header", matching("stainless-java-retry-.+")) .willReturn(ok()) ) + val sleeper = RecordingSleeper() val retryingClient = - retryingHttpClientBuilder().maxRetries(2).idempotencyHeader("X-Some-Header").build() + retryingHttpClientBuilder(sleeper) + .maxRetries(2) + .idempotencyHeader("X-Some-Header") + .build() val response = retryingClient.execute( @@ -126,20 +151,20 @@ internal class RetryingHttpClientTest { assertThat(response.statusCode()).isEqualTo(200) verify(1, postRequestedFor(urlPathEqualTo("/something"))) + assertThat(sleeper.durations).isEmpty() assertNoResponseLeaks() } @ParameterizedTest @ValueSource(booleans = [false, true]) fun execute_withRetryAfterHeader(async: Boolean) { + val retryAfterDate = "Wed, 21 Oct 2015 07:28:00 GMT" stubFor( post(urlPathEqualTo("/something")) // First we fail with a retry after header given as a date .inScenario("foo") .whenScenarioStateIs(Scenario.STARTED) - .willReturn( - serviceUnavailable().withHeader("Retry-After", "Wed, 21 Oct 2015 07:28:00 GMT") - ) + .willReturn(serviceUnavailable().withHeader("Retry-After", retryAfterDate)) .willSetStateTo("RETRY_AFTER_DATE") ) stubFor( @@ -158,7 +183,13 @@ internal class RetryingHttpClientTest { .willReturn(ok()) .willSetStateTo("COMPLETED") ) - val retryingClient = retryingHttpClientBuilder().maxRetries(2).build() + // Fix the clock to 5 seconds before the Retry-After date so the date-based backoff is + // deterministic. + val retryAfterDateTime = + OffsetDateTime.parse(retryAfterDate, DateTimeFormatter.RFC_1123_DATE_TIME) + val clock = Clock.fixed(retryAfterDateTime.minusSeconds(5).toInstant(), ZoneOffset.UTC) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper, clock).maxRetries(2).build() val response = retryingClient.execute( @@ -186,19 +217,20 @@ internal class RetryingHttpClientTest { postRequestedFor(urlPathEqualTo("/something")) .withHeader("x-stainless-retry-count", equalTo("2")), ) + assertThat(sleeper.durations) + .containsExactly(Duration.ofSeconds(5), Duration.ofMillis(1234)) assertNoResponseLeaks() } @ParameterizedTest @ValueSource(booleans = [false, true]) fun execute_withOverwrittenRetryCountHeader(async: Boolean) { + val retryAfterDate = "Wed, 21 Oct 2015 07:28:00 GMT" stubFor( post(urlPathEqualTo("/something")) .inScenario("foo") // first we fail with a retry after header given as a date .whenScenarioStateIs(Scenario.STARTED) - .willReturn( - serviceUnavailable().withHeader("Retry-After", "Wed, 21 Oct 2015 07:28:00 GMT") - ) + .willReturn(serviceUnavailable().withHeader("Retry-After", retryAfterDate)) .willSetStateTo("RETRY_AFTER_DATE") ) stubFor( @@ -208,7 +240,11 @@ internal class RetryingHttpClientTest { .willReturn(ok()) .willSetStateTo("COMPLETED") ) - val retryingClient = retryingHttpClientBuilder().maxRetries(2).build() + val retryAfterDateTime = + OffsetDateTime.parse(retryAfterDate, DateTimeFormatter.RFC_1123_DATE_TIME) + val clock = Clock.fixed(retryAfterDateTime.minusSeconds(5).toInstant(), ZoneOffset.UTC) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper, clock).maxRetries(2).build() val response = retryingClient.execute( @@ -227,6 +263,7 @@ internal class RetryingHttpClientTest { postRequestedFor(urlPathEqualTo("/something")) .withHeader("x-stainless-retry-count", equalTo("42")), ) + assertThat(sleeper.durations).containsExactly(Duration.ofSeconds(5)) assertNoResponseLeaks() } @@ -247,7 +284,8 @@ internal class RetryingHttpClientTest { .willReturn(ok()) .willSetStateTo("COMPLETED") ) - val retryingClient = retryingHttpClientBuilder().maxRetries(1).build() + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).maxRetries(1).build() val response = retryingClient.execute( @@ -261,6 +299,7 @@ internal class RetryingHttpClientTest { assertThat(response.statusCode()).isEqualTo(200) verify(2, postRequestedFor(urlPathEqualTo("/something"))) + assertThat(sleeper.durations).containsExactly(Duration.ofMillis(10)) assertNoResponseLeaks() } @@ -301,21 +340,12 @@ internal class RetryingHttpClientTest { override fun close() = httpClient.close() } + val sleeper = RecordingSleeper() val retryingClient = RetryingHttpClient.builder() .httpClient(failingHttpClient) .maxRetries(2) - .sleeper( - object : Sleeper { - - override fun sleep(duration: Duration) {} - - override fun sleepAsync(duration: Duration): CompletableFuture = - CompletableFuture.completedFuture(null) - - override fun close() {} - } - ) + .sleeper(sleeper) .build() val response = @@ -339,25 +369,153 @@ internal class RetryingHttpClientTest { postRequestedFor(urlPathEqualTo("/something")) .withHeader("x-stainless-retry-count", equalTo("0")), ) + // Exponential backoff with jitter: 0.5s * jitter where jitter is in [0.75, 1.0]. + assertThat(sleeper.durations).hasSize(1) + assertThat(sleeper.durations[0]).isBetween(Duration.ofMillis(375), Duration.ofMillis(500)) assertNoResponseLeaks() } - private fun retryingHttpClientBuilder() = - RetryingHttpClient.builder() - .httpClient(httpClient) - // Use a no-op `Sleeper` to make the test fast. - .sleeper( - object : Sleeper { + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withExponentialBackoff(async: Boolean) { + stubFor(post(urlPathEqualTo("/something")).willReturn(serviceUnavailable())) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).maxRetries(3).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) - override fun sleep(duration: Duration) {} + // All retries exhausted; the last 503 response is returned. + assertThat(response.statusCode()).isEqualTo(503) + verify(4, postRequestedFor(urlPathEqualTo("/something"))) + // Exponential backoff with jitter: backoff = min(0.5 * 2^(retries-1), 8) * jitter where + // jitter is in [0.75, 1.0]. + assertThat(sleeper.durations).hasSize(3) + // retries=1: 0.5s * [0.75, 1.0] + assertThat(sleeper.durations[0]).isBetween(Duration.ofMillis(375), Duration.ofMillis(500)) + // retries=2: 1.0s * [0.75, 1.0] + assertThat(sleeper.durations[1]).isBetween(Duration.ofMillis(750), Duration.ofMillis(1000)) + // retries=3: 2.0s * [0.75, 1.0] + assertThat(sleeper.durations[2]).isBetween(Duration.ofMillis(1500), Duration.ofMillis(2000)) + assertNoResponseLeaks() + } - override fun sleepAsync(duration: Duration): CompletableFuture = - CompletableFuture.completedFuture(null) + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withExponentialBackoffCap(async: Boolean) { + stubFor(post(urlPathEqualTo("/something")).willReturn(serviceUnavailable())) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).maxRetries(6).build() - override fun close() {} - } + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, ) + assertThat(response.statusCode()).isEqualTo(503) + verify(7, postRequestedFor(urlPathEqualTo("/something"))) + assertThat(sleeper.durations).hasSize(6) + // retries=5: min(0.5 * 2^4, 8) = 8.0s * [0.75, 1.0] + assertThat(sleeper.durations[4]).isBetween(Duration.ofMillis(6000), Duration.ofMillis(8000)) + // retries=6: min(0.5 * 2^5, 8) = min(16, 8) = 8.0s * [0.75, 1.0] (capped) + assertThat(sleeper.durations[5]).isBetween(Duration.ofMillis(6000), Duration.ofMillis(8000)) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withRetryAfterMsPriorityOverRetryAfter(async: Boolean) { + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn( + serviceUnavailable() + .withHeader("Retry-After-Ms", "50") + .withHeader("Retry-After", "2") + ) + .willSetStateTo("RETRY") + ) + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") + .whenScenarioStateIs("RETRY") + .willReturn(ok()) + .willSetStateTo("COMPLETED") + ) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).maxRetries(1).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + // Retry-After-Ms (50ms) takes priority over Retry-After (2s). + assertThat(sleeper.durations).containsExactly(Duration.ofMillis(50)) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withRetryAfterUnparseable(async: Boolean) { + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn(serviceUnavailable().withHeader("Retry-After", "not-a-date-or-number")) + .willSetStateTo("RETRY") + ) + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") + .whenScenarioStateIs("RETRY") + .willReturn(ok()) + .willSetStateTo("COMPLETED") + ) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).maxRetries(1).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + // Unparseable Retry-After falls through to exponential backoff. + assertThat(sleeper.durations).hasSize(1) + assertThat(sleeper.durations[0]).isBetween(Duration.ofMillis(375), Duration.ofMillis(500)) + assertNoResponseLeaks() + } + + private fun retryingHttpClientBuilder( + sleeper: RecordingSleeper, + clock: Clock = Clock.systemUTC(), + ) = RetryingHttpClient.builder().httpClient(httpClient).sleeper(sleeper).clock(clock) + private fun HttpClient.execute(request: HttpRequest, async: Boolean): HttpResponse = if (async) executeAsync(request).get() else execute(request) From b79d216cc18514631e585e04478ff35b0d04756e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:17:49 +0000 Subject: [PATCH 06/10] feat(api): Add event_subtype to statement line items --- .stats.yml | 4 +- .../lithic/api/models/StatementLineItems.kt | 53 ++++++++++++++++++- .../api/models/StatementLineItemsTest.kt | 3 ++ 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4e2f0a05..a098ed97 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 189 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-1e902917b2eae41d549957e790eb6b137969e451efe673815647deba330fe05a.yml -openapi_spec_hash: 82cab06ce65462e60316939db630460a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-34cfbf6ee4a6903838da11a879bbbfe71b84e7585b3c8c6957bf524deb378b41.yml +openapi_spec_hash: f9e20ed9f3c5d78a185af18be0d7a199 config_hash: 8799cfd589579f105ef8696a6d664c71 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt index c9207b7d..92b9049e 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt @@ -226,6 +226,7 @@ private constructor( private val financialTransactionToken: JsonField, private val cardToken: JsonField, private val descriptor: JsonField, + private val eventSubtype: JsonField, private val additionalProperties: MutableMap, ) { @@ -263,6 +264,9 @@ private constructor( @JsonProperty("descriptor") @ExcludeMissing descriptor: JsonField = JsonMissing.of(), + @JsonProperty("event_subtype") + @ExcludeMissing + eventSubtype: JsonField = JsonMissing.of(), ) : this( token, amount, @@ -276,6 +280,7 @@ private constructor( financialTransactionToken, cardToken, descriptor, + eventSubtype, mutableMapOf(), ) @@ -372,6 +377,14 @@ private constructor( */ fun descriptor(): Optional = descriptor.getOptional("descriptor") + /** + * Subtype of the event that generated the line items + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun eventSubtype(): Optional = eventSubtype.getOptional("event_subtype") + /** * Returns the raw JSON value of [token]. * @@ -474,6 +487,16 @@ private constructor( @ExcludeMissing fun _descriptor(): JsonField = descriptor + /** + * Returns the raw JSON value of [eventSubtype]. + * + * Unlike [eventSubtype], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("event_subtype") + @ExcludeMissing + fun _eventSubtype(): JsonField = eventSubtype + @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -524,6 +547,7 @@ private constructor( private var financialTransactionToken: JsonField? = null private var cardToken: JsonField = JsonMissing.of() private var descriptor: JsonField = JsonMissing.of() + private var eventSubtype: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -541,6 +565,7 @@ private constructor( financialTransactionToken = statementLineItemResponse.financialTransactionToken cardToken = statementLineItemResponse.cardToken descriptor = statementLineItemResponse.descriptor + eventSubtype = statementLineItemResponse.eventSubtype additionalProperties = statementLineItemResponse.additionalProperties.toMutableMap() } @@ -701,6 +726,25 @@ private constructor( */ fun descriptor(descriptor: JsonField) = apply { this.descriptor = descriptor } + /** Subtype of the event that generated the line items */ + fun eventSubtype(eventSubtype: String?) = + eventSubtype(JsonField.ofNullable(eventSubtype)) + + /** Alias for calling [Builder.eventSubtype] with `eventSubtype.orElse(null)`. */ + fun eventSubtype(eventSubtype: Optional) = + eventSubtype(eventSubtype.getOrNull()) + + /** + * Sets [Builder.eventSubtype] to an arbitrary JSON value. + * + * You should usually call [Builder.eventSubtype] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun eventSubtype(eventSubtype: JsonField) = apply { + this.eventSubtype = eventSubtype + } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -755,6 +799,7 @@ private constructor( checkRequired("financialTransactionToken", financialTransactionToken), cardToken, descriptor, + eventSubtype, additionalProperties.toMutableMap(), ) } @@ -778,6 +823,7 @@ private constructor( financialTransactionToken() cardToken() descriptor() + eventSubtype() validated = true } @@ -808,7 +854,8 @@ private constructor( (if (financialTransactionEventToken.asKnown().isPresent) 1 else 0) + (if (financialTransactionToken.asKnown().isPresent) 1 else 0) + (if (cardToken.asKnown().isPresent) 1 else 0) + - (if (descriptor.asKnown().isPresent) 1 else 0) + (if (descriptor.asKnown().isPresent) 1 else 0) + + (if (eventSubtype.asKnown().isPresent) 1 else 0) class TransactionCategory @JsonCreator @@ -1720,6 +1767,7 @@ private constructor( financialTransactionToken == other.financialTransactionToken && cardToken == other.cardToken && descriptor == other.descriptor && + eventSubtype == other.eventSubtype && additionalProperties == other.additionalProperties } @@ -1737,6 +1785,7 @@ private constructor( financialTransactionToken, cardToken, descriptor, + eventSubtype, additionalProperties, ) } @@ -1744,7 +1793,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "StatementLineItemResponse{token=$token, amount=$amount, category=$category, created=$created, currency=$currency, effectiveDate=$effectiveDate, eventType=$eventType, financialAccountToken=$financialAccountToken, financialTransactionEventToken=$financialTransactionEventToken, financialTransactionToken=$financialTransactionToken, cardToken=$cardToken, descriptor=$descriptor, additionalProperties=$additionalProperties}" + "StatementLineItemResponse{token=$token, amount=$amount, category=$category, created=$created, currency=$currency, effectiveDate=$effectiveDate, eventType=$eventType, financialAccountToken=$financialAccountToken, financialTransactionEventToken=$financialTransactionEventToken, financialTransactionToken=$financialTransactionToken, cardToken=$cardToken, descriptor=$descriptor, eventSubtype=$eventSubtype, additionalProperties=$additionalProperties}" } override fun equals(other: Any?): Boolean { diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/StatementLineItemsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/StatementLineItemsTest.kt index ece39b04..53d551cc 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/StatementLineItemsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/StatementLineItemsTest.kt @@ -34,6 +34,7 @@ internal class StatementLineItemsTest { .financialTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .cardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .descriptor("descriptor") + .eventSubtype("event_subtype") .build() ) .hasMore(true) @@ -57,6 +58,7 @@ internal class StatementLineItemsTest { .financialTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .cardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .descriptor("descriptor") + .eventSubtype("event_subtype") .build() ) assertThat(statementLineItems.hasMore()).isEqualTo(true) @@ -86,6 +88,7 @@ internal class StatementLineItemsTest { .financialTransactionToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .cardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .descriptor("descriptor") + .eventSubtype("event_subtype") .build() ) .hasMore(true) From be3f3fb90c7492fc1a6707f217c4fc1bf8e45211 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:01:01 +0000 Subject: [PATCH 07/10] feat(api): add loan_tape_date field to statement line items --- .stats.yml | 4 +- .../lithic/api/models/StatementLineItems.kt | 53 ++++++++++++++++++- .../api/models/StatementLineItemsTest.kt | 3 ++ 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index a098ed97..2f0500f7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 189 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-34cfbf6ee4a6903838da11a879bbbfe71b84e7585b3c8c6957bf524deb378b41.yml -openapi_spec_hash: f9e20ed9f3c5d78a185af18be0d7a199 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-fb9adae9eb94be3d04c66cc6c974cb0cc010d9d3a49e6fe23c32276e4317b568.yml +openapi_spec_hash: 8da1862112b00c8a0c9e19b2e83c89d8 config_hash: 8799cfd589579f105ef8696a6d664c71 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt index 92b9049e..06320240 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/StatementLineItems.kt @@ -227,6 +227,7 @@ private constructor( private val cardToken: JsonField, private val descriptor: JsonField, private val eventSubtype: JsonField, + private val loanTapeDate: JsonField, private val additionalProperties: MutableMap, ) { @@ -267,6 +268,9 @@ private constructor( @JsonProperty("event_subtype") @ExcludeMissing eventSubtype: JsonField = JsonMissing.of(), + @JsonProperty("loan_tape_date") + @ExcludeMissing + loanTapeDate: JsonField = JsonMissing.of(), ) : this( token, amount, @@ -281,6 +285,7 @@ private constructor( cardToken, descriptor, eventSubtype, + loanTapeDate, mutableMapOf(), ) @@ -385,6 +390,14 @@ private constructor( */ fun eventSubtype(): Optional = eventSubtype.getOptional("event_subtype") + /** + * Date of the loan tape that generated this line item + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun loanTapeDate(): Optional = loanTapeDate.getOptional("loan_tape_date") + /** * Returns the raw JSON value of [token]. * @@ -497,6 +510,16 @@ private constructor( @ExcludeMissing fun _eventSubtype(): JsonField = eventSubtype + /** + * Returns the raw JSON value of [loanTapeDate]. + * + * Unlike [loanTapeDate], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("loan_tape_date") + @ExcludeMissing + fun _loanTapeDate(): JsonField = loanTapeDate + @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -548,6 +571,7 @@ private constructor( private var cardToken: JsonField = JsonMissing.of() private var descriptor: JsonField = JsonMissing.of() private var eventSubtype: JsonField = JsonMissing.of() + private var loanTapeDate: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -566,6 +590,7 @@ private constructor( cardToken = statementLineItemResponse.cardToken descriptor = statementLineItemResponse.descriptor eventSubtype = statementLineItemResponse.eventSubtype + loanTapeDate = statementLineItemResponse.loanTapeDate additionalProperties = statementLineItemResponse.additionalProperties.toMutableMap() } @@ -745,6 +770,25 @@ private constructor( this.eventSubtype = eventSubtype } + /** Date of the loan tape that generated this line item */ + fun loanTapeDate(loanTapeDate: LocalDate?) = + loanTapeDate(JsonField.ofNullable(loanTapeDate)) + + /** Alias for calling [Builder.loanTapeDate] with `loanTapeDate.orElse(null)`. */ + fun loanTapeDate(loanTapeDate: Optional) = + loanTapeDate(loanTapeDate.getOrNull()) + + /** + * Sets [Builder.loanTapeDate] to an arbitrary JSON value. + * + * You should usually call [Builder.loanTapeDate] with a well-typed [LocalDate] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun loanTapeDate(loanTapeDate: JsonField) = apply { + this.loanTapeDate = loanTapeDate + } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -800,6 +844,7 @@ private constructor( cardToken, descriptor, eventSubtype, + loanTapeDate, additionalProperties.toMutableMap(), ) } @@ -824,6 +869,7 @@ private constructor( cardToken() descriptor() eventSubtype() + loanTapeDate() validated = true } @@ -855,7 +901,8 @@ private constructor( (if (financialTransactionToken.asKnown().isPresent) 1 else 0) + (if (cardToken.asKnown().isPresent) 1 else 0) + (if (descriptor.asKnown().isPresent) 1 else 0) + - (if (eventSubtype.asKnown().isPresent) 1 else 0) + (if (eventSubtype.asKnown().isPresent) 1 else 0) + + (if (loanTapeDate.asKnown().isPresent) 1 else 0) class TransactionCategory @JsonCreator @@ -1768,6 +1815,7 @@ private constructor( cardToken == other.cardToken && descriptor == other.descriptor && eventSubtype == other.eventSubtype && + loanTapeDate == other.loanTapeDate && additionalProperties == other.additionalProperties } @@ -1786,6 +1834,7 @@ private constructor( cardToken, descriptor, eventSubtype, + loanTapeDate, additionalProperties, ) } @@ -1793,7 +1842,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "StatementLineItemResponse{token=$token, amount=$amount, category=$category, created=$created, currency=$currency, effectiveDate=$effectiveDate, eventType=$eventType, financialAccountToken=$financialAccountToken, financialTransactionEventToken=$financialTransactionEventToken, financialTransactionToken=$financialTransactionToken, cardToken=$cardToken, descriptor=$descriptor, eventSubtype=$eventSubtype, additionalProperties=$additionalProperties}" + "StatementLineItemResponse{token=$token, amount=$amount, category=$category, created=$created, currency=$currency, effectiveDate=$effectiveDate, eventType=$eventType, financialAccountToken=$financialAccountToken, financialTransactionEventToken=$financialTransactionEventToken, financialTransactionToken=$financialTransactionToken, cardToken=$cardToken, descriptor=$descriptor, eventSubtype=$eventSubtype, loanTapeDate=$loanTapeDate, additionalProperties=$additionalProperties}" } override fun equals(other: Any?): Boolean { diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/StatementLineItemsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/StatementLineItemsTest.kt index 53d551cc..ed63494b 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/StatementLineItemsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/StatementLineItemsTest.kt @@ -35,6 +35,7 @@ internal class StatementLineItemsTest { .cardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .descriptor("descriptor") .eventSubtype("event_subtype") + .loanTapeDate(LocalDate.parse("2019-12-27")) .build() ) .hasMore(true) @@ -59,6 +60,7 @@ internal class StatementLineItemsTest { .cardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .descriptor("descriptor") .eventSubtype("event_subtype") + .loanTapeDate(LocalDate.parse("2019-12-27")) .build() ) assertThat(statementLineItems.hasMore()).isEqualTo(true) @@ -89,6 +91,7 @@ internal class StatementLineItemsTest { .cardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .descriptor("descriptor") .eventSubtype("event_subtype") + .loanTapeDate(LocalDate.parse("2019-12-27")) .build() ) .hasMore(true) From b8cb9ccdd1e1474b986e06ff44baf41ff45e4576 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:05:28 +0000 Subject: [PATCH 08/10] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 2f0500f7..1cd7cb5c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 189 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-fb9adae9eb94be3d04c66cc6c974cb0cc010d9d3a49e6fe23c32276e4317b568.yml openapi_spec_hash: 8da1862112b00c8a0c9e19b2e83c89d8 -config_hash: 8799cfd589579f105ef8696a6d664c71 +config_hash: 7daa8d0d03697920c0c1ca18ce6d4594 From de8c71325409c0b70285dba8100289872d835c72 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:33:38 +0000 Subject: [PATCH 09/10] feat(api): Add support for early direct deposit --- .stats.yml | 4 ++-- .../src/main/kotlin/com/lithic/api/models/Payment.kt | 12 ++++++++++++ .../lithic/api/models/PaymentSimulateActionParams.kt | 6 ++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1cd7cb5c..cb037391 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 189 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-fb9adae9eb94be3d04c66cc6c974cb0cc010d9d3a49e6fe23c32276e4317b568.yml -openapi_spec_hash: 8da1862112b00c8a0c9e19b2e83c89d8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-6eebc524f3f5b6499a79ef544e150cc49ea1dc1e1c76a5392079ca5a83e78100.yml +openapi_spec_hash: 500c46c1194a128c404e17f7a5bff676 config_hash: 7daa8d0d03697920c0c1ca18ce6d4594 diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt index 558ed9ec..1c900b2c 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Payment.kt @@ -1521,6 +1521,8 @@ private constructor( * * `ACH_RECEIPT_PROCESSED` - ACH receipt pending release from an ACH holder. * * `ACH_RECEIPT_SETTLED` - ACH receipt funds have settled. * * `ACH_RECEIPT_RELEASED` - ACH receipt released from pending to available balance. + * * `ACH_RECEIPT_RELEASED_EARLY` - ACH receipt released early from pending to available + * balance. * * `ACH_RETURN_INITIATED` - ACH initiated return for an ACH receipt. * * `ACH_RETURN_PROCESSED` - ACH receipt returned by the Receiving Depository Financial * Institution. @@ -1728,6 +1730,8 @@ private constructor( * * `ACH_RECEIPT_PROCESSED` - ACH receipt pending release from an ACH holder. * * `ACH_RECEIPT_SETTLED` - ACH receipt funds have settled. * * `ACH_RECEIPT_RELEASED` - ACH receipt released from pending to available balance. + * * `ACH_RECEIPT_RELEASED_EARLY` - ACH receipt released early from pending to available + * balance. * * `ACH_RETURN_INITIATED` - ACH initiated return for an ACH receipt. * * `ACH_RETURN_PROCESSED` - ACH receipt returned by the Receiving Depository Financial * Institution. @@ -2027,6 +2031,8 @@ private constructor( * * `ACH_RECEIPT_PROCESSED` - ACH receipt pending release from an ACH holder. * * `ACH_RECEIPT_SETTLED` - ACH receipt funds have settled. * * `ACH_RECEIPT_RELEASED` - ACH receipt released from pending to available balance. + * * `ACH_RECEIPT_RELEASED_EARLY` - ACH receipt released early from pending to available + * balance. * * `ACH_RETURN_INITIATED` - ACH initiated return for an ACH receipt. * * `ACH_RETURN_PROCESSED` - ACH receipt returned by the Receiving Depository Financial * Institution. @@ -2069,6 +2075,8 @@ private constructor( @JvmField val ACH_RECEIPT_RELEASED = of("ACH_RECEIPT_RELEASED") + @JvmField val ACH_RECEIPT_RELEASED_EARLY = of("ACH_RECEIPT_RELEASED_EARLY") + @JvmField val ACH_RECEIPT_SETTLED = of("ACH_RECEIPT_SETTLED") @JvmField val ACH_RETURN_INITIATED = of("ACH_RETURN_INITIATED") @@ -2093,6 +2101,7 @@ private constructor( ACH_ORIGINATION_SETTLED, ACH_RECEIPT_PROCESSED, ACH_RECEIPT_RELEASED, + ACH_RECEIPT_RELEASED_EARLY, ACH_RECEIPT_SETTLED, ACH_RETURN_INITIATED, ACH_RETURN_PROCESSED, @@ -2120,6 +2129,7 @@ private constructor( ACH_ORIGINATION_SETTLED, ACH_RECEIPT_PROCESSED, ACH_RECEIPT_RELEASED, + ACH_RECEIPT_RELEASED_EARLY, ACH_RECEIPT_SETTLED, ACH_RETURN_INITIATED, ACH_RETURN_PROCESSED, @@ -2150,6 +2160,7 @@ private constructor( ACH_ORIGINATION_SETTLED -> Value.ACH_ORIGINATION_SETTLED ACH_RECEIPT_PROCESSED -> Value.ACH_RECEIPT_PROCESSED ACH_RECEIPT_RELEASED -> Value.ACH_RECEIPT_RELEASED + ACH_RECEIPT_RELEASED_EARLY -> Value.ACH_RECEIPT_RELEASED_EARLY ACH_RECEIPT_SETTLED -> Value.ACH_RECEIPT_SETTLED ACH_RETURN_INITIATED -> Value.ACH_RETURN_INITIATED ACH_RETURN_PROCESSED -> Value.ACH_RETURN_PROCESSED @@ -2178,6 +2189,7 @@ private constructor( ACH_ORIGINATION_SETTLED -> Known.ACH_ORIGINATION_SETTLED ACH_RECEIPT_PROCESSED -> Known.ACH_RECEIPT_PROCESSED ACH_RECEIPT_RELEASED -> Known.ACH_RECEIPT_RELEASED + ACH_RECEIPT_RELEASED_EARLY -> Known.ACH_RECEIPT_RELEASED_EARLY ACH_RECEIPT_SETTLED -> Known.ACH_RECEIPT_SETTLED ACH_RETURN_INITIATED -> Known.ACH_RETURN_INITIATED ACH_RETURN_PROCESSED -> Known.ACH_RETURN_PROCESSED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentSimulateActionParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentSimulateActionParams.kt index 2773a6b0..c82e62c0 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentSimulateActionParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/PaymentSimulateActionParams.kt @@ -773,6 +773,8 @@ private constructor( @JvmField val ACH_RECEIPT_RELEASED = of("ACH_RECEIPT_RELEASED") + @JvmField val ACH_RECEIPT_RELEASED_EARLY = of("ACH_RECEIPT_RELEASED_EARLY") + @JvmField val ACH_RETURN_INITIATED = of("ACH_RETURN_INITIATED") @JvmField val ACH_RETURN_PROCESSED = of("ACH_RETURN_PROCESSED") @@ -790,6 +792,7 @@ private constructor( ACH_ORIGINATION_SETTLED, ACH_RECEIPT_SETTLED, ACH_RECEIPT_RELEASED, + ACH_RECEIPT_RELEASED_EARLY, ACH_RETURN_INITIATED, ACH_RETURN_PROCESSED, ACH_RETURN_SETTLED, @@ -813,6 +816,7 @@ private constructor( ACH_ORIGINATION_SETTLED, ACH_RECEIPT_SETTLED, ACH_RECEIPT_RELEASED, + ACH_RECEIPT_RELEASED_EARLY, ACH_RETURN_INITIATED, ACH_RETURN_PROCESSED, ACH_RETURN_SETTLED, @@ -838,6 +842,7 @@ private constructor( ACH_ORIGINATION_SETTLED -> Value.ACH_ORIGINATION_SETTLED ACH_RECEIPT_SETTLED -> Value.ACH_RECEIPT_SETTLED ACH_RECEIPT_RELEASED -> Value.ACH_RECEIPT_RELEASED + ACH_RECEIPT_RELEASED_EARLY -> Value.ACH_RECEIPT_RELEASED_EARLY ACH_RETURN_INITIATED -> Value.ACH_RETURN_INITIATED ACH_RETURN_PROCESSED -> Value.ACH_RETURN_PROCESSED ACH_RETURN_SETTLED -> Value.ACH_RETURN_SETTLED @@ -861,6 +866,7 @@ private constructor( ACH_ORIGINATION_SETTLED -> Known.ACH_ORIGINATION_SETTLED ACH_RECEIPT_SETTLED -> Known.ACH_RECEIPT_SETTLED ACH_RECEIPT_RELEASED -> Known.ACH_RECEIPT_RELEASED + ACH_RECEIPT_RELEASED_EARLY -> Known.ACH_RECEIPT_RELEASED_EARLY ACH_RETURN_INITIATED -> Known.ACH_RETURN_INITIATED ACH_RETURN_PROCESSED -> Known.ACH_RETURN_PROCESSED ACH_RETURN_SETTLED -> Known.ACH_RETURN_SETTLED From 508064cf535ebe2bf11920f1b888503d0a3262fc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 10 Mar 2026 17:34:09 +0000 Subject: [PATCH 10/10] release: 0.120.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 23 +++++++++++++++++++++++ README.md | 10 +++++----- build.gradle.kts | 2 +- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 124b9841..486a203f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.119.0" + ".": "0.120.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index afbe3e6a..9f98b865 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 0.120.0 (2026-03-10) + +Full Changelog: [v0.119.0...v0.120.0](https://github.com/lithic-com/lithic-java/compare/v0.119.0...v0.120.0) + +### Features + +* **api:** add EARLY_DIRECT_DEPOSIT_FLOAT type to financial account ([e333879](https://github.com/lithic-com/lithic-java/commit/e333879612c488e74effb36cca27da4fe9ed134f)) +* **api:** Add event_subtype to statement line items ([b79d216](https://github.com/lithic-com/lithic-java/commit/b79d216cc18514631e585e04478ff35b0d04756e)) +* **api:** add loan_tape_date field to statement line items ([be3f3fb](https://github.com/lithic-com/lithic-java/commit/be3f3fb90c7492fc1a6707f217c4fc1bf8e45211)) +* **api:** Add support for early direct deposit ([de8c713](https://github.com/lithic-com/lithic-java/commit/de8c71325409c0b70285dba8100289872d835c72)) +* **api:** add TypeScript rules, RuleFeature model, draft version state fields ([f57cd63](https://github.com/lithic-com/lithic-java/commit/f57cd63e55e1331e79cd7f4bdea8b64bf5d05582)) + + +### Bug Fixes + +* **api:** Disable MCP server to fix TypeScript SDK package publishing ([1e30690](https://github.com/lithic-com/lithic-java/commit/1e30690af36ee4c265fd3e772680ee3bf8878091)) +* **client:** incorrect `Retry-After` parsing ([42c61b6](https://github.com/lithic-com/lithic-java/commit/42c61b6534cff16b5e45a4b8ca15f5e8e3f4dacd)) + + +### Chores + +* **internal:** codegen related update ([10b1473](https://github.com/lithic-com/lithic-java/commit/10b14732a71e84708c2da1234a47664b19354c97)) + ## 0.119.0 (2026-03-05) Full Changelog: [v0.118.0...v0.119.0](https://github.com/lithic-com/lithic-java/compare/v0.118.0...v0.119.0) diff --git a/README.md b/README.md index cffe4d66..04ebd7e9 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.lithic.api/lithic-java)](https://central.sonatype.com/artifact/com.lithic.api/lithic-java/0.119.0) -[![javadoc](https://javadoc.io/badge2/com.lithic.api/lithic-java/0.119.0/javadoc.svg)](https://javadoc.io/doc/com.lithic.api/lithic-java/0.119.0) +[![Maven Central](https://img.shields.io/maven-central/v/com.lithic.api/lithic-java)](https://central.sonatype.com/artifact/com.lithic.api/lithic-java/0.120.0) +[![javadoc](https://javadoc.io/badge2/com.lithic.api/lithic-java/0.120.0/javadoc.svg)](https://javadoc.io/doc/com.lithic.api/lithic-java/0.120.0) @@ -13,7 +13,7 @@ The Lithic Java SDK is similar to the Lithic Kotlin SDK but with minor differenc -The REST API documentation can be found on [docs.lithic.com](https://docs.lithic.com). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.lithic.api/lithic-java/0.119.0). +The REST API documentation can be found on [docs.lithic.com](https://docs.lithic.com). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.lithic.api/lithic-java/0.120.0). @@ -24,7 +24,7 @@ The REST API documentation can be found on [docs.lithic.com](https://docs.lithic ### Gradle ```kotlin -implementation("com.lithic.api:lithic-java:0.119.0") +implementation("com.lithic.api:lithic-java:0.120.0") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.lithic.api:lithic-java:0.119.0") com.lithic.api lithic-java - 0.119.0 + 0.120.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index 322e98c9..a704d259 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.lithic.api" - version = "0.119.0" // x-release-please-version + version = "0.120.0" // x-release-please-version } subprojects {